Description
A type argument list can be a <selector>
, but only when followed by a "stop token" or "continuation token", which are tokens which conclusively prevent the trailing >
s from being an infix operator. Those are tokens which cannot start an expression, and therefore cannot start the second operand of a >
, >>
or >>>
operator, either because they end or delimit an expression, or because they are themselves infix or suffix, but not prefix, operators which require a first operand.
The continuation list should contain the cascade ..
and ?..
operators, but doesn't.
Those are both operators which require a prior operand, and it's possible to write code which either starts or continues a cascade after a type instantiation. Uncommon, not always useful, but possible. (Read: I hit it.)
It would be consistent to have them, even if it's probably only very rarely needed.
Should also not be a big change, just adding two more tokens to the "continuation token" list, which will only affect the parsing of programs that would otherwise not parse today.
Examples:
extension SpreadArgs2<R, P1, P2> on R Function(P1, P2) {
R apply((P1, P2) arga) => this.call(args.$1, args.$2);
}
void printSome<P1, P2>(P1 v1, P2 v2) {
print("$v1: $v2");
}
void main() {
var pair1 = (0, 1);
var pair2 = (1, 0);
printSome<int, int>..apply(pair1)..apply(pair2);
}
It could happen.
The example I actually hit was while inspecting types:
void main() {
someExpression..st<E<num>>..logValue;
}
extension <T> on T {
void st<X extends E<T>>() {}
void get logValue {
print("$this:$runtimeType @ $T")";
}
}
typedef E<T> = T Function(T);
The instantiated tear-off as a cascade selector has no practical use at runtime, but it does force a static type-check.
(Not a big loss that I have to add ()
afterwards in this case, but also not necessary or consistent.)