Version 2.13.0-179.0.dev
Merge commit '13556d623fc3330a4206c660432b2ff2223fd194' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_check.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_check.dart
index 51ba181..d00347b 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_check.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_check.dart
@@ -2,6 +2,8 @@
// 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 'dart:async';
+
void bang_promotes(int? x) {
x!;
/*nonNullable*/ x;
@@ -33,3 +35,18 @@
x!;
/*nonNullable*/ x;
}
+
+void bang_promotesNullableFutureInt(FutureOr<int>? x) {
+ x!;
+ /*nonNullable*/ x;
+}
+
+void bang_promotesFutureNullableInt(FutureOr<int?> x) {
+ x!;
+ x;
+}
+
+void bang_promotesNullableFutureNullableInt(FutureOr<int?>? x) {
+ x!;
+ x;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart
index 1b4354d..c818df6 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart
@@ -50,7 +50,7 @@
class F<S, T extends S> {
void nonNull(T t) {
if (t != null) {
- /*analyzer.T & S & Object*/ /*cfe.T & S*/ t;
+ /*T & S & Object*/ t;
}
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
index b45a75c..f9c2d18 100644
--- a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
@@ -61,6 +61,12 @@
}
@override
+ ImplicitFieldType toNonNull() {
+ return unsupported(
+ "toNonNullable", fieldBuilder.charOffset, fieldBuilder.fileUri);
+ }
+
+ @override
void toTextInternal(AstPrinter printer) {
printer.write('<implicit-field-type:$fieldBuilder>');
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/implicit_type_argument.dart b/pkg/front_end/lib/src/fasta/kernel/implicit_type_argument.dart
index c6daddf..3f27451 100644
--- a/pkg/front_end/lib/src/fasta/kernel/implicit_type_argument.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/implicit_type_argument.dart
@@ -49,6 +49,11 @@
}
@override
+ ImplicitTypeArgument toNonNull() {
+ return unsupported("toNonNullable", -1, null);
+ }
+
+ @override
bool equals(Object other, Assumptions assumptions) => this == other;
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index a86117d..13c72b9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -1249,7 +1249,7 @@
// UP(t0, t1)
// - Then the inferred type is T.
DartType originalLhsType = lhsResult.inferredType;
- DartType nonNullableLhsType = inferrer.computeNonNullable(originalLhsType);
+ DartType nonNullableLhsType = originalLhsType.toNonNull();
DartType inferredType = inferrer.typeSchemaEnvironment
.getStandardUpperBound(nonNullableLhsType, rhsResult.inferredType,
inferrer.library.library);
@@ -2725,7 +2725,7 @@
reportNonNullableInNullAwareWarningIfNeeded(
operandType, "!", node.operand.fileOffset);
inferrer.flowAnalysis.nonNullAssert_end(node.operand);
- DartType nonNullableResultType = inferrer.computeNonNullable(operandType);
+ DartType nonNullableResultType = operandType.toNonNull();
return inferrer.createNullAwareExpressionInferenceResult(
nonNullableResultType, node, nullAwareGuards);
}
@@ -2967,7 +2967,7 @@
.findInterfaceMember(readType, equalsName, node.fileOffset)
.member;
- DartType nonNullableReadType = inferrer.computeNonNullable(readType);
+ DartType nonNullableReadType = readType.toNonNull();
DartType inferredType = inferrer.typeSchemaEnvironment
.getStandardUpperBound(
nonNullableReadType, writeType, inferrer.library.library);
@@ -3032,8 +3032,7 @@
.member;
DartType originalReadType = readType;
- DartType nonNullableReadType =
- inferrer.computeNonNullable(originalReadType);
+ DartType nonNullableReadType = originalReadType.toNonNull();
DartType inferredType = inferrer.typeSchemaEnvironment
.getStandardUpperBound(nonNullableReadType, writeResult.inferredType,
inferrer.library.library);
@@ -3411,7 +3410,7 @@
Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
inferrer.flowAnalysis.ifNullExpression_end();
- DartType nonNullableReadType = inferrer.computeNonNullable(readType);
+ DartType nonNullableReadType = readType.toNonNull();
DartType inferredType = inferrer.typeSchemaEnvironment
.getStandardUpperBound(nonNullableReadType, valueResult.inferredType,
inferrer.library.library);
@@ -3592,7 +3591,7 @@
Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
inferrer.flowAnalysis.ifNullExpression_end();
- DartType nonNullableReadType = inferrer.computeNonNullable(readType);
+ DartType nonNullableReadType = readType.toNonNull();
DartType inferredType = inferrer.typeSchemaEnvironment
.getStandardUpperBound(nonNullableReadType, valueResult.inferredType,
inferrer.library.library);
@@ -3767,7 +3766,7 @@
Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
inferrer.flowAnalysis.ifNullExpression_end();
- DartType nonNullableReadType = inferrer.computeNonNullable(readType);
+ DartType nonNullableReadType = readType.toNonNull();
DartType inferredType = inferrer.typeSchemaEnvironment
.getStandardUpperBound(nonNullableReadType, valueResult.inferredType,
inferrer.library.library);
@@ -5211,7 +5210,7 @@
inferrer.createNullAwareGuard(receiverVariable);
Expression readReceiver = createVariableGet(receiverVariable);
Expression writeReceiver = createVariableGet(receiverVariable);
- DartType nonNullReceiverType = inferrer.computeNonNullable(receiverType);
+ DartType nonNullReceiverType = receiverType.toNonNull();
ExpressionInferenceResult readResult = _computePropertyGet(
node.readOffset,
@@ -5747,7 +5746,7 @@
inferrer.createNullAwareGuard(receiverVariable);
Expression readReceiver = createVariableGet(receiverVariable);
Expression writeReceiver = createVariableGet(receiverVariable);
- DartType nonNullReceiverType = inferrer.computeNonNullable(receiverType);
+ DartType nonNullReceiverType = receiverType.toNonNull();
ExpressionInferenceResult readResult = _computePropertyGet(node.readOffset,
readReceiver, nonNullReceiverType, node.name, typeContext,
@@ -5783,7 +5782,7 @@
inferrer.flowAnalysis.ifNullExpression_end();
- DartType nonNullableReadType = inferrer.computeNonNullable(readType);
+ DartType nonNullableReadType = readType.toNonNull();
DartType inferredType = inferrer.typeSchemaEnvironment
.getStandardUpperBound(nonNullableReadType, valueResult.inferredType,
inferrer.library.library);
@@ -6710,7 +6709,7 @@
inferrer.flowAnalysis.thisOrSuper(node, variable.type);
} else if (inferrer.isNonNullableByDefault) {
if (node.forNullGuardedAccess) {
- DartType nonNullableType = inferrer.computeNonNullable(variable.type);
+ DartType nonNullableType = variable.type.toNonNull();
if (nonNullableType != variable.type) {
promotedType = nonNullableType;
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index 2e20f55..4a87e32 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -18,9 +18,7 @@
InterfaceType,
Member,
NamedType,
- NeverType,
NullType,
- Nullability,
Statement,
TreeNode,
TypeParameter,
@@ -310,19 +308,7 @@
@override
DartType promoteToNonNull(DartType type) {
- if (type is TypeParameterType &&
- type.declaredNullability != Nullability.nullable) {
- DartType bound =
- type.bound.withDeclaredNullability(Nullability.nonNullable);
- if (bound != type.bound) {
- return new TypeParameterType(
- type.parameter, type.declaredNullability, bound);
- }
- return type;
- } else if (type is NullType) {
- return const NeverType.nonNullable();
- }
- return type.withDeclaredNullability(Nullability.nonNullable);
+ return type.toNonNull();
}
@override
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 2d7a818..38e0a42 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -264,17 +264,6 @@
return type.withDeclaredNullability(library.nullable);
}
- DartType computeNonNullable(DartType type) {
- if (type is NullType) {
- return isNonNullableByDefault ? const NeverType.nonNullable() : type;
- }
- if (type is TypeParameterType && type.promotedBound != null) {
- return new TypeParameterType(type.parameter, Nullability.nonNullable,
- computeNonNullable(type.promotedBound));
- }
- return type.withDeclaredNullability(library.nonNullable);
- }
-
Expression createReachabilityError(
int fileOffset, Message errorMessage, Message warningMessage) {
if (library.loader.target.context.options.warnOnReachabilityCheck &&
@@ -1192,8 +1181,8 @@
// invalid.
target = _findExtensionMember(
isNonNullableByDefault
- ? computeNonNullable(receiverType)
- : computeNonNullable(receiverBound),
+ ? receiverType.toNonNull()
+ : receiverBound.toNonNull(),
classNode,
name,
fileOffset,
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
index 883df40..cce226f 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
@@ -95,6 +95,9 @@
UnknownType withDeclaredNullability(Nullability nullability) => this;
@override
+ UnknownType toNonNull() => this;
+
+ @override
void toTextInternal(AstPrinter printer) {
printer.write('?');
}
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index bdc0a87..0da4649 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -874,7 +874,6 @@
result, runResult.outcome, runResult.error);
case "aot":
case "none":
- case "noneWithJs":
case "dart2js":
case "dartdevc":
// TODO(johnniwinther): Support running vm aot, dart2js and/or dartdevc.
@@ -1725,9 +1724,6 @@
case "none":
target = new NoneTarget(targetFlags);
break;
- case "noneWithJs":
- target = new NoneWithJsTarget(targetFlags);
- break;
case "dart2js":
target = new TestDart2jsTarget('dart2js', targetFlags);
break;
@@ -2140,14 +2136,6 @@
}
}
-class NoneWithJsTarget extends NoneTarget {
- NoneWithJsTarget(TargetFlags flags) : super(flags);
-
- @override
- ConstantsBackend constantsBackend(CoreTypes coreTypes) =>
- const NoneConstantsBackendWithJs(supportsUnevaluatedConstants: true);
-}
-
class NoneConstantsBackendWithJs extends NoneConstantsBackend {
const NoneConstantsBackendWithJs({bool supportsUnevaluatedConstants})
: super(supportsUnevaluatedConstants: supportsUnevaluatedConstants);
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart
index 6ceb6c7..67cfacc 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart
@@ -383,13 +383,9 @@
parseTestLibrary("");
checkLowerBound(
- type1: "Object",
- type2: "FutureOr<Null>",
- lowerBound: "FutureOr<Never>");
+ type1: "Object", type2: "FutureOr<Null>", lowerBound: "Never");
checkLowerBound(
- type1: "FutureOr<Null>",
- type2: "Object",
- lowerBound: "FutureOr<Never>");
+ type1: "FutureOr<Null>", type2: "Object", lowerBound: "Never");
// FutureOr<dynamic> is top.
checkLowerBound(
@@ -1329,6 +1325,59 @@
type2: "T",
upperBound: "List<Object?>",
typeParameters: "T extends List<T>, U extends List<Never>");
+ checkUpperBound(
+ type1: "T",
+ type2: "T",
+ upperBound: "T",
+ typeParameters: "T extends Object?");
+
+ // These cases are observed through `a ?? b`. Here the resulting type
+ // is `UP(NonNull(a),b)`, if `b` is `null`, is `NonNull(a)?`.
+
+ // We have
+ //
+ // NonNull(T extends Object?) = T & Object
+ //
+ // resulting in
+ //
+ // (T & Object)? = T? & Object
+ //
+ checkUpperBound(
+ type1: "T",
+ type2: "Null",
+ upperBound: "T? & Object",
+ typeParameters: "T extends Object?",
+ nonNull1: true);
+
+ // We have
+ //
+ // NonNull(T extends bool?) = T & bool
+ //
+ // resulting in
+ //
+ // (T & bool)? = T? & bool
+ //
+ checkUpperBound(
+ type1: "T",
+ type2: "Null",
+ upperBound: "T? & bool",
+ typeParameters: "T extends bool?",
+ nonNull1: true);
+
+ // We have
+ //
+ // NonNull(T extends bool) = T
+ //
+ // resulting in
+ //
+ // (T)? = T?
+ //
+ checkUpperBound(
+ type1: "T",
+ type2: "Null",
+ upperBound: "T?",
+ typeParameters: "T extends bool",
+ nonNull1: true);
}
void test_upper_bound_unknown() {
@@ -1521,16 +1570,29 @@
}
void checkUpperBound(
- {String type1, String type2, String upperBound, String typeParameters}) {
+ {String type1,
+ String type2,
+ String upperBound,
+ String typeParameters,
+ bool nonNull1: false,
+ bool nonNull2: false}) {
assert(type1 != null);
assert(type2 != null);
assert(upperBound != null);
typeParserEnvironment.withTypeParameters(typeParameters,
(List<TypeParameter> typeParameterNodes) {
+ DartType dartType1 = parseType(type1);
+ DartType dartType2 = parseType(type2);
+ if (nonNull1) {
+ dartType1 = dartType1.toNonNull();
+ }
+ if (nonNull2) {
+ dartType2 = dartType2.toNonNull();
+ }
expect(
typeSchemaEnvironment.getStandardUpperBound(
- parseType(type1), parseType(type2), testLibrary),
+ dartType1, dartType2, testLibrary),
parseType(upperBound));
});
}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/folder.options b/pkg/front_end/testcases/general/constants/js_semantics/folder.options
index 674c362..7a017fa 100644
--- a/pkg/front_end/testcases/general/constants/js_semantics/folder.options
+++ b/pkg/front_end/testcases/general/constants/js_semantics/folder.options
@@ -1,2 +1,2 @@
--enable-experiment=triple-shift
---target=noneWithJs
\ No newline at end of file
+--target=dart2js
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart b/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart
new file mode 100644
index 0000000..81c2ce24
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2021, 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.
+
+class MyClass {
+ final int a;
+ final int b;
+ const MyClass(i1, i2) : a = (i1 >>> i2), b = (i1 >>> i2);
+}
+
+test() {
+ const MyClass c1 = MyClass(1.0, 1);
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart.textual_outline.expect
new file mode 100644
index 0000000..c73f11f
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart.textual_outline.expect
@@ -0,0 +1,7 @@
+class MyClass {
+ final int a;
+ final int b;
+ const MyClass(i1, i2) : a = (i1 >>> i2), b = (i1 >>> i2);
+}
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart.weak.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart.weak.expect
new file mode 100644
index 0000000..bdbea12
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart.weak.expect
@@ -0,0 +1,20 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class MyClass extends core::Object /*hasConstConstructor*/ {
+ final field core::int a;
+ final field core::int b;
+ const constructor •(dynamic i1, dynamic i2) → self::MyClass
+ : self::MyClass::a = i1{dynamic}.>>>(i2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int, self::MyClass::b = i1{dynamic}.>>>(i2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int, super core::Object::•()
+ ;
+}
+static method test() → dynamic {}
+static method main() → dynamic {}
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue45376.dart:
+- MyClass. (from org-dartlang-testcase:///issue45376.dart:8:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart.weak.outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart.weak.outline.expect
new file mode 100644
index 0000000..dcdb486
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart.weak.outline.expect
@@ -0,0 +1,15 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class MyClass extends core::Object /*hasConstConstructor*/ {
+ final field core::int a;
+ final field core::int b;
+ const constructor •(dynamic i1, dynamic i2) → self::MyClass
+ : self::MyClass::a = i1{dynamic}.>>>(i2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int, self::MyClass::b = i1{dynamic}.>>>(i2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int, super core::Object::•()
+ ;
+}
+static method test() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart.weak.transformed.expect
new file mode 100644
index 0000000..bdbea12
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue45376.dart.weak.transformed.expect
@@ -0,0 +1,20 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class MyClass extends core::Object /*hasConstConstructor*/ {
+ final field core::int a;
+ final field core::int b;
+ const constructor •(dynamic i1, dynamic i2) → self::MyClass
+ : self::MyClass::a = i1{dynamic}.>>>(i2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int, self::MyClass::b = i1{dynamic}.>>>(i2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int, super core::Object::•()
+ ;
+}
+static method test() → dynamic {}
+static method main() → dynamic {}
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue45376.dart:
+- MyClass. (from org-dartlang-testcase:///issue45376.dart:8:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart b/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart
new file mode 100644
index 0000000..d4598da
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2021, 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.
+
+const dynamic a = 1.0;
+const dynamic b = 1.5;
+
+const dynamic c0 = a >> 1;
+const dynamic c1 = b >> 1;
+const dynamic c2 = a >>> 1;
+const dynamic c3 = b >>> 1;
+
+const dynamic d0 = 1 >> a;
+const dynamic d1 = 1 >> b;
+const dynamic d2 = 1 >>> a;
+const dynamic d3 = 1 >>> b;
+
+class Class {
+ final int a;
+
+ const Class.doubleShift(i1, i2) : a = (i1 >> i2);
+ const Class.tripleShift(i1, i2) : a = (i1 >>> i2);
+}
+
+main() {
+ const Class c1 = Class.doubleShift(a, 1);
+ const Class c2 = Class.doubleShift(b, 1);
+ const Class c3 = Class.tripleShift(a, 1);
+ const Class c4 = Class.tripleShift(b, 1);
+
+ const Class d1 = Class.doubleShift(1, a);
+ const Class d2 = Class.doubleShift(1, b);
+ const Class d3 = Class.tripleShift(1, a);
+ const Class d4 = Class.tripleShift(1, b);
+
+ const Class e1 = Class.doubleShift(1.0, 1);
+ const Class e2 = Class.doubleShift(1.5, 1);
+ const Class e3 = Class.tripleShift(1.0, 1);
+ const Class e4 = Class.tripleShift(1.5, 1);
+}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart.textual_outline.expect
new file mode 100644
index 0000000..006bef5
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart.textual_outline.expect
@@ -0,0 +1,16 @@
+const dynamic a = 1.0;
+const dynamic b = 1.5;
+const dynamic c0 = a >> 1;
+const dynamic c1 = b >> 1;
+const dynamic c2 = a >>> 1;
+const dynamic c3 = b >>> 1;
+const dynamic d0 = 1 >> a;
+const dynamic d1 = 1 >> b;
+const dynamic d2 = 1 >>> a;
+const dynamic d3 = 1 >>> b;
+class Class {
+ final int a;
+ const Class.doubleShift(i1, i2) : a = (i1 >> i2);
+ const Class.tripleShift(i1, i2) : a = (i1 >>> i2);
+}
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart.weak.expect b/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart.weak.expect
new file mode 100644
index 0000000..2573a35
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart.weak.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:27:26: Error: Constant evaluation error:
+// const Class c2 = Class.doubleShift(b, 1);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:21:45: Context: Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const Class.doubleShift(i1, i2) : a = (i1 >> i2);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:27:15: Context: While analyzing:
+// const Class c2 = Class.doubleShift(b, 1);
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:29:26: Error: Constant evaluation error:
+// const Class c4 = Class.tripleShift(b, 1);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:22:45: Context: Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const Class.tripleShift(i1, i2) : a = (i1 >>> i2);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:29:15: Context: While analyzing:
+// const Class c4 = Class.tripleShift(b, 1);
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:32:26: Error: Constant evaluation error:
+// const Class d2 = Class.doubleShift(1, b);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:21:45: Context: Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const Class.doubleShift(i1, i2) : a = (i1 >> i2);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:32:15: Context: While analyzing:
+// const Class d2 = Class.doubleShift(1, b);
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:34:26: Error: Constant evaluation error:
+// const Class d4 = Class.tripleShift(1, b);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:22:45: Context: Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const Class.tripleShift(i1, i2) : a = (i1 >>> i2);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:34:15: Context: While analyzing:
+// const Class d4 = Class.tripleShift(1, b);
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:37:26: Error: Constant evaluation error:
+// const Class e2 = Class.doubleShift(1.5, 1);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:21:45: Context: Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const Class.doubleShift(i1, i2) : a = (i1 >> i2);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:37:15: Context: While analyzing:
+// const Class e2 = Class.doubleShift(1.5, 1);
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:39:26: Error: Constant evaluation error:
+// const Class e4 = Class.tripleShift(1.5, 1);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:22:45: Context: Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const Class.tripleShift(i1, i2) : a = (i1 >>> i2);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:39:15: Context: While analyzing:
+// const Class e4 = Class.tripleShift(1.5, 1);
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:9:22: Error: Constant evaluation error:
+// const dynamic c1 = b >> 1;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:9:22: Context: Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const dynamic c1 = b >> 1;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:9:15: Context: While analyzing:
+// const dynamic c1 = b >> 1;
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:11:22: Error: Constant evaluation error:
+// const dynamic c3 = b >>> 1;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:11:22: Context: Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const dynamic c3 = b >>> 1;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:11:15: Context: While analyzing:
+// const dynamic c3 = b >>> 1;
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:14:22: Error: Constant evaluation error:
+// const dynamic d1 = 1 >> b;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:14:25: Context: Expected constant '1.5' to be of type 'int', but was of type 'double'.
+// const dynamic d1 = 1 >> b;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:14:15: Context: While analyzing:
+// const dynamic d1 = 1 >> b;
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:16:22: Error: Constant evaluation error:
+// const dynamic d3 = 1 >>> b;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:16:26: Context: Expected constant '1.5' to be of type 'int', but was of type 'double'.
+// const dynamic d3 = 1 >>> b;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:16:15: Context: While analyzing:
+// const dynamic d3 = 1 >>> b;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object /*hasConstConstructor*/ {
+ final field core::int a;
+ const constructor doubleShift(dynamic i1, dynamic i2) → self::Class
+ : self::Class::a = i1{dynamic}.>>(i2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int, super core::Object::•()
+ ;
+ const constructor tripleShift(dynamic i1, dynamic i2) → self::Class
+ : self::Class::a = i1{dynamic}.>>>(i2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int, super core::Object::•()
+ ;
+}
+static const field dynamic a = #C1;
+static const field dynamic b = #C2;
+static const field dynamic c0 = #C3;
+static const field dynamic c1 = invalid-expression "Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+static const field dynamic c2 = #C3;
+static const field dynamic c3 = invalid-expression "Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+static const field dynamic d0 = #C3;
+static const field dynamic d1 = invalid-expression "Expected constant '1.5' to be of type 'int', but was of type 'double'.";
+static const field dynamic d2 = #C3;
+static const field dynamic d3 = invalid-expression "Expected constant '1.5' to be of type 'int', but was of type 'double'.";
+static method main() → dynamic {
+ const self::Class c2 = invalid-expression "Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+ const self::Class c4 = invalid-expression "Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+ const self::Class d2 = invalid-expression "Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+ const self::Class d4 = invalid-expression "Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+ const self::Class e2 = invalid-expression "Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+ const self::Class e4 = invalid-expression "Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+}
+
+constants {
+ #C1 = 1.0
+ #C2 = 1.5
+ #C3 = 0.0
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///on_double.dart:
+- Class.doubleShift (from org-dartlang-testcase:///on_double.dart:21:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
+- Class.tripleShift (from org-dartlang-testcase:///on_double.dart:22:9)
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart.weak.outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart.weak.outline.expect
new file mode 100644
index 0000000..c94c041
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart.weak.outline.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object /*hasConstConstructor*/ {
+ final field core::int a;
+ const constructor doubleShift(dynamic i1, dynamic i2) → self::Class
+ : self::Class::a = i1{dynamic}.>>(i2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int, super core::Object::•()
+ ;
+ const constructor tripleShift(dynamic i1, dynamic i2) → self::Class
+ : self::Class::a = i1{dynamic}.>>>(i2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int, super core::Object::•()
+ ;
+}
+static const field dynamic a = 1.0;
+static const field dynamic b = 1.5;
+static const field dynamic c0 = self::a{dynamic}.>>(1);
+static const field dynamic c1 = self::b{dynamic}.>>(1);
+static const field dynamic c2 = self::a{dynamic}.>>>(1);
+static const field dynamic c3 = self::b{dynamic}.>>>(1);
+static const field dynamic d0 = 1.{core::int::>>}(self::a as{TypeError,ForDynamic,ForNonNullableByDefault} core::int){(core::int) → core::int};
+static const field dynamic d1 = 1.{core::int::>>}(self::b as{TypeError,ForDynamic,ForNonNullableByDefault} core::int){(core::int) → core::int};
+static const field dynamic d2 = 1.{core::int::>>>}(self::a as{TypeError,ForDynamic,ForNonNullableByDefault} core::int){(core::int) → core::int};
+static const field dynamic d3 = 1.{core::int::>>>}(self::b as{TypeError,ForDynamic,ForNonNullableByDefault} core::int){(core::int) → core::int};
+static method main() → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: DynamicInvocation @ org-dartlang-testcase:///on_double.dart:8:22 -> DoubleConstant(0.0)
+Evaluated: StaticGet @ org-dartlang-testcase:///on_double.dart:9:20 -> DoubleConstant(1.5)
+Evaluated: DynamicInvocation @ org-dartlang-testcase:///on_double.dart:10:22 -> DoubleConstant(0.0)
+Evaluated: StaticGet @ org-dartlang-testcase:///on_double.dart:11:20 -> DoubleConstant(1.5)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///on_double.dart:13:22 -> DoubleConstant(0.0)
+Evaluated: StaticGet @ org-dartlang-testcase:///on_double.dart:14:25 -> DoubleConstant(1.5)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///on_double.dart:15:22 -> DoubleConstant(0.0)
+Evaluated: StaticGet @ org-dartlang-testcase:///on_double.dart:16:26 -> DoubleConstant(1.5)
+Extra constant evaluation: evaluated: 22, effectively constant: 8
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart.weak.transformed.expect
new file mode 100644
index 0000000..2573a35
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/on_double.dart.weak.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:27:26: Error: Constant evaluation error:
+// const Class c2 = Class.doubleShift(b, 1);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:21:45: Context: Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const Class.doubleShift(i1, i2) : a = (i1 >> i2);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:27:15: Context: While analyzing:
+// const Class c2 = Class.doubleShift(b, 1);
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:29:26: Error: Constant evaluation error:
+// const Class c4 = Class.tripleShift(b, 1);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:22:45: Context: Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const Class.tripleShift(i1, i2) : a = (i1 >>> i2);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:29:15: Context: While analyzing:
+// const Class c4 = Class.tripleShift(b, 1);
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:32:26: Error: Constant evaluation error:
+// const Class d2 = Class.doubleShift(1, b);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:21:45: Context: Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const Class.doubleShift(i1, i2) : a = (i1 >> i2);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:32:15: Context: While analyzing:
+// const Class d2 = Class.doubleShift(1, b);
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:34:26: Error: Constant evaluation error:
+// const Class d4 = Class.tripleShift(1, b);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:22:45: Context: Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const Class.tripleShift(i1, i2) : a = (i1 >>> i2);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:34:15: Context: While analyzing:
+// const Class d4 = Class.tripleShift(1, b);
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:37:26: Error: Constant evaluation error:
+// const Class e2 = Class.doubleShift(1.5, 1);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:21:45: Context: Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const Class.doubleShift(i1, i2) : a = (i1 >> i2);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:37:15: Context: While analyzing:
+// const Class e2 = Class.doubleShift(1.5, 1);
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:39:26: Error: Constant evaluation error:
+// const Class e4 = Class.tripleShift(1.5, 1);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:22:45: Context: Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const Class.tripleShift(i1, i2) : a = (i1 >>> i2);
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:39:15: Context: While analyzing:
+// const Class e4 = Class.tripleShift(1.5, 1);
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:9:22: Error: Constant evaluation error:
+// const dynamic c1 = b >> 1;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:9:22: Context: Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const dynamic c1 = b >> 1;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:9:15: Context: While analyzing:
+// const dynamic c1 = b >> 1;
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:11:22: Error: Constant evaluation error:
+// const dynamic c3 = b >>> 1;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:11:22: Context: Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.
+// const dynamic c3 = b >>> 1;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:11:15: Context: While analyzing:
+// const dynamic c3 = b >>> 1;
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:14:22: Error: Constant evaluation error:
+// const dynamic d1 = 1 >> b;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:14:25: Context: Expected constant '1.5' to be of type 'int', but was of type 'double'.
+// const dynamic d1 = 1 >> b;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:14:15: Context: While analyzing:
+// const dynamic d1 = 1 >> b;
+// ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:16:22: Error: Constant evaluation error:
+// const dynamic d3 = 1 >>> b;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:16:26: Context: Expected constant '1.5' to be of type 'int', but was of type 'double'.
+// const dynamic d3 = 1 >>> b;
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/on_double.dart:16:15: Context: While analyzing:
+// const dynamic d3 = 1 >>> b;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object /*hasConstConstructor*/ {
+ final field core::int a;
+ const constructor doubleShift(dynamic i1, dynamic i2) → self::Class
+ : self::Class::a = i1{dynamic}.>>(i2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int, super core::Object::•()
+ ;
+ const constructor tripleShift(dynamic i1, dynamic i2) → self::Class
+ : self::Class::a = i1{dynamic}.>>>(i2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int, super core::Object::•()
+ ;
+}
+static const field dynamic a = #C1;
+static const field dynamic b = #C2;
+static const field dynamic c0 = #C3;
+static const field dynamic c1 = invalid-expression "Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+static const field dynamic c2 = #C3;
+static const field dynamic c3 = invalid-expression "Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+static const field dynamic d0 = #C3;
+static const field dynamic d1 = invalid-expression "Expected constant '1.5' to be of type 'int', but was of type 'double'.";
+static const field dynamic d2 = #C3;
+static const field dynamic d3 = invalid-expression "Expected constant '1.5' to be of type 'int', but was of type 'double'.";
+static method main() → dynamic {
+ const self::Class c2 = invalid-expression "Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+ const self::Class c4 = invalid-expression "Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+ const self::Class d2 = invalid-expression "Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+ const self::Class d4 = invalid-expression "Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+ const self::Class e2 = invalid-expression "Binary operator '>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+ const self::Class e4 = invalid-expression "Binary operator '>>>' on '1.5' requires operand of type 'int', but was of type 'double'.";
+}
+
+constants {
+ #C1 = 1.0
+ #C2 = 1.5
+ #C3 = 0.0
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///on_double.dart:
+- Class.doubleShift (from org-dartlang-testcase:///on_double.dart:21:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
+- Class.tripleShift (from org-dartlang-testcase:///on_double.dart:22:9)
diff --git a/pkg/front_end/testcases/general/null_check_type_variable_type.dart b/pkg/front_end/testcases/general/null_check_type_variable_type.dart
new file mode 100644
index 0000000..30f0312
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_check_type_variable_type.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2021, 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.
+
+class Element {}
+
+class Class<E extends Element?> {
+ E? element;
+
+ Class(this.element);
+
+ void setElement(E? element) {
+ if (this.element != element) {
+ this.element = element;
+ Set<Element> elements = new Set<Element>();
+ if (element != null) {
+ elements.add(element);
+ }
+ if (this.element != null) {
+ elements.add(this.element!);
+ }
+ }
+ }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/null_check_type_variable_type.dart.textual_outline.expect b/pkg/front_end/testcases/general/null_check_type_variable_type.dart.textual_outline.expect
new file mode 100644
index 0000000..e380d41
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_check_type_variable_type.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+class Element {}
+
+class Class<E extends Element?> {
+ E? element;
+ Class(this.element);
+ void setElement(E? element) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/null_check_type_variable_type.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/null_check_type_variable_type.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c1b9d90
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_check_type_variable_type.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Class<E extends Element?> {
+ Class(this.element);
+ E? element;
+ void setElement(E? element) {}
+}
+
+class Element {}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/null_check_type_variable_type.dart.weak.expect b/pkg/front_end/testcases/general/null_check_type_variable_type.dart.weak.expect
new file mode 100644
index 0000000..6972fb1
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_check_type_variable_type.dart.weak.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class Element extends core::Object {
+ synthetic constructor •() → self::Element
+ : super core::Object::•()
+ ;
+}
+class Class<E extends self::Element? = self::Element?> extends core::Object {
+ generic-covariant-impl field self::Class::E? element;
+ constructor •(self::Class::E? element) → self::Class<self::Class::E%>
+ : self::Class::element = element, super core::Object::•()
+ ;
+ method setElement(generic-covariant-impl self::Class::E? element) → void {
+ if(!this.{self::Class::element}.{core::Object::==}(element)) {
+ this.{self::Class::element} = element;
+ core::Set<self::Element> elements = col::LinkedHashSet::•<self::Element>();
+ if(!element.{core::Object::==}(null)) {
+ elements.{core::Set::add}(element{self::Class::E% & self::Element /* '%' & '!' = '!' */});
+ }
+ if(!this.{self::Class::element}.{core::Object::==}(null)) {
+ elements.{core::Set::add}(this.{self::Class::element}!);
+ }
+ }
+ }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/null_check_type_variable_type.dart.weak.outline.expect b/pkg/front_end/testcases/general/null_check_type_variable_type.dart.weak.outline.expect
new file mode 100644
index 0000000..199055c
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_check_type_variable_type.dart.weak.outline.expect
@@ -0,0 +1,17 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Element extends core::Object {
+ synthetic constructor •() → self::Element
+ ;
+}
+class Class<E extends self::Element? = self::Element?> extends core::Object {
+ generic-covariant-impl field self::Class::E? element;
+ constructor •(self::Class::E? element) → self::Class<self::Class::E%>
+ ;
+ method setElement(generic-covariant-impl self::Class::E? element) → void
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/null_check_type_variable_type.dart.weak.transformed.expect b/pkg/front_end/testcases/general/null_check_type_variable_type.dart.weak.transformed.expect
new file mode 100644
index 0000000..6405a73
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_check_type_variable_type.dart.weak.transformed.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class Element extends core::Object {
+ synthetic constructor •() → self::Element
+ : super core::Object::•()
+ ;
+}
+class Class<E extends self::Element? = self::Element?> extends core::Object {
+ generic-covariant-impl field self::Class::E? element;
+ constructor •(self::Class::E? element) → self::Class<self::Class::E%>
+ : self::Class::element = element, super core::Object::•()
+ ;
+ method setElement(generic-covariant-impl self::Class::E? element) → void {
+ if(!this.{self::Class::element}.{core::Object::==}(element)) {
+ this.{self::Class::element} = element;
+ core::Set<self::Element> elements = new col::_CompactLinkedHashSet::•<self::Element>();
+ if(!element.{core::Object::==}(null)) {
+ elements.{core::Set::add}(element{self::Class::E% & self::Element /* '%' & '!' = '!' */});
+ }
+ if(!this.{self::Class::element}.{core::Object::==}(null)) {
+ elements.{core::Set::add}(this.{self::Class::element}!);
+ }
+ }
+ }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.strong.expect
index d15a9c9..3bfcc52 100644
--- a/pkg/front_end/testcases/nnbd/issue43278.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.strong.expect
@@ -19,15 +19,8 @@
// b.fooExtension ??= x; // Error.
// ^^^^^^^^^^^^
//
-// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The getter 'fooExtension' isn't defined for the class 'B?'.
-// - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'fooExtension'.
-// t.fooExtension ??= x; // Error.
-// ^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The setter 'fooExtension' isn't defined for the class 'B?'.
-// - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-// Try correcting the name to the name of an existing setter, or defining a setter or field named 'fooExtension'.
+// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+// Try accessing using ?. instead.
// t.fooExtension ??= x; // Error.
// ^^^^^^^^^^^^
//
@@ -86,15 +79,13 @@
Try accessing using ?. instead.
b.fooExtension ??= x; // Error.
^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t10, x) : null;
- let final self::testExtension::T% #t13 = t in invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The getter 'fooExtension' isn't defined for the class 'B?'.
- - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'fooExtension'.
+ let final self::testExtension::T% #t13 = t in (let final Never #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
t.fooExtension ??= x; // Error.
- ^^^^^^^^^^^^".{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The setter 'fooExtension' isn't defined for the class 'B?'.
- - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-Try correcting the name to the name of an existing setter, or defining a setter or field named 'fooExtension'.
+ ^^^^^^^^^^^^" in self::Extension|get#fooExtension(#t13)).{core::num::==}(null) ?{core::int} let final Never #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
t.fooExtension ??= x; // Error.
- ^^^^^^^^^^^^" : null;
- let final self::B? #t14 = b in #t14.{core::Object::==}(null) ?{core::int?} null : let final self::B #t15 = self::Extension|get#barExtension(#t14{self::B}) in self::Extension|get#fooExtension(#t15).{core::num::==}(null) ?{core::int} self::Extension|set#fooExtension(#t15, x) : null;
+ ^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t13, x) : null;
+ let final self::B? #t16 = b in #t16.{core::Object::==}(null) ?{core::int?} null : let final self::B #t17 = self::Extension|get#barExtension(#t16{self::B}) in self::Extension|get#fooExtension(#t17).{core::num::==}(null) ?{core::int} self::Extension|set#fooExtension(#t17, x) : null;
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.strong.transformed.expect
index d15a9c9..3bfcc52 100644
--- a/pkg/front_end/testcases/nnbd/issue43278.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.strong.transformed.expect
@@ -19,15 +19,8 @@
// b.fooExtension ??= x; // Error.
// ^^^^^^^^^^^^
//
-// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The getter 'fooExtension' isn't defined for the class 'B?'.
-// - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'fooExtension'.
-// t.fooExtension ??= x; // Error.
-// ^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The setter 'fooExtension' isn't defined for the class 'B?'.
-// - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-// Try correcting the name to the name of an existing setter, or defining a setter or field named 'fooExtension'.
+// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+// Try accessing using ?. instead.
// t.fooExtension ??= x; // Error.
// ^^^^^^^^^^^^
//
@@ -86,15 +79,13 @@
Try accessing using ?. instead.
b.fooExtension ??= x; // Error.
^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t10, x) : null;
- let final self::testExtension::T% #t13 = t in invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The getter 'fooExtension' isn't defined for the class 'B?'.
- - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'fooExtension'.
+ let final self::testExtension::T% #t13 = t in (let final Never #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
t.fooExtension ??= x; // Error.
- ^^^^^^^^^^^^".{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The setter 'fooExtension' isn't defined for the class 'B?'.
- - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-Try correcting the name to the name of an existing setter, or defining a setter or field named 'fooExtension'.
+ ^^^^^^^^^^^^" in self::Extension|get#fooExtension(#t13)).{core::num::==}(null) ?{core::int} let final Never #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
t.fooExtension ??= x; // Error.
- ^^^^^^^^^^^^" : null;
- let final self::B? #t14 = b in #t14.{core::Object::==}(null) ?{core::int?} null : let final self::B #t15 = self::Extension|get#barExtension(#t14{self::B}) in self::Extension|get#fooExtension(#t15).{core::num::==}(null) ?{core::int} self::Extension|set#fooExtension(#t15, x) : null;
+ ^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t13, x) : null;
+ let final self::B? #t16 = b in #t16.{core::Object::==}(null) ?{core::int?} null : let final self::B #t17 = self::Extension|get#barExtension(#t16{self::B}) in self::Extension|get#fooExtension(#t17).{core::num::==}(null) ?{core::int} self::Extension|set#fooExtension(#t17, x) : null;
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.weak.expect
index d15a9c9..3bfcc52 100644
--- a/pkg/front_end/testcases/nnbd/issue43278.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.weak.expect
@@ -19,15 +19,8 @@
// b.fooExtension ??= x; // Error.
// ^^^^^^^^^^^^
//
-// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The getter 'fooExtension' isn't defined for the class 'B?'.
-// - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'fooExtension'.
-// t.fooExtension ??= x; // Error.
-// ^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The setter 'fooExtension' isn't defined for the class 'B?'.
-// - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-// Try correcting the name to the name of an existing setter, or defining a setter or field named 'fooExtension'.
+// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+// Try accessing using ?. instead.
// t.fooExtension ??= x; // Error.
// ^^^^^^^^^^^^
//
@@ -86,15 +79,13 @@
Try accessing using ?. instead.
b.fooExtension ??= x; // Error.
^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t10, x) : null;
- let final self::testExtension::T% #t13 = t in invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The getter 'fooExtension' isn't defined for the class 'B?'.
- - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'fooExtension'.
+ let final self::testExtension::T% #t13 = t in (let final Never #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
t.fooExtension ??= x; // Error.
- ^^^^^^^^^^^^".{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The setter 'fooExtension' isn't defined for the class 'B?'.
- - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-Try correcting the name to the name of an existing setter, or defining a setter or field named 'fooExtension'.
+ ^^^^^^^^^^^^" in self::Extension|get#fooExtension(#t13)).{core::num::==}(null) ?{core::int} let final Never #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
t.fooExtension ??= x; // Error.
- ^^^^^^^^^^^^" : null;
- let final self::B? #t14 = b in #t14.{core::Object::==}(null) ?{core::int?} null : let final self::B #t15 = self::Extension|get#barExtension(#t14{self::B}) in self::Extension|get#fooExtension(#t15).{core::num::==}(null) ?{core::int} self::Extension|set#fooExtension(#t15, x) : null;
+ ^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t13, x) : null;
+ let final self::B? #t16 = b in #t16.{core::Object::==}(null) ?{core::int?} null : let final self::B #t17 = self::Extension|get#barExtension(#t16{self::B}) in self::Extension|get#fooExtension(#t17).{core::num::==}(null) ?{core::int} self::Extension|set#fooExtension(#t17, x) : null;
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.weak.transformed.expect
index d15a9c9..3bfcc52 100644
--- a/pkg/front_end/testcases/nnbd/issue43278.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.weak.transformed.expect
@@ -19,15 +19,8 @@
// b.fooExtension ??= x; // Error.
// ^^^^^^^^^^^^
//
-// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The getter 'fooExtension' isn't defined for the class 'B?'.
-// - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'fooExtension'.
-// t.fooExtension ??= x; // Error.
-// ^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The setter 'fooExtension' isn't defined for the class 'B?'.
-// - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-// Try correcting the name to the name of an existing setter, or defining a setter or field named 'fooExtension'.
+// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+// Try accessing using ?. instead.
// t.fooExtension ??= x; // Error.
// ^^^^^^^^^^^^
//
@@ -86,15 +79,13 @@
Try accessing using ?. instead.
b.fooExtension ??= x; // Error.
^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t10, x) : null;
- let final self::testExtension::T% #t13 = t in invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The getter 'fooExtension' isn't defined for the class 'B?'.
- - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'fooExtension'.
+ let final self::testExtension::T% #t13 = t in (let final Never #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
t.fooExtension ??= x; // Error.
- ^^^^^^^^^^^^".{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: The setter 'fooExtension' isn't defined for the class 'B?'.
- - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
-Try correcting the name to the name of an existing setter, or defining a setter or field named 'fooExtension'.
+ ^^^^^^^^^^^^" in self::Extension|get#fooExtension(#t13)).{core::num::==}(null) ?{core::int} let final Never #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
t.fooExtension ??= x; // Error.
- ^^^^^^^^^^^^" : null;
- let final self::B? #t14 = b in #t14.{core::Object::==}(null) ?{core::int?} null : let final self::B #t15 = self::Extension|get#barExtension(#t14{self::B}) in self::Extension|get#fooExtension(#t15).{core::num::==}(null) ?{core::int} self::Extension|set#fooExtension(#t15, x) : null;
+ ^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t13, x) : null;
+ let final self::B? #t16 = b in #t16.{core::Object::==}(null) ?{core::int?} null : let final self::B #t17 = self::Extension|get#barExtension(#t16{self::B}) in self::Extension|get#fooExtension(#t17).{core::num::==}(null) ?{core::int} self::Extension|set#fooExtension(#t17, x) : null;
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index a8397df..66bc9f8 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -30,7 +30,9 @@
general/bad_setter_abstract: FormatterCrash
general/bug31124: FormatterCrash
general/clone_function_type: FormatterCrash
+general/constants/js_semantics/issue45376: FormatterCrash
general/constants/js_semantics/number_folds: FormatterCrash
+general/constants/js_semantics/on_double: FormatterCrash
general/constants/number_folds: FormatterCrash
general/constants/various: FormatterCrash
general/constructor_initializer_invalid: FormatterCrash
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 3298c90..fde2440 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -84,6 +84,7 @@
import 'type_algebra.dart';
import 'type_environment.dart';
import 'src/assumptions.dart';
+import 'src/non_null.dart';
import 'src/printer.dart';
import 'src/text_util.dart';
@@ -10394,6 +10395,14 @@
/// `void`, or `bottom`.
DartType withDeclaredNullability(Nullability declaredNullability);
+ /// Creates the type corresponding to this type without null, if possible.
+ ///
+ /// Note that not all types, for instance `dynamic`, have a corresponding
+ /// non-nullable type. For these, the type itself is returned.
+ ///
+ /// This corresponds to the `NonNull` function of the nnbd specification.
+ DartType toNonNull() => computeNonNull(this);
+
/// Checks if the type is potentially nullable.
///
/// A type is potentially nullable if it's nullable or if its nullability is
@@ -11577,9 +11586,6 @@
if (declaredNullability == this.declaredNullability) {
return this;
}
- // TODO(dmitryas): Consider removing the assert.
- assert(promotedBound == null,
- "Can't change the nullability attribute of an intersection type.");
return new TypeParameterType(parameter, declaredNullability, promotedBound);
}
diff --git a/pkg/kernel/lib/src/non_null.dart b/pkg/kernel/lib/src/non_null.dart
index d8b3c73..b0e7cd2 100644
--- a/pkg/kernel/lib/src/non_null.dart
+++ b/pkg/kernel/lib/src/non_null.dart
@@ -4,7 +4,7 @@
import '../ast.dart';
-/// Returns the type defines as `NonNull(type)` in the nnbd specification.
+/// Returns the type defined as `NonNull(type)` in the nnbd specification.
DartType computeNonNull(DartType type) {
return type.accept(const _NonNullVisitor()) ?? type;
}
@@ -23,10 +23,18 @@
}
@override
- DartType? visitDynamicType(DynamicType node) => null;
+ DartType? visitDynamicType(DynamicType node) {
+ // NonNull(dynamic) = dynamic
+ return null;
+ }
@override
DartType? visitFunctionType(FunctionType node) {
+ // NonNull(T0 Function(...)) = T0 Function(...)
+ //
+ // NonNull(T?) = NonNull(T)
+ //
+ // NonNull(T*) = NonNull(T)
if (node.declaredNullability == Nullability.nonNullable) {
return null;
}
@@ -35,17 +43,51 @@
@override
DartType? visitFutureOrType(FutureOrType node) {
- DartType? typeArgument = node.typeArgument.accept(this);
- if (node.declaredNullability == Nullability.nonNullable &&
- typeArgument == null) {
+ // NonNull(FutureOr<T>) = FutureOr<T>
+ //
+ // NonNull(T?) = NonNull(T)
+ //
+ // NonNull(T*) = NonNull(T)
+
+ // Note that we should _not_ compute NonNull of the type argument. Consider
+ //
+ // NonNull(FutureOr<int?>?)
+ //
+ // We have that
+ //
+ // FutureOr<int?>? = Future<int?>? | int?
+ //
+ // and therefore that
+ //
+ // NonNull(FutureOr<int?>?) = NonNull(FutureOr<int?>?) | NonNull(int?)
+ // = FutureOr<int?> | int
+ //
+ // but that means that while `null` is not a possible value from `int` it
+ // is still a possible value from awaiting the future. Taking NonNull on
+ // the type argument as well as on the `FutureOr`:
+ //
+ // NonNull(FutureOr<int?>?) = NonNull(FutureOr<NonNull(int?)>?)
+ // = FutureOr<int>
+ //
+ // would be wrong since it would compute that the awaited result could not
+ // be `null`.
+
+ if (node.declaredNullability == Nullability.nonNullable) {
return null;
}
- return new FutureOrType(
- typeArgument ?? node.typeArgument, Nullability.nonNullable);
+ return new FutureOrType(node.typeArgument, Nullability.nonNullable);
}
@override
DartType? visitInterfaceType(InterfaceType node) {
+ // NonNull(C<T1, ... , Tn>) = C<T1, ... , Tn> for class C other
+ // than Null (including Object).
+ //
+ // NonNull(Function) = Function
+ //
+ // NonNull(T?) = NonNull(T)
+ //
+ // NonNull(T*) = NonNull(T)
if (node.declaredNullability == Nullability.nonNullable) {
return null;
}
@@ -54,6 +96,12 @@
@override
DartType? visitExtensionType(ExtensionType node) {
+ // NonNull(C<T1, ... , Tn>) = C<T1, ... , Tn> for class C other
+ // than Null (including Object).
+ //
+ // NonNull(T?) = NonNull(T)
+ //
+ // NonNull(T*) = NonNull(T)
if (node.declaredNullability == Nullability.nonNullable) {
return null;
}
@@ -65,6 +113,11 @@
@override
DartType? visitNeverType(NeverType node) {
+ // NonNull(Never) = Never
+ //
+ // NonNull(T?) = NonNull(T)
+ //
+ // NonNull(T*) = NonNull(T)
if (node.declaredNullability == Nullability.nonNullable) {
return null;
}
@@ -73,15 +126,25 @@
@override
DartType? visitNullType(NullType node) {
+ // NonNull(Null) = Never
return const NeverType.nonNullable();
}
@override
DartType? visitTypeParameterType(TypeParameterType node) {
+ // NonNull(X) = X & NonNull(B), where B is the bound of X.
+ //
+ // NonNull(X & T) = X & NonNull(T)
+ //
+ // NonNull(T?) = NonNull(T)
+ //
+ // NonNull(T*) = NonNull(T)
if (node.nullability == Nullability.nonNullable) {
return null;
}
if (node.promotedBound != null) {
+ // NonNull(X & T) = X & NonNull(T)
+
if (node.promotedBound!.nullability == Nullability.nonNullable) {
// The promoted bound is already non-nullable so we set the declared
// nullability to non-nullable.
@@ -108,6 +171,7 @@
node.parameter, Nullability.undetermined, promotedBound);
}
} else {
+ // NonNull(X) = X & NonNull(B), where B is the bound of X.
if (node.bound.nullability == Nullability.nonNullable) {
// The bound is already non-nullable so we set the declared nullability
// to non-nullable.
@@ -134,6 +198,12 @@
@override
DartType? visitTypedefType(TypedefType node) {
+ // NonNull(C<T1, ... , Tn>) = C<T1, ... , Tn> for class C other
+ // than Null (including Object).
+ //
+ // NonNull(T?) = NonNull(T)
+ //
+ // NonNull(T*) = NonNull(T)
if (node.declaredNullability == Nullability.nonNullable) {
return null;
}
@@ -141,5 +211,8 @@
}
@override
- DartType? visitVoidType(VoidType node) => null;
+ DartType? visitVoidType(VoidType node) {
+ // NonNull(void) = void
+ return null;
+ }
}
diff --git a/pkg/kernel/test/non_null_test.dart b/pkg/kernel/test/non_null_test.dart
index ef3b433..5a3dca1 100644
--- a/pkg/kernel/test/non_null_test.dart
+++ b/pkg/kernel/test/non_null_test.dart
@@ -29,18 +29,18 @@
'List<Object*>': 'List<Object*>',
'List<Object*>?': 'List<Object*>',
'List<Object*>*': 'List<Object*>',
- 'FutureOr<Null>': 'FutureOr<Never>',
+ 'FutureOr<Null>': 'FutureOr<Null>',
'FutureOr<dynamic>': 'FutureOr<dynamic>',
'FutureOr<Object>': 'FutureOr<Object>',
'FutureOr<Object>?': 'FutureOr<Object>',
'FutureOr<Object>*': 'FutureOr<Object>',
- 'FutureOr<Object?>': 'FutureOr<Object>',
- 'FutureOr<Object?>?': 'FutureOr<Object>',
- 'FutureOr<Object?>*': 'FutureOr<Object>',
- 'FutureOr<Object*>': 'FutureOr<Object>',
- 'FutureOr<Object*>?': 'FutureOr<Object>',
- 'FutureOr<Object*>*': 'FutureOr<Object>',
- 'FutureOr<FutureOr<Object?>>': 'FutureOr<FutureOr<Object>>',
+ 'FutureOr<Object?>': 'FutureOr<Object?>',
+ 'FutureOr<Object?>?': 'FutureOr<Object?>',
+ 'FutureOr<Object?>*': 'FutureOr<Object?>',
+ 'FutureOr<Object*>': 'FutureOr<Object*>',
+ 'FutureOr<Object*>?': 'FutureOr<Object*>',
+ 'FutureOr<Object*>*': 'FutureOr<Object*>',
+ 'FutureOr<FutureOr<Object?>>': 'FutureOr<FutureOr<Object?>>',
'(List<Object>, {required List<Object> a, List<Object> b}) -> List<Object>':
'(List<Object>, {required List<Object> a, List<Object> b})'
' -> List<Object>',
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 6c22c21..fa9e3e8 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -199,7 +199,7 @@
V(::, reachabilityFence, ReachabilityFence, 0x619235c1) \
V(_Utf8Decoder, _scan, Utf8DecoderScan, 0x4983e111) \
V(_Future, timeout, FutureTimeout, 0xc83eaf79) \
- V(Future, wait, FutureWait, 0x99cfb096) \
+ V(Future, wait, FutureWait, 0xc71e731d) \
V(_RootZone, runUnary, RootZoneRunUnary, 0x966a802c) \
V(_FutureListener, handleValue, FutureListenerHandleValue, 0x165b47c4) \
diff --git a/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart b/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
index 303c5a4..655006c 100644
--- a/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
@@ -8,7 +8,7 @@
import 'dart:typed_data';
import 'dart:isolate';
-DynamicLibrary _open(String name) native "Ffi_dl_open";
+DynamicLibrary _open(String path) native "Ffi_dl_open";
DynamicLibrary _processLibrary() native "Ffi_dl_processLibrary";
DynamicLibrary _executableLibrary() native "Ffi_dl_executableLibrary";
@@ -16,8 +16,8 @@
@pragma("vm:entry-point")
class DynamicLibrary {
@patch
- factory DynamicLibrary.open(String name) {
- return _open(name);
+ factory DynamicLibrary.open(String path) {
+ return _open(path);
}
@patch
diff --git a/sdk/lib/ffi/dynamic_library.dart b/sdk/lib/ffi/dynamic_library.dart
index bcfa586..16e1b0f 100644
--- a/sdk/lib/ffi/dynamic_library.dart
+++ b/sdk/lib/ffi/dynamic_library.dart
@@ -4,47 +4,77 @@
part of dart.ffi;
-/// Represents a dynamically loaded C library.
+/// A dynamically loaded native library.
+///
+/// A dynamically loaded library is a mapping from symbols to memory addresses.
+/// These memory addresses can be accessed through [lookup].
class DynamicLibrary {
/// Creates a dynamic library holding all global symbols.
///
- /// Any symbol in a library currently loaded with global visibility (including
- /// the executable itself) may be resolved in this library.
+ /// Any symbol in a library currently loaded with global visibility
+ /// (including the executable itself) may be resolved through this library.
///
- /// This feature is not available on Windows, instead an exception is thrown.
+ /// This feature is not available on Windows.
external factory DynamicLibrary.process();
- /// Creates a dynamic library representing the running executable.
+ /// Creates a dynamic library containing all the symbols of the running
+ /// executable.
external factory DynamicLibrary.executable();
- /// Loads a dynamic library file with local visibility.
+ /// Loads a library file and provides access to its symbols.
///
- /// Throws an [ArgumentError] if loading the dynamic library fails.
+ /// The [path] must refer to a native library file which can be successfully
+ /// loaded.
///
- /// Calling this function multiple times, even in different isolates, returns
- /// objects which are equal but not identical. The underlying library is only
- /// loaded once into the DartVM by the OS.
- external factory DynamicLibrary.open(String name);
+ /// Calling this function multiple times with the same [path], even across
+ /// different isolates, only loads the library into the DartVM process once.
+ /// Multiple loads of the same library file produces [DynamicLibrary] objects
+ /// which are equal (`==`), but not [identical].
+ external factory DynamicLibrary.open(String path);
/// Looks up a symbol in the [DynamicLibrary] and returns its address in
- /// memory. Equivalent of dlsym.
+ /// memory.
///
- /// Throws an [ArgumentError] if it fails to lookup the symbol.
+ /// Similar to the functionality of the
+ /// [dlsym(3)](https://man7.org/linux/man-pages/man3/dlsym.3.html) system
+ /// call.
+ ///
+ /// The symbol must be provided by the dynamic library.
external Pointer<T> lookup<T extends NativeType>(String symbolName);
/// Dynamic libraries are equal if they load the same library.
external bool operator ==(Object other);
- /// The hash code for a DynamicLibrary only depends on the loaded library
+ /// The hash code for a [DynamicLibrary] only depends on the loaded library.
external int get hashCode;
- /// The handle to the dynamic library.
+ /// The opaque handle to the dynamic library.
+ ///
+ /// Similar to the return value of
+ /// [dlopen(3)](https://man7.org/linux/man-pages/man3/dlopen.3.html).
+ /// Can be used as arguments to other functions in the `dlopen` API
+ /// through FFI calls.
external Pointer<Void> get handle;
}
-/// Methods which cannot be invoked dynamically.
+/// Method which must not be invoked dynamically.
extension DynamicLibraryExtension on DynamicLibrary {
- /// Helper that combines lookup and cast to a Dart function.
+ /// Looks up a native function and returns it as a Dart function.
+ ///
+ /// [T] is the C function signature, and [F] is the Dart function signature.
+ /// For example:
+ ///
+ /// ```c
+ /// int32_t add(int32_t a, int32_t b) {
+ /// return a + b;
+ /// }
+ /// ```
+ ///
+ /// ```dart
+ /// DynamicLibrary dylib;
+ /// final add = dylib.lookupFunction<Int32 Function(Int32, Int32),
+ /// int Function(int, int)>('add');
+ /// ```
external F lookupFunction<T extends Function, F extends Function>(
String symbolName);
}
diff --git a/tools/VERSION b/tools/VERSION
index 52a4a09..73e776b6 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 178
+PRERELEASE 179
PRERELEASE_PATCH 0
\ No newline at end of file