Version 2.12.0-164.0.dev
Merge commit '6b7442ce14d66c1b77dcea248c93c44fd25990ae' into 'dev'
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 75a633f..2c8ad78 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -1105,6 +1105,8 @@
node.hasImplicitReturnType ? null : node.function.returnType;
DartType inferredType =
visitFunctionNode(node.function, null, returnContext, node.fileOffset);
+ inferrer.library.checkBoundsInFunctionNode(node.function,
+ inferrer.typeSchemaEnvironment, inferrer.library.fileUri);
node.variable.type = inferredType;
inferrer.flowAnalysis.functionExpression_end();
return const StatementInferenceResult();
@@ -1116,6 +1118,11 @@
inferrer.flowAnalysis.functionExpression_begin(node);
DartType inferredType =
visitFunctionNode(node.function, typeContext, null, node.fileOffset);
+ // In anonymous functions the return type isn't declared, so
+ // it shouldn't be checked.
+ inferrer.library.checkBoundsInFunctionNode(
+ node.function, inferrer.typeSchemaEnvironment, inferrer.library.fileUri,
+ skipReturnType: true);
inferrer.flowAnalysis.functionExpression_end();
return new ExpressionInferenceResult(inferredType, node);
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 5949536..a57f05f 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -3431,7 +3431,8 @@
List<VariableDeclaration> positionalParameters,
List<VariableDeclaration> namedParameters,
DartType returnType,
- int requiredParameterCount}) {
+ int requiredParameterCount,
+ bool skipReturnType = false}) {
if (typeParameters != null) {
for (TypeParameter parameter in typeParameters) {
checkBoundsInType(
@@ -3455,7 +3456,7 @@
allowSuperBounded: true);
}
}
- if (returnType != null) {
+ if (!skipReturnType && returnType != null) {
final DartType bottomType = isNonNullableByDefault
? const NeverType(Nullability.nonNullable)
: const NullType();
@@ -3528,14 +3529,16 @@
}
void checkBoundsInFunctionNode(
- FunctionNode function, TypeEnvironment typeEnvironment, Uri fileUri) {
+ FunctionNode function, TypeEnvironment typeEnvironment, Uri fileUri,
+ {bool skipReturnType = false}) {
checkBoundsInFunctionNodeParts(
typeEnvironment, fileUri, function.fileOffset,
typeParameters: function.typeParameters,
positionalParameters: function.positionalParameters,
namedParameters: function.namedParameters,
returnType: function.returnType,
- requiredParameterCount: function.requiredParameterCount);
+ requiredParameterCount: function.requiredParameterCount,
+ skipReturnType: skipReturnType);
}
void checkBoundsInListLiteral(
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 96f5f94..0e029cd 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -48,8 +48,10 @@
bail
bailing
bailout
+barbar
bash
bat
+bazbaz
bbb
bc
bench
@@ -758,3 +760,4 @@
year
yxxx
yy
+zz
diff --git a/pkg/front_end/testcases/general/issue44476.dart b/pkg/front_end/testcases/general/issue44476.dart
new file mode 100644
index 0000000..d8459e2
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44476.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, 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 A<X extends int> {}
+
+foo(A<num> x) {
+ bar(A<num> y) {
+ barbar(A<num> yy) => null;
+ }
+ var baz = (A<num> z) {
+ var bazbaz = (A<num> zz) => null;
+ };
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue44476.dart.outline.expect b/pkg/front_end/testcases/general/issue44476.dart.outline.expect
new file mode 100644
index 0000000..7f40fcf
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44476.dart.outline.expect
@@ -0,0 +1,33 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44476.dart:7:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// foo(A<num> x) {
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::int* = core::int*> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X*>*
+ ;
+ 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 method foo(self::A<core::num*>* x) → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/issue44476.dart.strong.expect b/pkg/front_end/testcases/general/issue44476.dart.strong.expect
new file mode 100644
index 0000000..136f9b1
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44476.dart.strong.expect
@@ -0,0 +1,88 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44476.dart:7:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// foo(A<num> x) {
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:9:19: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// barbar(A<num> yy) => null;
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:8:14: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// bar(A<num> y) {
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:12:26: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// var bazbaz = (A<num> zz) => null;
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:12:9: Error: Inferred type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// var bazbaz = (A<num> zz) => null;
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:11:21: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// var baz = (A<num> z) {
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:11:7: Error: Inferred type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// var baz = (A<num> z) {
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::int* = core::int*> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X*>*
+ : 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 method foo(self::A<core::num*>* x) → dynamic {
+ function bar(self::A<core::num*>* y) → Null {
+ function barbar(self::A<core::num*>* yy) → Null
+ return null;
+ }
+ (self::A<core::num*>*) →* Null baz = (self::A<core::num*>* z) → Null {
+ (self::A<core::num*>*) →* Null bazbaz = (self::A<core::num*>* zz) → Null => null;
+ };
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue44476.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue44476.dart.strong.transformed.expect
new file mode 100644
index 0000000..136f9b1
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44476.dart.strong.transformed.expect
@@ -0,0 +1,88 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44476.dart:7:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// foo(A<num> x) {
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:9:19: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// barbar(A<num> yy) => null;
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:8:14: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// bar(A<num> y) {
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:12:26: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// var bazbaz = (A<num> zz) => null;
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:12:9: Error: Inferred type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// var bazbaz = (A<num> zz) => null;
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:11:21: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// var baz = (A<num> z) {
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:11:7: Error: Inferred type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// var baz = (A<num> z) {
+// ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::int* = core::int*> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X*>*
+ : 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 method foo(self::A<core::num*>* x) → dynamic {
+ function bar(self::A<core::num*>* y) → Null {
+ function barbar(self::A<core::num*>* yy) → Null
+ return null;
+ }
+ (self::A<core::num*>*) →* Null baz = (self::A<core::num*>* z) → Null {
+ (self::A<core::num*>*) →* Null bazbaz = (self::A<core::num*>* zz) → Null => null;
+ };
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue44476.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue44476.dart.textual_outline.expect
new file mode 100644
index 0000000..c3257fc
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44476.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+class A<X extends int> {}
+
+foo(A<num> x) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/issue44476.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue44476.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c3257fc
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44476.dart.textual_outline_modelled.expect
@@ -0,0 +1,4 @@
+class A<X extends int> {}
+
+foo(A<num> x) {}
+main() {}
diff --git a/tools/VERSION b/tools/VERSION
index f8fc983..3b233a1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 12
PATCH 0
-PRERELEASE 163
+PRERELEASE 164
PRERELEASE_PATCH 0
\ No newline at end of file