-
Notifications
You must be signed in to change notification settings - Fork 209
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
Generics lost in extension after cast type #3335
Comments
Here is some background information about the situation, and about related discussions that we already had in this area: This is a rather fundamental design choice. Extension methods are resolved at compile time, and this implies that the value of This means that it is not likely that Dart can accommodate a redesign of extension declarations such that they will use the dynamic value of type parameters: It's going to be a massively breaking change. Also, it will make extension methods less performant, and it may also eliminate some optimization opportunities. However, we've had a number of discussions about doing things of this nature, provided via different mechanisms. For example #170 proposed a general mechanism which could be used to "look up" the value of a type argument (at compile time or at run time), and #177 proposed a variant of the extension feature which would allow for dynamic dispatch as well as dynamically bound type parameters. |
It's maybe worth noting that if generics were resolved at runtime rather than compile time, then issues such as #620 could be resolved using extensions. We would be able to do: class Unary<A> {}
void doSomething<T extends Unary<Object?>>(T unary) {
unary._doSomething();
}
extension<A> on Unary<A> {
void _doSomething() {
print('use $A');
}
} This wouldn't work for all cases though. |
Good point, @rrousselGit! Actually, an 'existential open' operation would suffice, so we wouldn't have to make huge breaking changes to the semantics of class Unary<A> {}
void doSomething<T extends Unary<Object?>>(T unary) {
unary._doSomething();
}
extension on Unary<Object?> {
void _doSomething() {
final self = this; // We need this until we get promotion of `this`.
if (self is Unary<final X>) {
// In this scope we have access to the actual value of the type
// argument `X` where `self` has run-time type `Unary<X>`.
X x = ...; // We can use `X` as a type.
print('use $X'); // Of course, we can also obtain a `Type` from it.
}
}
} The construct This is not surprising, I just think it's worth mentioning that we won't have to make radical changes to the semantics of existing mechanisms in order to provide access to this kind of functionality. |
To be fair, relying on extensions for such a thing is probably undesirable. It would mainly work with functions do not use the generic in either return value or parameters. So we probably can't avoid #620. |
Generics lost in extension after cast type
output:
The text was updated successfully, but these errors were encountered: