-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Different handling of nested Futures #31743
Comments
Seems a bit suspicious. @mkustermann, could you check this out when you have time? |
The inferred types look bad.
Namely, But what should it actually be? @leafpetersen @stereotype441 |
The inferred types are correct, I believe. The behavior here is basically a library issue. Dart 2.0 should infer
Obviously, I think the former is friendlier. For context, in strong mode before cc @lrhn |
Agree. The specification has been updated to not flatten more than one level of |
So the libraries will change. In Dart 1.0 you might have assumed that, due to flattening, foo(new Future.value(true)).then((Future<bool> result) {
result.then((bool result) {
print(result.runtimeType);
});
}); I guess everything is working as intended here? |
I can't say for sure. With the workaround above, execution fails in Dart 1.0 on
In Dart 2.0, it works. However, if I change import 'dart:async';
void main() {
foo(new Future.value(true)).then((result) {
result.then((value) {
print(value.runtimeType);
});
});
}
Future foo(value) => new Future.value(value);
|
The non-generic behavior is expected in both Dart 1 and Dart 2. Future<dynamic> foo(dynamic value) => new Future<dynamic>.value(value); Rewritten, the program is then equivalent to: var fooArg = new Future<dynamic>.value(true); // `dynamic` inferred from context.
Future fooResult = new Future.value(fooArg); // inlined `foo` call
fooResult.then((dynamic result) {
result.then((dynamic value) {
print(value.runtimeType);
});
}); So, |
Does |
It does, yes. The signature of Future.value(FutureOr<T> result); If the argument is a |
Just to be sure we're on the same page, it should probably only unwrap if required. That is, pseudo-code for Future.value(FutureOr<T> result) {
if (result is T) return new Future.reallyValue(result);
else return (result as Future<T>).then((a) => a);
} |
Something like that, but probably testing against the future type first. It makes a difference for the case (Actually, looking at that code, it seems it has been updated to only unfold once, but I have to check some edge cases to be sure that it's not just skin deep). |
Hi, has this issue been converged? I've run into something very similar with this code: import 'dart:async';
import 'package:isolate/isolate_runner.dart';
import 'package:isolate/load_balancer.dart';
Future main() async {
final balancer = await LoadBalancer.create(1, IsolateRunner.spawn);
balancer.run(_run, null).then((result) {
if (result) {
print('OK');
}
});
}
Future<bool> _run(_) =>
new Future<bool>.delayed(const Duration(seconds: 1), () => true); On DartVM
Changing FutureOr<bool> _run(_) =>
new Future<bool>.delayed(const Duration(seconds: 1), () => true); leads to runtime failure:
|
The isolate library seems to be creating a The |
What is the status of this issue? Is this a VM issue, a library issue or a front-end issue? /cc @lrhn @kmillikin |
The behavior from the comment above could be replicated with the current |
@lrhn @lexaknyazev If the return type of If the return type of Future<R> run<R, P>(R function(P argument), P argument,
{Duration timeout, onTimeout()}) {
return singleResultFuture((SendPort port) {
_commandPort.send(list4(_RUN, function, argument, port));
}, timeout: timeout, onTimeout: onTimeout);
}
We think this is a library issue. |
Does it also explain process hang? With about 50% chance, |
"Hanging" is most likely just a symptom of the main isolate still having an open receive port, and never getting a message that it should stop listening. If something fails in a spawned isolate, it may still print the error. It can then die or not (it probably doesn't), but if that means that the computation never completes, then the main isolate never gets told to stop listening. You can use var runner = await IsolateRunner.spawn();
runner.onExit.whenComplete(runner.close); but that won't prevent the runner isolate from staying alive and doing nothing. Arguably, the runner isolate should run every operation in a new error zone, and report the operation as failing if it has any uncaught errors, not just if the entry-point for the operation throws. That would prevent that particular issue. |
Given that |
I've published isolate v2.0.0 |
Consider this code:
foo.dart
It gives no analyzer issues. However, running it with "legacy" VM and with Dart2 options results in different output:
Is it expected?
The text was updated successfully, but these errors were encountered: