-
Notifications
You must be signed in to change notification settings - Fork 230
Specify null-safety async returns
#941
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
Conversation
async returns
eernstg
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great feedback, thanks! Made various changes, PTAL.
|
Rethinking this a bit: The purpose of switching to a dynamic semantics built on "static await" criteria would be that programs are more comprehensible when it is specified directly that an await operation will definitely occur, or will definitely not occur. However, the rules turn out to be so complex that it might not help the reader of code in practice. So maybe we should simply keep the old semantics? It's somewhat quirky, and they do make it less predictable when there will be an await operation, but the old semantics is considerably simpler... |
|
As I mentioned in my review, I think we may need to use future value type in the dynamic semantics for reasons that I filed an issue about (unless I'm confusing myself in the late hour). I'm not convinced that the rest of the change to the dynamic semantics pulls its weight though. I think it's more breaking than advertised, and I don't see that it really makes anything clearer (if anything, less so). |
I agree, and I'm also worried about the breakage. So I'd suggest that we use the existing dynamic semantics, except for the 'future value type' soundness fix. |
|
I uploaded another commit where we use the old semantics, only adjusted to have the 'future value type' correction. |
|
My reason for preferring a static approach is not (just) simplicity, but lack of run-time overhead for type-checking - at least when it's possible. So, the static rule for
and the dynamic semantics are:
Those two match up, but I'd still prefer to change 2. to:
The only difference would occur when S <: |
leafpetersen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM. Can you write tests and file implementation issues?
a82edf6 to
47e1e3d
Compare
|
@lrhn wrote:
If |
This PR on the nnbd spec introduces the requirement "
Sassignable toT_vorflatten(S) <: T_v" (aka model 1) for a return statement in anasyncfunction, whereSis the static type of the returned expression, andT_vis the future value type of the function.This PR also specifies the dynamic semantics, using an approach where the presence/absence of an
awaitstep is statically determined whenever possible.The new dynamic semantics is the same as the pre-null-safety dynamic semantics (that is, the one which is currently specified in
dartLangSpec.tex), except for the case where the returned object dynamic type is a subtype of as wellT_vasFuture<T_v>, and the returned object static type is notdynamic, but it is a subtype ofT_v. This case is expected to be very rare.@lrhn, I made some changes to the rules that you proposed: (1) The case where
Sisdynamicis now first: This ensures that we will await aFuture<T_v>, even in the case whereT_vis a top type. If we checkS <: T_vfirst then that case will apply, and we wouldn't await the future. The typical case isf() async => Future.value(1) as dynamic;, and I think it is an unnecessary breaking change iffwould stop awaiting the future and instead use it to complete the returnedFuture<dynamic>.(2) I removed the case for
S implements Future<dynamic>, because that is a compile-time error with model 1 (because otherwise an earlier case would apply). (3) I removed the case forS is FutureOr<dynamic>for the same reason.