Description
openedon Aug 6, 2018
After exploring the concept in #23696, we've come to the conclusion that implicitly making type arguments available by name would unnecessarily expose previously unobservable implementation details. As such, I'll be breaking that proposal down into two parts. One is just the partial inference (which is here), which can stand on its own, as discussed in #20122 and #10571.
To recap, partial type argument inference is the idea that some number of type arguments in a type argument list may be provided, while others are elided and fulfilled via inference using the rest. Specifically, in #10571 a number of different syntax proposals will brought forward:
For the following examples, assume we have a
declare foo<A,B,C>(): [A, B, C];
Variant 1 - elided entries
foo<,,string>(); // returns [{}, {}, string]
This is the most terse option, as simply the lack of inputs implies inference sites. This would almost seem to logically follow from how not providing a list also causes inference to occur at all sites. This does have issues, however: specifying a final parameter as needing inference would require a trailing ,
in the list (something we currently explicitly disallow), and lists could very easily become confusing, as a ,
is very easy to skip over.
Variant 2 - Sigil marker
foo<*, *, string>(); // returns [{}, {}, string]
As the second most terse option, this also has appeal; however I think it also fails on a few points. First, *
is non-obvious what it means; it implies a "wildcard" of some kind, but in the context of types that could mean an inferred type, a bound, or an existential. Second, as a single-character sigil, we're unlikely to meaningfully provide completions for it even though it is contextually relevant. Finally, we're considering other work to do with existentials and generated type parameters in the future which we'd like to be able to use the *
as an indicator for.
Variant 3 - Keyword marker
a. auto
foo<auto, auto, string>(); // returns [{}, {}, string]
b. infer
foo<infer, infer, string>(); // returns [{}, {}, string]
Neither of these are as terse as the others, but both are still likely substantially shorter than providing the entire list of types by hand in situations where partial inference is desired. Of the two keywords, auto
may be shorter, but currently carries no meaning within the language. infer
on the other hand is already used for marking inference positions within conditional types. The infer
method was explored in #22368, however was taken much father - almost fully replicating the arbitrary placement and naming the operator affords within conditional types.
In the end, I'm advocating for variant 3b - the infer
placeholder, with none of the extra features afforded in #22368 (we can always add them later if there is demand).