-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Problem with type definition using generics #51152
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
Comments
A text version is also helpful, as one can not copy from a screenshot. class Wrapper<T> {
const Wrapper(this.value);
final T value;
}
Future<T> send<W extends Wrapper<T>, T>(W wrapper) async {
throw Exception();
}
void main() {
final wrapper = Wrapper(1);
final result = send(wrapper);
print(result);
} |
It looks like a mathematically valid solution AFAICT. It's not clear what you're trying to accomplish with the declaration of If you want the Future<T> send<T>(Wrapper<T> wrapper) async { ... } |
The inferred value of a type variable is often the least possible type. So if we have a constraint like However, in the case where a type parameter has no constraints (that is, the constraint is I think the section Grounded constraint solution for a type variable in the feature specification of type inference contains the most useful information. Basically, the inferred value of a type variable like So we should expect the unconstrained type parameter to be inferred to be a top type. However, I'm not sure why it is inferred as |
Sorry, I forgot to paste a text version of code😢 |
So, does it mean that there is no way to get abstract class Request<R extends Object?> {
const Request(this.value);
final R value;
}
class SomeRequest extends Request<int> {
const SomeRequest(super.value);
}
abstract class RequestHandler<R extends Object?, T extends Request<R>> {
const RequestHandler();
Future<R> call(T request);
}
Future<R> send<R extends Object?, T extends Request<R>>(
T request,
) async {
final handler = _getRequestHandlerFor<T>();
throw Exception();
}
RequestHandler? _getRequestHandlerFor<T extends Request>() => throw Exception();
Future<void> main() async {
const request = SomeRequest(1);
final result = await send(request);
} Type of |
Depends on what you mean by 'no way'. ;-) As @vsmenon mentioned, you could just simplify the situation by having fewer type parameters (and hence fewer degrees of freedom during inference): abstract class Request<R extends Object?> {
const Request(this.value);
final R value;
}
class SomeRequest extends Request<int> {
const SomeRequest(super.value);
}
abstract class RequestHandler<R extends Object?> {
const RequestHandler();
Future<R> call(Request<R> request);
}
Future<R> send<R extends Object?>(Request<R> request) async {
final handler = _getRequestHandlerFor<Request<R>>();
throw Exception();
}
RequestHandler? _getRequestHandlerFor<T extends Request>() => throw Exception();
Future<void> main() async {
const request = SomeRequest(1);
final result = await send(request); // `result` has type `int`.
} I suppose you're using the bound (I usually prefer enhancing the support for getting diagnostic notifications about any location where the type However, I eliminated the type variable That said, there are of course some situations where the elimination of type parameters like this will cause an actual loss of useful typing information: abstract class A<X, Y extends Iterable<X>> {
final X x;
A(this.x);
Y get foo;
}
class B1 extends A<X, List<X>> {
B1(super.x);
List<X> get foo => [x];
}
// Assume that `A` has some other subtypes `B2`, `B3` etc. With these declarations, you would be able to have a variable In those cases you might have to write the type arguments explicitly. |
I'll close this issue because there's considerable overlap between the not-yet-resolved parts of this issue and an existing issue, cf. dart-lang/language#620 (comment). |
Thank you! Great explanation👍 |
I think that there is a serious problem with generic types.
On the 1st screenshot you can read whole code.
On the 2nd screenshot you can see that the type of
wrapper
isWrapper<int>
(as expected)On the 3rd screenshot you can see that the type of
result
isFuture<dynamic>
(as NOT expected, I expectFuture<int>
)The text was updated successfully, but these errors were encountered: