-
Notifications
You must be signed in to change notification settings - Fork 28
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
Fixes #2490. Add more await tests for extension types #2500
Conversation
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.
Looks good! A few tests have issues, though, in particular with intersection types.
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t04.dart
Outdated
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t04.dart
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t06.dart
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t06.dart
Outdated
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t07.dart
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t08.dart
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t10.dart
Outdated
Show resolved
Hide resolved
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.
Updated. Please take another look
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t04.dart
Outdated
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t04.dart
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t06.dart
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t06.dart
Outdated
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t08.dart
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t10.dart
Outdated
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t06.dart
Show resolved
Hide resolved
extension type IntET(int _) {} | ||
|
||
test1<X extends FutureOr<NumET>>(X x) async { | ||
if (x is int) { |
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.
I think this would have to be something like x is NumET
: We don't get a promotion of x
to a non-subtype of FutureOr<NumET>
, and then we aren't testing anything of the form X & B
.
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.
Changed to
extension type NumET(num _) implements num {}
extension type IntET(int _) implements NumET {}
This should work, shouldn't it?
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.
Not yet: The type of x
is initially X extends FutureOr<NumET>
. We then test for int
, but int
is not a subtype of FutureOr<NumET>
and hence there's no promotion and no intersection type.
However, NumET <: FutureOr<NumET>
because T <: FutureOr<T>
for any T
(including extension types), so we could have if (x is NumET) ...
and that would promote the type of x
to X & NumET
. Similarly, we could have if (x is IntET) ...
if we have IntET <: NumET
(as in the new code).
NumET
and IntET
are incompatible with await, but that's OK: If we await x
then we just determine that NumET
/IntET
do not derive a future type, but X
does, and then await x
is OK, with type flatten(X) == flatten(FutureOr<NumET>) == NumET
.
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.
NumET
andIntET
are incompatible with await, but that's OK: If we await x then we just determine thatNumET
/IntET
do not derive a future type, butX
does, and thenawait x
is OK, with typeflatten(X) == flatten(FutureOr<NumET>) == NumET
.
Sorry, I don't quite understand. Do you want to sat that
if (x is IntET) {
await x;
}
is OK? No error? But, according to the definition
- T is X & B, and either:
- B is incompatible with await, or
In case of x is IntET
, IntET
is incompatible with await, criteria met, so await x
should be a compile-time error.
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.
Ah, you're right. We have a slight inconsistency because 'incompatible with await' is more aggressive than flatten, so we never get around to try to invoke flatten on the type of x
because it is already an error, as you mention, according to the 'incompatible' rule to have await x
.
The underlying question is "do we want to make it an error to have await e
when the type of e
is X & B
where B
'is bad' but X
is 'good'?". The 'incompatible' rule says "yes, don't even bother to look at X
", but flatten allows us to disregard B
if it doesn't derive any future types, and then use X
.
So the question is whether we can actually have this situation at all:
- We do
await x
. - The static type of
x
isX & B
. B
is an extension type which is compatible with await.B
does not derive a future type.- So we use
X
in flatten, and it does derive a future type.
I don't think we can find a type B
with those properties.
So this basically means that we can't use the 'otherwise' case in the rule about flatten on an intersection type X & B
where B
is an extension type.
But then we'd just have to test that we do get the compile-time error when B
is an extension type that does not implement Future<T>
for any T
. Perhaps that's already done in some other test?
Next, we can test that the first case is used in the flatten rule about X & B
when X
does not derive a future type, but B
does (perhaps X extends Object
and B == NumFutureET
).
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.
But then we'd just have to test that we do get the compile-time error when
B
is an extension type that does not implementFuture<T>
for anyT
. Perhaps that's already done in some other test?
Below in this test we have if (x is IntET) {
Next, we can test that the first case is used in the flatten rule about
X & B
whenX
does not derive a future type, butB
does (perhapsX extends Object
andB == NumFutureET
).
Added static_analysis_extension_types_A08_t11.dart
which checks it. In case X extends Object
X
is compatible with await, so I used X extends ObjectET
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t07.dart
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t08.dart
Outdated
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t06.dart
Outdated
Show resolved
Hide resolved
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.
Still a couple of issues. I've commented on several cases where the description is about intersection types, but we don't have an expression whose type is an intersection type. In general, we just need to perform the type test on a subtype of the current type of the variable at that point.
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.
Updated. Please review, there are some places where I'm not 100% sure
extension type IntET(int _) {} | ||
|
||
test1<X extends FutureOr<NumET>>(X x) async { | ||
if (x is int) { |
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.
Changed to
extension type NumET(num _) implements num {}
extension type IntET(int _) implements NumET {}
This should work, shouldn't it?
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t08.dart
Outdated
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t07.dart
Show resolved
Hide resolved
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 one still has some issues.
extension type IntET(int _) {} | ||
|
||
test1<X extends FutureOr<NumET>>(X x) async { | ||
if (x is int) { |
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.
Not yet: The type of x
is initially X extends FutureOr<NumET>
. We then test for int
, but int
is not a subtype of FutureOr<NumET>
and hence there's no promotion and no intersection type.
However, NumET <: FutureOr<NumET>
because T <: FutureOr<T>
for any T
(including extension types), so we could have if (x is NumET) ...
and that would promote the type of x
to X & NumET
. Similarly, we could have if (x is IntET) ...
if we have IntET <: NumET
(as in the new code).
NumET
and IntET
are incompatible with await, but that's OK: If we await x
then we just determine that NumET
/IntET
do not derive a future type, but X
does, and then await x
is OK, with type flatten(X) == flatten(FutureOr<NumET>) == NumET
.
|
||
test1<X extends Future<NumET>>(X x) async { | ||
test1<X extends NumET>(X x) async { | ||
if (x is int) { |
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.
We still can't promote to int
, because that isn't a subtype of NumET
.
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.
Indeed... Removed this
if (x is int) { | ||
await x; // No error here, int is compatible with await | ||
} | ||
if (x is FutureOr<IntET>) { |
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.
Can't promote to FutureOr<IntET>
.
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t07.dart
Show resolved
Hide resolved
if (x is int) { | ||
await x; // No error here, int is compatible with await | ||
} | ||
if (x is FutureOr<IntET>) { |
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.
Can't promote x
because FutureOr<IntET>
is not a subtype of num
.
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.
Fixed
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t08.dart
Outdated
Show resolved
Hide resolved
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.
Added a comment.
extension type IntET(int _) {} | ||
|
||
test1<X extends FutureOr<NumET>>(X x) async { | ||
if (x is int) { |
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.
Ah, you're right. We have a slight inconsistency because 'incompatible with await' is more aggressive than flatten, so we never get around to try to invoke flatten on the type of x
because it is already an error, as you mention, according to the 'incompatible' rule to have await x
.
The underlying question is "do we want to make it an error to have await e
when the type of e
is X & B
where B
'is bad' but X
is 'good'?". The 'incompatible' rule says "yes, don't even bother to look at X
", but flatten allows us to disregard B
if it doesn't derive any future types, and then use X
.
So the question is whether we can actually have this situation at all:
- We do
await x
. - The static type of
x
isX & B
. B
is an extension type which is compatible with await.B
does not derive a future type.- So we use
X
in flatten, and it does derive a future type.
I don't think we can find a type B
with those properties.
So this basically means that we can't use the 'otherwise' case in the rule about flatten on an intersection type X & B
where B
is an extension type.
But then we'd just have to test that we do get the compile-time error when B
is an extension type that does not implement Future<T>
for any T
. Perhaps that's already done in some other test?
Next, we can test that the first case is used in the flatten rule about X & B
when X
does not derive a future type, but B
does (perhaps X extends Object
and B == NumFutureET
).
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.
Thank you! Updated once again. Please review
|
||
test1<X extends Future<NumET>>(X x) async { | ||
test1<X extends NumET>(X x) async { | ||
if (x is int) { |
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.
Indeed... Removed this
extension type IntET(int _) {} | ||
|
||
test1<X extends FutureOr<NumET>>(X x) async { | ||
if (x is int) { |
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.
But then we'd just have to test that we do get the compile-time error when
B
is an extension type that does not implementFuture<T>
for anyT
. Perhaps that's already done in some other test?
Below in this test we have if (x is IntET) {
Next, we can test that the first case is used in the flatten rule about
X & B
whenX
does not derive a future type, butB
does (perhapsX extends Object
andB == NumFutureET
).
Added static_analysis_extension_types_A08_t11.dart
which checks it. In case X extends Object
X
is compatible with await, so I used X extends ObjectET
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t06.dart
Show resolved
Hide resolved
if (x is int) { | ||
await x; // No error here, int is compatible with await | ||
} | ||
if (x is FutureOr<IntET>) { |
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.
Fixed
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.
Just one more thing: I think there is still one ?
that prevents promotion.
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t07.dart
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t07.dart
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t08.dart
Show resolved
Hide resolved
LanguageFeatures/Extension-types/static_analysis_extension_types_A08_t06.dart
Show resolved
Hide resolved
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.
LGTM!
2024-02-02 sgrekhov22@gmail.com Fix dart-lang/co19#2517. Fix wrong test, add experimental flags (dart-lang/co19#2518) 2024-02-02 sgrekhov22@gmail.com Fix dart-lang/co19#2490. Update incompatible with await tests according to the changed rule (dart-lang/co19#2516) 2024-02-01 sgrekhov22@gmail.com dart-lang/co19#2420. Add more exhaustiveness tests (dart-lang/co19#2513) 2024-01-31 sgrekhov22@gmail.com dart-lang/co19#2446. Add additional test for cast pattern (dart-lang/co19#2514) 2024-01-30 sgrekhov22@gmail.com dart-lang/co19#1399. Add more tests for records (dart-lang/co19#2511) 2024-01-30 sgrekhov22@gmail.com dart-lang/co19#2485. Update map and list constant literals tests. Add parenthesized for records (dart-lang/co19#2512) 2024-01-29 sgrekhov22@gmail.com Fixes dart-lang/co19#2490. Add more await tests for extension types (dart-lang/co19#2500) 2024-01-29 sgrekhov22@gmail.com dart-lang/co19#2119. Fix typo in Subtyping tests description (dart-lang/co19#2510) 2024-01-29 sgrekhov22@gmail.com Fixes dart-lang/co19#2505. Add more tests for `call` member (dart-lang/co19#2506) 2024-01-29 sgrekhov22@gmail.com dart-lang/co19#2420. Add cast-pattern tests for extension types (dart-lang/co19#2458) Change-Id: I631705a013f9a77910ae0f0be5a9fea01e7c719f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/350240 Reviewed-by: Erik Ernst <eernst@google.com> Commit-Queue: Erik Ernst <eernst@google.com> Reviewed-by: William Hesse <whesse@google.com>
…lang#2500) Add more await tests for extension types.
…lang#2500) Add more await tests for extension types.
No description provided.