Skip to content

Commit 80c307f

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Handle FutureOr<int> as context type for +
Closes #44595 Change-Id: I0631deb9d23b5e4a7618268b5e1f0f850bfd5ad9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/177703 Reviewed-by: Dmitry Stefantsov <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent 897b1a2 commit 80c307f

9 files changed

+223
-2
lines changed

pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,6 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
147147
if (isNonNullableByDefault) {
148148
if (contextType is! NeverType &&
149149
type1 is! NeverType &&
150-
isSubtypeOf(contextType, coreTypes.numNonNullableRawType,
151-
SubtypeCheckMode.withNullabilities) &&
152150
isSubtypeOf(type1, coreTypes.numNonNullableRawType,
153151
SubtypeCheckMode.withNullabilities)) {
154152
// If e is an expression of the form e1 + e2, e1 - e2, e1 * e2, e1 % e2
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import "dart:async";
6+
7+
T id<T>(T value) => value;
8+
9+
main() async {
10+
FutureOr<int> x = 1 + id(1); // Should work, gives error.
11+
12+
// Checking it!
13+
FutureOr<int> y = 1 + id(1)
14+
..checkStaticType<Exactly<int>>();
15+
FutureOr<int> z = 1 + contextType(1)
16+
..checkStaticType<Exactly<int>>();
17+
}
18+
19+
extension<T> on T {
20+
void checkStaticType<R extends Exactly<T>>() {}
21+
}
22+
23+
typedef Exactly<T> = T Function(T);
24+
T contextType<T>(Object? o) => o as T;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
import "dart:async";
6+
7+
typedef Exactly<invariant T extends dynamic = dynamic> = (T%) → T%;
8+
extension _extension#0<T extends core::Object? = dynamic> on T% {
9+
method checkStaticType = self::_extension#0|checkStaticType;
10+
tearoff checkStaticType = self::_extension#0|get#checkStaticType;
11+
}
12+
static method id<T extends core::Object? = dynamic>(self::id::T% value) → self::id::T%
13+
;
14+
static method main() → dynamic async
15+
;
16+
static method _extension#0|checkStaticType<T extends core::Object? = dynamic, R extends (self::_extension#0|checkStaticType::T%) → self::_extension#0|checkStaticType::T% = (dynamic) → dynamic>(lowered final self::_extension#0|checkStaticType::T% #this) → void
17+
;
18+
static method _extension#0|get#checkStaticType<T extends core::Object? = dynamic>(lowered final self::_extension#0|get#checkStaticType::T% #this) → <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void
19+
return <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void => self::_extension#0|checkStaticType<self::_extension#0|get#checkStaticType::T%, R>(#this);
20+
static method contextType<T extends core::Object? = dynamic>(core::Object? o) → self::contextType::T%
21+
;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
import "dart:async";
6+
7+
typedef Exactly<invariant T extends dynamic = dynamic> = (T%) → T%;
8+
extension _extension#0<T extends core::Object? = dynamic> on T% {
9+
method checkStaticType = self::_extension#0|checkStaticType;
10+
tearoff checkStaticType = self::_extension#0|get#checkStaticType;
11+
}
12+
static method id<T extends core::Object? = dynamic>(self::id::T% value) → self::id::T%
13+
return value;
14+
static method main() → dynamic async {
15+
FutureOr<core::int>x = 1.{core::num::+}(self::id<core::int>(1));
16+
FutureOr<core::int>y = let final core::int #t1 = 1.{core::num::+}(self::id<core::int>(1)) in block {
17+
self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t1);
18+
} =>#t1;
19+
FutureOr<core::int>z = let final core::int #t2 = 1.{core::num::+}(self::contextType<core::int>(1)) in block {
20+
self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
21+
} =>#t2;
22+
}
23+
static method _extension#0|checkStaticType<T extends core::Object? = dynamic, R extends (self::_extension#0|checkStaticType::T%) → self::_extension#0|checkStaticType::T% = (dynamic) → dynamic>(lowered final self::_extension#0|checkStaticType::T% #this) → void {}
24+
static method _extension#0|get#checkStaticType<T extends core::Object? = dynamic>(lowered final self::_extension#0|get#checkStaticType::T% #this) → <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void
25+
return <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void => self::_extension#0|checkStaticType<self::_extension#0|get#checkStaticType::T%, R>(#this);
26+
static method contextType<T extends core::Object? = dynamic>(core::Object? o) → self::contextType::T%
27+
return o as{ForNonNullableByDefault} self::contextType::T%;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:async" as asy;
5+
6+
import "dart:async";
7+
8+
typedef Exactly<invariant T extends dynamic = dynamic> = (T%) → T%;
9+
extension _extension#0<T extends core::Object? = dynamic> on T% {
10+
method checkStaticType = self::_extension#0|checkStaticType;
11+
tearoff checkStaticType = self::_extension#0|get#checkStaticType;
12+
}
13+
static method id<T extends core::Object? = dynamic>(self::id::T% value) → self::id::T%
14+
return value;
15+
static method main() → dynamic /* originally async */ {
16+
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
17+
core::bool* :is_sync = false;
18+
FutureOr<dynamic>? :return_value;
19+
(dynamic) → dynamic :async_op_then;
20+
(core::Object, core::StackTrace) → dynamic :async_op_error;
21+
core::int :await_jump_var = 0;
22+
dynamic :await_ctx_var;
23+
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
24+
try {
25+
#L1:
26+
{
27+
FutureOr<core::int>x = 1.{core::num::+}(self::id<core::int>(1));
28+
FutureOr<core::int>y = let final core::int #t1 = 1.{core::num::+}(self::id<core::int>(1)) in block {
29+
self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t1);
30+
} =>#t1;
31+
FutureOr<core::int>z = let final core::int #t2 = 1.{core::num::+}(self::contextType<core::int>(1)) in block {
32+
self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
33+
} =>#t2;
34+
}
35+
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
36+
return;
37+
}
38+
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
39+
asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
40+
}
41+
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
42+
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
43+
:async_op.call();
44+
:is_sync = true;
45+
return :async_future;
46+
}
47+
static method _extension#0|checkStaticType<T extends core::Object? = dynamic, R extends (self::_extension#0|checkStaticType::T%) → self::_extension#0|checkStaticType::T% = (dynamic) → dynamic>(lowered final self::_extension#0|checkStaticType::T% #this) → void {}
48+
static method _extension#0|get#checkStaticType<T extends core::Object? = dynamic>(lowered final self::_extension#0|get#checkStaticType::T% #this) → <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void
49+
return <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void => self::_extension#0|checkStaticType<self::_extension#0|get#checkStaticType::T%, R>(#this);
50+
static method contextType<T extends core::Object? = dynamic>(core::Object? o) → self::contextType::T%
51+
return o as{ForNonNullableByDefault} self::contextType::T%;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import "dart:async";
2+
3+
T id<T>(T value) => value;
4+
main() async {}
5+
6+
extension<T> on T {
7+
void checkStaticType<R extends Exactly<T>>() {}
8+
}
9+
10+
typedef Exactly<T> = T Function(T);
11+
T contextType<T>(Object? o) => o as T;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import "dart:async";
2+
3+
T contextType<T>(Object? o) => o as T;
4+
T id<T>(T value) => value;
5+
6+
extension<T> on T {
7+
void checkStaticType<R extends Exactly<T>>() {}
8+
}
9+
10+
main() async {}
11+
typedef Exactly<T> = T Function(T);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
import "dart:async";
6+
7+
typedef Exactly<invariant T extends dynamic = dynamic> = (T%) → T%;
8+
extension _extension#0<T extends core::Object? = dynamic> on T% {
9+
method checkStaticType = self::_extension#0|checkStaticType;
10+
tearoff checkStaticType = self::_extension#0|get#checkStaticType;
11+
}
12+
static method id<T extends core::Object? = dynamic>(self::id::T% value) → self::id::T%
13+
return value;
14+
static method main() → dynamic async {
15+
FutureOr<core::int>x = 1.{core::num::+}(self::id<core::int>(1));
16+
FutureOr<core::int>y = let final core::int #t1 = 1.{core::num::+}(self::id<core::int>(1)) in block {
17+
self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t1);
18+
} =>#t1;
19+
FutureOr<core::int>z = let final core::int #t2 = 1.{core::num::+}(self::contextType<core::int>(1)) in block {
20+
self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
21+
} =>#t2;
22+
}
23+
static method _extension#0|checkStaticType<T extends core::Object? = dynamic, R extends (self::_extension#0|checkStaticType::T%) → self::_extension#0|checkStaticType::T% = (dynamic) → dynamic>(lowered final self::_extension#0|checkStaticType::T% #this) → void {}
24+
static method _extension#0|get#checkStaticType<T extends core::Object? = dynamic>(lowered final self::_extension#0|get#checkStaticType::T% #this) → <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void
25+
return <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void => self::_extension#0|checkStaticType<self::_extension#0|get#checkStaticType::T%, R>(#this);
26+
static method contextType<T extends core::Object? = dynamic>(core::Object? o) → self::contextType::T%
27+
return o as{ForNonNullableByDefault} self::contextType::T%;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:async" as asy;
5+
6+
import "dart:async";
7+
8+
typedef Exactly<invariant T extends dynamic = dynamic> = (T%) → T%;
9+
extension _extension#0<T extends core::Object? = dynamic> on T% {
10+
method checkStaticType = self::_extension#0|checkStaticType;
11+
tearoff checkStaticType = self::_extension#0|get#checkStaticType;
12+
}
13+
static method id<T extends core::Object? = dynamic>(self::id::T% value) → self::id::T%
14+
return value;
15+
static method main() → dynamic /* originally async */ {
16+
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
17+
core::bool* :is_sync = false;
18+
FutureOr<dynamic>? :return_value;
19+
(dynamic) → dynamic :async_op_then;
20+
(core::Object, core::StackTrace) → dynamic :async_op_error;
21+
core::int :await_jump_var = 0;
22+
dynamic :await_ctx_var;
23+
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
24+
try {
25+
#L1:
26+
{
27+
FutureOr<core::int>x = 1.{core::num::+}(self::id<core::int>(1));
28+
FutureOr<core::int>y = let final core::int #t1 = 1.{core::num::+}(self::id<core::int>(1)) in block {
29+
self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t1);
30+
} =>#t1;
31+
FutureOr<core::int>z = let final core::int #t2 = 1.{core::num::+}(self::contextType<core::int>(1)) in block {
32+
self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
33+
} =>#t2;
34+
}
35+
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
36+
return;
37+
}
38+
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
39+
asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
40+
}
41+
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
42+
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
43+
:async_op.call();
44+
:is_sync = true;
45+
return :async_future;
46+
}
47+
static method _extension#0|checkStaticType<T extends core::Object? = dynamic, R extends (self::_extension#0|checkStaticType::T%) → self::_extension#0|checkStaticType::T% = (dynamic) → dynamic>(lowered final self::_extension#0|checkStaticType::T% #this) → void {}
48+
static method _extension#0|get#checkStaticType<T extends core::Object? = dynamic>(lowered final self::_extension#0|get#checkStaticType::T% #this) → <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void
49+
return <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void => self::_extension#0|checkStaticType<self::_extension#0|get#checkStaticType::T%, R>(#this);
50+
static method contextType<T extends core::Object? = dynamic>(core::Object? o) → self::contextType::T%
51+
return o as{ForNonNullableByDefault} self::contextType::T%;

0 commit comments

Comments
 (0)