-
Notifications
You must be signed in to change notification settings - Fork 211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
With constructors in static extensions, do we resolve them using type arguments? #4049
Comments
(May also apply to static extension constructor tear-offs! #3876.) |
I would prefer to match non-static extensions as much as possible/reasonable. That would only apply to constructors, since static extension members ignore type arguments. (But they should probably not apply to a type literal with type arguments.) It is also important that a generative constructor returns a precise type. That means that "valid for the ... So an explicit For explicit type arguments, that's "easy". We do not want to perform type inference on constructor arguments more than once. Or effectively introduce overloading based on arguments. (But may be non-trivial if your parameters are not trivial, fx static extension <T> on List<List<T>> {
List.nest() : this.filled(<T>[]);
}
Iterable<Iterable<int>> _ =
List.nest(); If we can infer So, yes. Do use type arguments to static extensions to decide if a constructor applies. (Tear-offs may or may not be even more problematic, since the context type does include parameter types.) |
If we use type arguments to resolve the static extensions it would allow the rest of #276 which instance extensions already partially allows. |
Constructors are the problem. However, if we say that the following should work: static extension AList<T> on List<T> {
List.singleton(T value) : this.filled(1, value, growable: true);
}
void main() {
var list = List.singleton(4);
list = List.singleton(5);
var list2 = List<num>.singleton(6);
list2.add(1.5);
} then it puts some constraints on what we can disallow. What's interesting here is that So two different cases for So, during type inference of:
Then further:
Basically, if you write: static extension AList<T> on List<T> {
List.singleton(T value) : this.filled(1, value);
} then you can directly access: var v1 = AList.singleton(1);
var v2 = AList<int>.singleton(1);
List<num> v3 = AList.singleton(1);
var v4 = AList.singleton;
var v5 = AList<int>.singleton;
List<num> Function() v6 = AList.singleton; We will need to specify the meaning of that, which is trivial for non-constructors. For constructors, it follows the same rules as for constructors declared on a class, except that the return type of the constructor is the If you then write var v1 = List.singleton(1);
var v2 = List<int>.singleton(1);
List<num> v3 = List.singleton(1);
var v4 = List.singleton;
var v5 = List<int>.singleton;
List<num> Function() v6 = List.singleton; then it work exactly the same, with Unless there is a context type, then we infer that on the way down, of if the type isn't raw, then we use the resulting instantiated static extension If we have an instantiation of the created type, before looking at arguments, it's used as a filter. Feels messy. But might just work, if we can solve. |
This issue raises the question whether we should resolve the invocation of a constructor for a class
C
which is declared by several static extensions based on the constructor return type, or should we just report an error as soon as there are multiple extensions declaring constructors with the requested name?Background: #3835 provides a proposal for generalizing
extension
declarations such that they can contribute static members and constructors to an existing declaration (e.g., a class, an extension type, etc.), in a way that may resemble extension instance members (that is, "normal" members of the extension declarations that we have had in the language for several years). The same PR also provides a proposal where a new kind of declaration,static extension
, delivers the same affordances, but avoids conflating the semantics ofextension
with new mechanisms and new syntax. We may prefer one or the other proposal, or something else altogether, but the following question seems relevant to them all (and I'll just usestatic extension
to refer to the kind of declaration that provides this feature):A
static extension
can declare a constructor for its so-called on-class, and it has an associated constructor return type (which is similar to the on-type of a regular extension).The question raised in this issue is whether we should allow the actual type arguments to enable resolution of an instance creation, or we should report a compile-time error as soon as we have detected that there are multiple declarations of constructors with the desired name. Here is an example:
A proposal has been made to make this an error even in the second case because both
E1
andE2
have the on-classMyClass
, and both of them provide a constructor namedMyClass.inExtension
.According to the proposal in #3835, it is not an error, because only
E1
is capable of receiving type arguments such that its constructor return type is the specified typeMyClass<num>
(namely:E1<num>
).So @dart-lang/language-team, do you prefer to report an error early (by declaring an ambiguity based on the on-class alone), or do you prefer to take the type parameters into account, and only report an error if there is an ambiguity among the static extensions that are able to match the requested type?
Edit: Corrected the constructor names in the instance creations in main.
The text was updated successfully, but these errors were encountered: