Version 2.18.0-210.0.dev
Merge commit '0d702207f53ede3bc920bf8c0e33f494d1b6bd47' into 'dev'
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 105a6f1..6bfba8e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -4211,7 +4211,7 @@
result = name.buildTypeWithResolvedArguments(
libraryBuilder.nullableBuilderIfTrue(isMarkedAsNullable), arguments,
allowPotentiallyConstantType: allowPotentiallyConstantType,
- forTypeLiteral: false);
+ forTypeCanonicalization: constantContext != ConstantContext.none);
// ignore: unnecessary_null_comparison
if (result == null) {
unhandled("null", "result", beginToken.charOffset, uri);
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index f295cdd..33ca2e8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -256,7 +256,7 @@
TypeBuilder buildTypeWithResolvedArguments(
NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments,
{required bool allowPotentiallyConstantType,
- required bool forTypeLiteral}) {
+ required bool forTypeCanonicalization}) {
Message message = templateNotAType.withArguments(token.lexeme);
_helper.libraryBuilder
.addProblem(message, fileOffset, lengthForToken(token), _uri);
@@ -2931,13 +2931,13 @@
TypeBuilder buildTypeWithResolvedArguments(
NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments,
{required bool allowPotentiallyConstantType,
- required bool forTypeLiteral}) {
+ required bool forTypeCanonicalization}) {
String name = "${prefixGenerator._plainNameForRead}."
"${suffixGenerator._plainNameForRead}";
TypeBuilder type = suffixGenerator.buildTypeWithResolvedArguments(
nullabilityBuilder, arguments,
allowPotentiallyConstantType: allowPotentiallyConstantType,
- forTypeLiteral: forTypeLiteral);
+ forTypeCanonicalization: forTypeCanonicalization);
LocatedMessage message;
if (type is NamedTypeBuilder &&
type.declaration is InvalidTypeDeclarationBuilder) {
@@ -3058,7 +3058,7 @@
TypeBuilder buildTypeWithResolvedArguments(
NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments,
{required bool allowPotentiallyConstantType,
- required bool forTypeLiteral}) {
+ required bool forTypeCanonicalization}) {
if (declaration is OmittedTypeDeclarationBuilder) {
// TODO(johnniwinther): Report errors when this occurs in-body or with
// type arguments.
@@ -3071,7 +3071,7 @@
fileUri: _uri,
charOffset: fileOffset,
instanceTypeVariableAccess: _helper.instanceTypeVariableAccessState,
- forTypeLiteral: forTypeLiteral)
+ forTypeLiteral: forTypeCanonicalization)
..bind(_helper.libraryBuilder, declaration);
}
@@ -3118,7 +3118,8 @@
_helper.buildDartType(
buildTypeWithResolvedArguments(
_helper.libraryBuilder.nonNullableBuilder, typeArguments,
- allowPotentiallyConstantType: true, forTypeLiteral: true),
+ allowPotentiallyConstantType: true,
+ forTypeCanonicalization: true),
TypeUse.typeLiteral,
allowPotentiallyConstantType:
_helper.libraryFeatures.constructorTearoffs.isEnabled));
@@ -4194,7 +4195,7 @@
TypeBuilder buildTypeWithResolvedArguments(
NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments,
{required bool allowPotentiallyConstantType,
- required bool forTypeLiteral}) {
+ required bool forTypeCanonicalization}) {
Template<Message Function(String, String)> template = isUnresolved
? templateUnresolvedPrefixInTypeAnnotation
: templateNotAPrefixInTypeAnnotation;
@@ -4314,7 +4315,7 @@
TypeBuilder buildTypeWithResolvedArguments(
NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments,
{required bool allowPotentiallyConstantType,
- required bool forTypeLiteral}) {
+ required bool forTypeCanonicalization}) {
_helper.libraryBuilder.addProblem(message, fileOffset, noLength, _uri);
return new NamedTypeBuilder.forInvalidType(token.lexeme, nullabilityBuilder,
message.withLocation(_uri, fileOffset, noLength));
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index e5db1cd..78c6f01 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -463,6 +463,7 @@
ops
optimal
oracle
+ot
outbound
outliers
overhead
diff --git a/pkg/front_end/testcases/general/issue46518.dart b/pkg/front_end/testcases/general/issue46518.dart
new file mode 100644
index 0000000..788c568
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46518.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.9
+import "./issue46518_lib.dart";
+
+const optedOutToken = OT<NullableIntF>();
+
+class CheckIdentical {
+ const CheckIdentical(x, y) : assert(identical(x, y));
+}
+
+testOptedOut() {
+ const localToken = OT<NullableIntF>();
+ const CheckIdentical(optedInToken, localToken);
+ const CheckIdentical(optedOutToken, localToken);
+}
+
+const testCrossLibraries = const CheckIdentical(optedInToken, optedOutToken);
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue46518.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue46518.dart.textual_outline.expect
new file mode 100644
index 0000000..f3cfe6d
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46518.dart.textual_outline.expect
@@ -0,0 +1,12 @@
+// @dart = 2.9
+import "./issue46518_lib.dart";
+
+const optedOutToken = OT<NullableIntF>();
+
+class CheckIdentical {
+ const CheckIdentical(x, y) : assert(identical(x, y));
+}
+
+testOptedOut() {}
+const testCrossLibraries = const CheckIdentical(optedInToken, optedOutToken);
+main() {}
diff --git a/pkg/front_end/testcases/general/issue46518.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue46518.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..6505ed0
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46518.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+// @dart = 2.9
+import "./issue46518_lib.dart";
+
+class CheckIdentical {
+ const CheckIdentical(x, y) : assert(identical(x, y));
+}
+
+const optedOutToken = OT<NullableIntF>();
+const testCrossLibraries = const CheckIdentical(optedInToken, optedOutToken);
+main() {}
+testOptedOut() {}
diff --git a/pkg/front_end/testcases/general/issue46518.dart.weak.expect b/pkg/front_end/testcases/general/issue46518.dart.weak.expect
new file mode 100644
index 0000000..2c9870a
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46518.dart.weak.expect
@@ -0,0 +1,72 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "issue46518_lib.dart" as iss;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///issue46518_lib.dart";
+
+class CheckIdentical extends core::Object /*hasConstConstructor*/ {
+ const constructor •(dynamic x, dynamic y) → self::CheckIdentical*
+ : assert(core::identical(x, y)), super core::Object::•()
+ ;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field iss::OT<() →* asy::Future<core::int*>*>* optedOutToken = #C1;
+static const field self::CheckIdentical* testCrossLibraries = #C2;
+static method testOptedOut() → dynamic {
+ #C2;
+ #C2;
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as iss;
+import "dart:async" as asy;
+import "dart:core" as core;
+import "issue46518.dart" as self;
+
+import "org-dartlang-testcase:///issue46518.dart";
+
+typedef NullableIntF = () → asy::Future<core::int?>;
+class OT<T extends core::Object> extends core::Object /*hasConstConstructor*/ {
+ const constructor •() → iss::OT<iss::OT::T>
+ : super core::Object::•()
+ ;
+ @#C3
+ method toString() → core::String {
+ return "${this.{core::Object::runtimeType}{core::Type}}";
+ }
+}
+static const field iss::OT<() → asy::Future<core::int?>> optedInToken = #C1;
+static method testOptedIn() → dynamic {
+ #C2;
+ #C2;
+}
+
+constants {
+ #C1 = iss::OT<() →* asy::Future<core::int?>*> {}
+ #C2 = self::CheckIdentical {}
+ #C3 = core::_Override {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue46518.dart:
+- OT. (from org-dartlang-testcase:///issue46518_lib.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- CheckIdentical. (from org-dartlang-testcase:///issue46518.dart:11:9)
+
+org-dartlang-testcase:///issue46518_lib.dart:
+- OT. (from org-dartlang-testcase:///issue46518_lib.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- CheckIdentical. (from org-dartlang-testcase:///issue46518.dart:11:9)
diff --git a/pkg/front_end/testcases/general/issue46518.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue46518.dart.weak.modular.expect
new file mode 100644
index 0000000..2c9870a
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46518.dart.weak.modular.expect
@@ -0,0 +1,72 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "issue46518_lib.dart" as iss;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///issue46518_lib.dart";
+
+class CheckIdentical extends core::Object /*hasConstConstructor*/ {
+ const constructor •(dynamic x, dynamic y) → self::CheckIdentical*
+ : assert(core::identical(x, y)), super core::Object::•()
+ ;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field iss::OT<() →* asy::Future<core::int*>*>* optedOutToken = #C1;
+static const field self::CheckIdentical* testCrossLibraries = #C2;
+static method testOptedOut() → dynamic {
+ #C2;
+ #C2;
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as iss;
+import "dart:async" as asy;
+import "dart:core" as core;
+import "issue46518.dart" as self;
+
+import "org-dartlang-testcase:///issue46518.dart";
+
+typedef NullableIntF = () → asy::Future<core::int?>;
+class OT<T extends core::Object> extends core::Object /*hasConstConstructor*/ {
+ const constructor •() → iss::OT<iss::OT::T>
+ : super core::Object::•()
+ ;
+ @#C3
+ method toString() → core::String {
+ return "${this.{core::Object::runtimeType}{core::Type}}";
+ }
+}
+static const field iss::OT<() → asy::Future<core::int?>> optedInToken = #C1;
+static method testOptedIn() → dynamic {
+ #C2;
+ #C2;
+}
+
+constants {
+ #C1 = iss::OT<() →* asy::Future<core::int?>*> {}
+ #C2 = self::CheckIdentical {}
+ #C3 = core::_Override {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue46518.dart:
+- OT. (from org-dartlang-testcase:///issue46518_lib.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- CheckIdentical. (from org-dartlang-testcase:///issue46518.dart:11:9)
+
+org-dartlang-testcase:///issue46518_lib.dart:
+- OT. (from org-dartlang-testcase:///issue46518_lib.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- CheckIdentical. (from org-dartlang-testcase:///issue46518.dart:11:9)
diff --git a/pkg/front_end/testcases/general/issue46518.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue46518.dart.weak.outline.expect
new file mode 100644
index 0000000..18423e5
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46518.dart.weak.outline.expect
@@ -0,0 +1,57 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "issue46518_lib.dart" as iss;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///issue46518_lib.dart";
+
+class CheckIdentical extends core::Object /*hasConstConstructor*/ {
+ const constructor •(dynamic x, dynamic y) → self::CheckIdentical*
+ : assert(core::identical(x, y)), super core::Object::•()
+ ;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field iss::OT<() →* asy::Future<core::int*>*>* optedOutToken = const iss::OT::•<() →* asy::Future<core::int?>>();
+static const field self::CheckIdentical* testCrossLibraries = const self::CheckIdentical::•(iss::optedInToken, self::optedOutToken);
+static method testOptedOut() → dynamic
+ ;
+static method main() → dynamic
+ ;
+
+library /*isNonNullableByDefault*/;
+import self as iss;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///issue46518.dart";
+
+typedef NullableIntF = () → asy::Future<core::int?>;
+class OT<T extends core::Object> extends core::Object /*hasConstConstructor*/ {
+ const constructor •() → iss::OT<iss::OT::T>
+ : super core::Object::•()
+ ;
+ @core::override
+ method toString() → core::String
+ ;
+}
+static const field iss::OT<() → asy::Future<core::int?>> optedInToken = const iss::OT::•<() → asy::Future<core::int?>>();
+static method testOptedIn() → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue46518.dart:8:23 -> InstanceConstant(const OT<Future<int?>* Function()*>{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue46518.dart:20:34 -> InstanceConstant(const CheckIdentical{})
+Evaluated: StaticGet @ org-dartlang-testcase:///issue46518_lib.dart:12:4 -> InstanceConstant(const _Override{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue46518_lib.dart:24:22 -> InstanceConstant(const OT<Future<int?>* Function()*>{})
+Extra constant evaluation: evaluated: 7, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/issue46518.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue46518.dart.weak.transformed.expect
new file mode 100644
index 0000000..2c9870a
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46518.dart.weak.transformed.expect
@@ -0,0 +1,72 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "issue46518_lib.dart" as iss;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///issue46518_lib.dart";
+
+class CheckIdentical extends core::Object /*hasConstConstructor*/ {
+ const constructor •(dynamic x, dynamic y) → self::CheckIdentical*
+ : assert(core::identical(x, y)), super core::Object::•()
+ ;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field iss::OT<() →* asy::Future<core::int*>*>* optedOutToken = #C1;
+static const field self::CheckIdentical* testCrossLibraries = #C2;
+static method testOptedOut() → dynamic {
+ #C2;
+ #C2;
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as iss;
+import "dart:async" as asy;
+import "dart:core" as core;
+import "issue46518.dart" as self;
+
+import "org-dartlang-testcase:///issue46518.dart";
+
+typedef NullableIntF = () → asy::Future<core::int?>;
+class OT<T extends core::Object> extends core::Object /*hasConstConstructor*/ {
+ const constructor •() → iss::OT<iss::OT::T>
+ : super core::Object::•()
+ ;
+ @#C3
+ method toString() → core::String {
+ return "${this.{core::Object::runtimeType}{core::Type}}";
+ }
+}
+static const field iss::OT<() → asy::Future<core::int?>> optedInToken = #C1;
+static method testOptedIn() → dynamic {
+ #C2;
+ #C2;
+}
+
+constants {
+ #C1 = iss::OT<() →* asy::Future<core::int?>*> {}
+ #C2 = self::CheckIdentical {}
+ #C3 = core::_Override {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue46518.dart:
+- OT. (from org-dartlang-testcase:///issue46518_lib.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- CheckIdentical. (from org-dartlang-testcase:///issue46518.dart:11:9)
+
+org-dartlang-testcase:///issue46518_lib.dart:
+- OT. (from org-dartlang-testcase:///issue46518_lib.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- CheckIdentical. (from org-dartlang-testcase:///issue46518.dart:11:9)
diff --git a/pkg/front_end/testcases/general/issue46518_lib.dart b/pkg/front_end/testcases/general/issue46518_lib.dart
new file mode 100644
index 0000000..35602fd
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46518_lib.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import './issue46518.dart';
+
+typedef NullableIntF = Future<int?> Function();
+
+class OT<T extends Object> {
+ const OT();
+
+ @override
+ String toString() {
+ return "$runtimeType";
+ }
+}
+
+testOptedIn() {
+ const localToken = OT<NullableIntF>();
+ const CheckIdentical(optedInToken, localToken);
+ const CheckIdentical(optedOutToken, localToken);
+}
+
+const optedInToken = OT<NullableIntF>();
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.outline.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.outline.expect
index e218902..ec6a7f6 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.outline.expect
@@ -28,19 +28,19 @@
Extra constant evaluation status:
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:821:13 -> SymbolConstant(#catchError)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:821:13 -> ListConstant(const <Type*>[])
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:821:13 -> SymbolConstant(#test)
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:872:13 -> SymbolConstant(#whenComplete)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:872:13 -> ListConstant(const <Type*>[])
-Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:872:13 -> MapConstant(const <Symbol*, dynamic>{})
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:916:13 -> SymbolConstant(#timeout)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:916:13 -> ListConstant(const <Type*>[])
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:916:13 -> SymbolConstant(#onTimeout)
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:770:13 -> SymbolConstant(#then)
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:770:13 -> SymbolConstant(#onError)
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:881:13 -> SymbolConstant(#asStream)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:881:13 -> ListConstant(const <Type*>[])
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:881:13 -> ListConstant(const <dynamic>[])
-Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:881:13 -> MapConstant(const <Symbol*, dynamic>{})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:814:13 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:814:13 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:814:13 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:865:13 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:865:13 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:865:13 -> MapConstant(const <Symbol*, dynamic>{})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:909:13 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:909:13 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:909:13 -> SymbolConstant(#onTimeout)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:763:13 -> SymbolConstant(#then)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:763:13 -> SymbolConstant(#onError)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:874:13 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:874:13 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:874:13 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:874:13 -> MapConstant(const <Symbol*, dynamic>{})
Extra constant evaluation: evaluated: 61, effectively constant: 15
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index ca05fc6..f4da9ca 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -109,6 +109,7 @@
CastStreamTransformer,
checkNotNullable,
EmptyIterator,
+ isNullFuture,
IterableElementError,
nullFuture,
printToZone,
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index f83386d..908e5e1 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -223,13 +223,6 @@
/// it's very clearly documented.
@pragma("wasm:entry-point")
abstract class Future<T> {
- /// A `Future<Null>` completed with `null`.
- ///
- /// Currently shared with `dart:internal`.
- /// If that future can be removed, then change this back to
- /// `_Future<Null>.zoneValue(null, _rootZone);`
- static final _Future<Null> _nullFuture = nullFuture as _Future<Null>;
-
/// A `Future<bool>` completed with `false`.
static final _Future<bool> _falseFuture =
new _Future<bool>.zoneValue(false, _rootZone);
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 038c3bb..bb942d9 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -515,7 +515,7 @@
controller
..onCancel = () {
timer.cancel();
- return Future._nullFuture;
+ return nullFuture;
}
..onPause = () {
watch.stop();
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index 2baf008..2d381c5 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -588,7 +588,10 @@
Future<void> get done => _ensureDoneFuture();
Future<void> _ensureDoneFuture() =>
- _doneFuture ??= _isCanceled ? Future._nullFuture : _Future<void>();
+ _doneFuture ??
+ (_isCanceled
+ ? nullFuture as Future<void>
+ : _doneFuture = _Future<void>());
/// Send or enqueue a data event.
void add(T value) {
@@ -919,7 +922,7 @@
var cancel = addSubscription.cancel();
if (cancel == null) {
addStreamFuture._asyncComplete(null);
- return Future._nullFuture;
+ return nullFuture;
}
return cancel.whenComplete(() {
addStreamFuture._asyncComplete(null);
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index b4fb5d8..9065c46 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -197,7 +197,7 @@
if (!_isCanceled) {
_cancel();
}
- return _cancelFuture ?? Future._nullFuture;
+ return _cancelFuture ?? nullFuture;
}
Future<E> asFuture<E>([E? futureValue]) {
@@ -217,7 +217,7 @@
};
_onError = (Object error, StackTrace stackTrace) {
Future cancelFuture = cancel();
- if (!identical(cancelFuture, Future._nullFuture)) {
+ if (!isNullFuture(Zone._current, cancelFuture)) {
cancelFuture.whenComplete(() {
result._completeError(error, stackTrace);
});
@@ -297,7 +297,7 @@
// Hooks called when the input is paused, unpaused or canceled.
// These must not throw. If overwritten to call user code, include suitable
// try/catch wrapping and send any errors to
- // [_Zone.current.handleUncaughtError].
+ // [Zone._current.handleUncaughtError].
void _onPause() {
assert(_isInputPaused);
}
@@ -352,7 +352,6 @@
// future to finish we must not report the error.
if (_isCanceled && !_waitsForCancel) return;
_state |= _STATE_IN_CALLBACK;
- // TODO(floitsch): this dynamic should be 'void'.
var onError = _onError;
if (onError is void Function(Object, StackTrace)) {
_zone.runBinaryGuarded<Object, StackTrace>(onError, error, stackTrace);
@@ -366,8 +365,7 @@
_state |= _STATE_WAIT_FOR_CANCEL;
_cancel();
var cancelFuture = _cancelFuture;
- if (cancelFuture != null &&
- !identical(cancelFuture, Future._nullFuture)) {
+ if (cancelFuture != null && !isNullFuture(Zone._current, cancelFuture)) {
cancelFuture.whenComplete(sendError);
} else {
sendError();
@@ -396,7 +394,7 @@
_cancel();
_state |= _STATE_WAIT_FOR_CANCEL;
var cancelFuture = _cancelFuture;
- if (cancelFuture != null && !identical(cancelFuture, Future._nullFuture)) {
+ if (cancelFuture != null && !isNullFuture(Zone._current, cancelFuture)) {
cancelFuture.whenComplete(sendDone);
} else {
sendDone();
@@ -672,7 +670,7 @@
}
}
- Future cancel() => Future._nullFuture;
+ Future cancel() => nullFuture;
Future<E> asFuture<E>([E? futureValue]) {
E resultValue;
@@ -819,7 +817,7 @@
Future cancel() {
_stream._cancelSubscription();
- return Future._nullFuture;
+ return nullFuture;
}
bool get isPaused {
@@ -963,7 +961,7 @@
}
return subscription.cancel();
}
- return Future._nullFuture;
+ return nullFuture;
}
void _onData(T data) {
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index cd707be..78ad675 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -26,7 +26,7 @@
void _cancelAndError(StreamSubscription subscription, _Future future,
Object error, StackTrace stackTrace) {
var cancelFuture = subscription.cancel();
- if (cancelFuture != null && !identical(cancelFuture, Future._nullFuture)) {
+ if (cancelFuture != null && !isNullFuture(Zone._current, cancelFuture)) {
cancelFuture.whenComplete(() => future._completeError(error, stackTrace));
} else {
future._completeError(error, stackTrace);
@@ -55,7 +55,7 @@
before completing with a value. */
void _cancelAndValue(StreamSubscription subscription, _Future future, value) {
var cancelFuture = subscription.cancel();
- if (cancelFuture != null && !identical(cancelFuture, Future._nullFuture)) {
+ if (cancelFuture != null && !isNullFuture(Zone._current, cancelFuture)) {
cancelFuture.whenComplete(() => future._complete(value));
} else {
future._complete(value);
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 671f68a..4bc1905 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -37302,7 +37302,7 @@
}
Future cancel() {
- if (_canceled) return nullFuture;
+ if (_canceled) return Future<void>.value(null);
_unlisten();
// Clear out the target to indicate this is complete.
diff --git a/sdk/lib/internal/internal.dart b/sdk/lib/internal/internal.dart
index ff3d890..a763b12 100644
--- a/sdk/lib/internal/internal.dart
+++ b/sdk/lib/internal/internal.dart
@@ -136,7 +136,7 @@
return digit1 * 16 + digit2 - (digit2 & 256);
}
-/// A reusable `null`-valued future used by `dart:async`.
+/// A reusable `null`-valued future per zone used by `dart:async`.
///
/// **DO NOT USE.**
///
@@ -156,7 +156,14 @@
/// This future will be removed again if we can ever do so.
/// Do not use it for anything other than preserving timing
/// during the null safety migration.
-final Future<Null> nullFuture = Zone.root.run(() => Future<Null>.value(null));
+Future<Null> get nullFuture => _nullFutures[Zone.current] ??=
+ Future<Null>.value(null);
+
+/// Whether [future] is the null future of the current zone.
+bool isNullFuture(Zone zone, Future future) =>
+ identical(_nullFutures[zone], future);
+
+final Expando<Future<Null>> _nullFutures = Expando<Future<Null>>();
/// A default hash function used by the platform in various places.
///
diff --git a/tests/lib/async/null_future_zone_test.dart b/tests/lib/async/null_future_zone_test.dart
index 9a266be..34201e7 100644
--- a/tests/lib/async/null_future_zone_test.dart
+++ b/tests/lib/async/null_future_zone_test.dart
@@ -13,21 +13,32 @@
Expect.isFalse(await it.moveNext());
late Future nullFuture;
+
+ bool nullFutureZoneUsed = false;
+ runZoned(() {
+ nullFuture = (new StreamController()..stream.listen(null).cancel()).done;
+ }, zoneSpecification: new ZoneSpecification(scheduleMicrotask:
+ (Zone self, ZoneDelegate parent, Zone zone, void f()) {
+ Expect.identical(zone, self);
+ nullFutureZoneUsed = true;
+ parent.scheduleMicrotask(zone, f);
+ }));
+
+ nullFuture.then((value) {
+ Expect.isNull(value);
+ Expect.isTrue(nullFutureZoneUsed);
+ asyncEnd();
+ });
+
late Future falseFuture;
runZoned(() {
- nullFuture = (new StreamController()..stream.listen(null).cancel()).done;
falseFuture = it.moveNext();
}, zoneSpecification: new ZoneSpecification(scheduleMicrotask:
(Zone self, ZoneDelegate parent, Zone zone, void f()) {
Expect.fail("Should not be called");
}));
- nullFuture.then((value) {
- Expect.isNull(value);
- asyncEnd();
- });
-
falseFuture.then((value) {
Expect.isFalse(value);
asyncEnd();
diff --git a/tests/lib_2/async/null_future_zone_test.dart b/tests/lib_2/async/null_future_zone_test.dart
index 3322916..77cb1b7 100644
--- a/tests/lib_2/async/null_future_zone_test.dart
+++ b/tests/lib_2/async/null_future_zone_test.dart
@@ -15,21 +15,32 @@
Expect.isFalse(await it.moveNext());
Future nullFuture;
+
+ bool nullFutureZoneUsed = false;
+ runZoned(() {
+ nullFuture = (new StreamController()..stream.listen(null).cancel()).done;
+ }, zoneSpecification: new ZoneSpecification(scheduleMicrotask:
+ (Zone self, ZoneDelegate parent, Zone zone, void f()) {
+ Expect.identical(zone, self);
+ nullFutureZoneUsed = true;
+ parent.scheduleMicrotask(zone, f);
+ }));
+
+ nullFuture.then((value) {
+ Expect.isNull(value);
+ Expect.isTrue(nullFutureZoneUsed);
+ asyncEnd();
+ });
+
Future falseFuture;
runZoned(() {
- nullFuture = (new StreamController()..stream.listen(null).cancel()).done;
falseFuture = it.moveNext();
}, zoneSpecification: new ZoneSpecification(scheduleMicrotask:
(Zone self, ZoneDelegate parent, Zone zone, void f()) {
Expect.fail("Should not be called");
}));
- nullFuture.then((value) {
- Expect.isNull(value);
- asyncEnd();
- });
-
falseFuture.then((value) {
Expect.isFalse(value);
asyncEnd();
diff --git a/tools/VERSION b/tools/VERSION
index 90241e9..db6faae 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 18
PATCH 0
-PRERELEASE 209
+PRERELEASE 210
PRERELEASE_PATCH 0
\ No newline at end of file