-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Analyzer: Implementation of new static analysis for return statements #41803
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
Should these new rules be applied for both legacy and opted-in libraries, or only to opted-in libraries? |
Only for code with null-safety (this is also the reason why these tests are in |
I have an issue with this code ( import 'dart:async';
FutureOr<Object?> Function(void) f = (void a) async {
return a;
// ^
// [analyzer] unspecified
// [cfe] unspecified
}; For function expressions we need to infer the return type. I'm using these rules. Imposed type: For this rule: Let So, the inferred type of the closure is Then later, when we check @eernstg @leafpetersen Is there a mistake in my calculations? Is this an unexpected interaction between closure return type inference and null safety? |
@scheglov Good catch, I agree with your analysis. This also raises another issue however. I believe that the change to use
Should be replaced with
with a suitable definition of @eernstg can you follow up? |
@eernstg ping |
Sorry, don't know why I missed this one. Looking into it now. |
Just created dart-lang/language#989 to adjust inference.md. Here is the analysis again:
import 'dart:async';
FutureOr<Object?> Function(void) f = (void a) async {
return a;
}; Rules are here. Imposed return type schema: So the analysis still holds, yielding an inferred return type for the function literal which is Created https://dart-review.googlesource.com/149163 where the test is updated such that it does not expect an error. |
I'm sorry for not being explicit about this, but the test that you reference is just one of the group of tests looked to me as being similar, and exercise function expressions inference and return types validation. Once I found this, I decided that this is something more serious with tests, and just chosen randomly one test to explain why it did not look right to me. I don't exclude that some of them might fail by a different reason, but random sampling gives me similar tests. I can try to implement the change to the spec.
|
The change to the spec is needed in order to handle situations like this one: Future<int>? Function() f = () async => Future<int?>.value(null); If we use So this change will be needed in any case. It's getting late, so I'll look at the long list of tests tomorrow. ;) |
About tests/language/invalid_returns/async_valid_returns_test.dart: There are 12 errors.
The remaining 4 cases return a So these test failures are all working as intended. |
About sync_invalid_return_27_test.dart: This error is legitimate. It is a soundness violation to allow returning the value of an expression of type The errors in 'async_invalid_return_47_test.dart' and 'async_invalid_return_50_test.dart' have the same nature. |
CL https://dart-review.googlesource.com/c/sdk/+/149163/ changes the following tests:
The difference is that the expectation to get an error has been removed from those function literals whose inferred return type is different from the type of the variable that it is assigned to, in such a way that the error doesn't arise. The errors on the regular functions have not changed. A couple of variables of type So the problems with the tests were concerned with function literals and their inferred return types, and the remaining test failures look legitimate to me. |
I will leave comment for changed tests in the CL that changes them, but there are issues for
dynamic f() async {
return;
} We apply this rule:
Here
void vv = null;
dynamic async_void_to_dynamic_e() async => vv; Similar to (1), We apply this rule:
So, the error. |
That's a good catch! I agree on the analysis, the rules imply that it should be flagged as an error. However, I did not consider that case carefully enough, because it seems inconsistent with the treatment of the type The rule Similarly, the return type We would then add an extra rule,
Maybe, maybe not, we don't actually give
This would be covered by a new rule |
Thank you, I added the new rule for I also made a small fix to the legacy rules. An example: // @dart = 2.7
Future<void> start(Future<List<void>> v) async {
return v;
} The change that I made to legacy implementation is what the spec says, I think? Is this my misunderstanding of the spec, or a real bug in our implementation? I have a feeling that I have already asked about this or similar return type issue. |
Change-Id: I36661c955b9e033fce92481033307525028a5dc3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/149163 Reviewed-by: Leaf Petersen <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Erik Ernst <[email protected]>
Considering this example: // @dart = 2.7
Future<void> start(Future<List<void>> v) async {
return v;
} It is true that we have had the rule which requires this error for years (since SDK commit 5d8501a, Dec 2018), but for a long time we hadn't detected that it wasn't enforced. So for the pre-null-safety code we will have to consider this as a known bug and continue to omit reporting it, because the fix is a breaking change. But with null-safety we can take the step to report this kind of error. In any case, the rule is based on the observation that the following two functions have a very similar overall dataflow, even though they are of course different with respect to the detailed control flow and typing: void f1() {
return 3;
}
Future<void> f2() async {
return 3; // Or `return Future.value(3);`.
}
void main() {
f1(); // Discard 3.
await f2(); // Discard 3.
} In both cases, a computation yields |
Thank you for the explanation. I understand this as we never going to report this error in legacy libraries, but will report a similar error in migrated libraries. |
#41803 https://dart-review.googlesource.com/c/sdk/+/149163 dart-lang/language#989 Change-Id: I13caf53a3e96c7b266dd3b3bf511002addcf83b6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/149373 Commit-Queue: Konstantin Shcheglov <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
The null-safety specification updates in dart-lang/language#941 and dart-lang/language#948 have been unfolded as part of the migration of
tests/language/invalid_returns
. This issue is concerned with updating the analyzer correspondingly.The following tests have a missing compile-time error:
The main reasons for the above is that the rules about
return;
are now more strict, and a void expression can no longer be returned in anasync
function with return typeFuture<Null>
(and several similar types).The following tests incur some compile-time errors that shouldn't be there:
The reason for this is that the old rules required
Future<flatten(S)>
to be assignable to the return type whereS
is the type of the returned expression, and the new rules requireS
to be assignable to the future value type of the function, orflatten(S)
to be a subtype thereof.The text was updated successfully, but these errors were encountered: