[cfe] Allow generic types in arguments and bounds under a flag
The flag that enables the feature is the 'generic-metadata' experiment
flag.
Bug: https://github.com/dart-lang/sdk/issues/44916
Change-Id: I2770c672280831bf5af6643fde9cb0f1be3083b8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/188701
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index 92ac343..3017856 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -425,19 +425,21 @@
Library library = libraryBuilder.library;
List<TypeArgumentIssue> issues = findTypeArgumentIssues(
- library,
new InterfaceType(
supertype.classNode, library.nonNullable, supertype.typeArguments),
typeEnvironment,
libraryBuilder.isNonNullableByDefault
? SubtypeCheckMode.withNullabilities
: SubtypeCheckMode.ignoringNullabilities,
- allowSuperBounded: false);
+ allowSuperBounded: false,
+ isNonNullableByDefault: library.isNonNullableByDefault,
+ areGenericArgumentsAllowed:
+ libraryBuilder.enableGenericMetadataInLibrary);
for (TypeArgumentIssue issue in issues) {
DartType argument = issue.argument;
TypeParameter typeParameter = issue.typeParameter;
bool inferred = libraryBuilder.inferredTypes.contains(argument);
- if (isGenericFunctionTypeOrAlias(argument)) {
+ if (issue.isGenericTypeAsArgumentIssue) {
if (inferred) {
// Supertype can't be or contain super-bounded types, so null is
// passed for super-bounded hint here.
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 e3158d4..e409ff0 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
@@ -32,8 +32,7 @@
TypeArgumentIssue,
findTypeArgumentIssues,
findTypeArgumentIssuesForInvocation,
- getGenericTypeName,
- isGenericFunctionTypeOrAlias;
+ getGenericTypeName;
import 'package:kernel/type_algebra.dart' show Substitution, substitute;
@@ -2923,15 +2922,17 @@
bool haveErroneousBounds = false;
if (!inErrorRecovery) {
- for (int i = 0; i < variables.length; ++i) {
- TypeVariableBuilder variable = variables[i];
- List<TypeBuilder> genericFunctionTypes = <TypeBuilder>[];
- findGenericFunctionTypes(variable.bound,
- result: genericFunctionTypes);
- if (genericFunctionTypes.length > 0) {
- haveErroneousBounds = true;
- addProblem(messageGenericFunctionTypeInBound, variable.charOffset,
- variable.name.length, variable.fileUri);
+ if (!enableGenericMetadataInLibrary) {
+ for (int i = 0; i < variables.length; ++i) {
+ TypeVariableBuilder variable = variables[i];
+ List<TypeBuilder> genericFunctionTypes = <TypeBuilder>[];
+ findGenericFunctionTypes(variable.bound,
+ result: genericFunctionTypes);
+ if (genericFunctionTypes.length > 0) {
+ haveErroneousBounds = true;
+ addProblem(messageGenericFunctionTypeInBound, variable.charOffset,
+ variable.name.length, variable.fileUri);
+ }
}
}
@@ -3170,7 +3171,7 @@
inferredTypes.contains(argument);
offset =
typeArgumentsInfo?.getOffsetForIndex(issue.index, offset) ?? offset;
- if (isGenericFunctionTypeOrAlias(argument)) {
+ if (issue.isGenericTypeAsArgumentIssue) {
if (issueInferred) {
message = templateGenericFunctionTypeInferredAsActualTypeArgument
.withArguments(argument, isNonNullableByDefault);
@@ -3221,10 +3222,14 @@
}
}
+ // Don't show the hint about an attempted super-bounded type if the issue
+ // with the argument is that it's generic.
reportTypeArgumentIssue(message, fileUri, offset,
typeParameter: typeParameter,
- superBoundedAttempt: issue.enclosingType,
- superBoundedAttemptInverted: issue.invertedType);
+ superBoundedAttempt:
+ issue.isGenericTypeAsArgumentIssue ? null : issue.enclosingType,
+ superBoundedAttemptInverted:
+ issue.isGenericTypeAsArgumentIssue ? null : issue.invertedType);
}
}
@@ -3306,13 +3311,14 @@
// Check in bounds of own type variables.
for (TypeParameter parameter in typeParameters) {
List<TypeArgumentIssue> issues = findTypeArgumentIssues(
- library,
parameter.bound,
typeEnvironment,
isNonNullableByDefault
? SubtypeCheckMode.withNullabilities
: SubtypeCheckMode.ignoringNullabilities,
- allowSuperBounded: true);
+ allowSuperBounded: true,
+ isNonNullableByDefault: library.isNonNullableByDefault,
+ areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
for (TypeArgumentIssue issue in issues) {
DartType argument = issue.argument;
TypeParameter typeParameter = issue.typeParameter;
@@ -3325,7 +3331,7 @@
continue;
}
- if (isGenericFunctionTypeOrAlias(argument)) {
+ if (issue.isGenericTypeAsArgumentIssue) {
reportTypeArgumentIssue(
messageGenericFunctionTypeUsedAsActualTypeArgument,
fileUri,
@@ -3382,13 +3388,14 @@
}
if (!skipReturnType && returnType != null) {
List<TypeArgumentIssue> issues = findTypeArgumentIssues(
- library,
returnType,
typeEnvironment,
isNonNullableByDefault
? SubtypeCheckMode.withNullabilities
: SubtypeCheckMode.ignoringNullabilities,
- allowSuperBounded: true);
+ allowSuperBounded: true,
+ isNonNullableByDefault: library.isNonNullableByDefault,
+ areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
for (TypeArgumentIssue issue in issues) {
DartType argument = issue.argument;
TypeParameter typeParameter = issue.typeParameter;
@@ -3396,7 +3403,7 @@
// We don't need to check if [argument] was inferred or specified
// here, because inference in return types boils down to instantiate-
// -to-bound, and it can't provide a type that violates the bound.
- if (isGenericFunctionTypeOrAlias(argument)) {
+ if (issue.isGenericTypeAsArgumentIssue) {
reportTypeArgumentIssue(
messageGenericFunctionTypeUsedAsActualTypeArgument,
fileUri,
@@ -3490,13 +3497,14 @@
DartType type, TypeEnvironment typeEnvironment, Uri fileUri, int offset,
{bool inferred, bool allowSuperBounded = true}) {
List<TypeArgumentIssue> issues = findTypeArgumentIssues(
- library,
type,
typeEnvironment,
isNonNullableByDefault
? SubtypeCheckMode.withNullabilities
: SubtypeCheckMode.ignoringNullabilities,
- allowSuperBounded: allowSuperBounded);
+ allowSuperBounded: allowSuperBounded,
+ isNonNullableByDefault: library.isNonNullableByDefault,
+ areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
reportTypeArgumentIssues(issues, fileUri, offset, inferred: inferred);
}
@@ -3554,14 +3562,15 @@
? const NeverType.nonNullable()
: const NullType();
List<TypeArgumentIssue> issues = findTypeArgumentIssuesForInvocation(
- library,
parameters,
arguments,
typeEnvironment,
isNonNullableByDefault
? SubtypeCheckMode.withNullabilities
: SubtypeCheckMode.ignoringNullabilities,
- bottomType);
+ bottomType,
+ isNonNullableByDefault: library.isNonNullableByDefault,
+ areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
if (issues.isNotEmpty) {
DartType targetReceiver;
if (klass != null) {
@@ -3631,14 +3640,15 @@
? const NeverType.nonNullable()
: const NullType();
List<TypeArgumentIssue> issues = findTypeArgumentIssuesForInvocation(
- library,
instantiatedMethodParameters,
arguments.types,
typeEnvironment,
isNonNullableByDefault
? SubtypeCheckMode.withNullabilities
: SubtypeCheckMode.ignoringNullabilities,
- bottomType);
+ bottomType,
+ isNonNullableByDefault: library.isNonNullableByDefault,
+ areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
reportTypeArgumentIssues(issues, fileUri, offset,
typeArgumentsInfo: getTypeArgumentsInfo(arguments),
targetReceiver: receiverType,
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart
new file mode 100644
index 0000000..c64ec6b
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.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 A<X> {}
+
+A<Y> foo<Y>(Y y) => throw 42;
+
+test() {
+ var x = foo(<Z>(Z) => throw 42);
+ var y = [foo];
+ var z = {y.first};
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.expect
new file mode 100644
index 0000000..19d9303
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ : super core::Object::•()
+ ;
+}
+static method foo<Y extends core::Object? = dynamic>(self::foo::Y% y) → self::A<self::foo::Y%>
+ return throw 42;
+static method test() → dynamic {
+ self::A<<Z extends core::Object? = dynamic>(dynamic) → Never> x = self::foo<<Z extends core::Object? = dynamic>(dynamic) → Never>(<Z extends core::Object? = dynamic>(dynamic Z) → Never => throw 42);
+ core::List<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>> y = <<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>>[#C1];
+ core::Set<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>> z = block {
+ final core::Set<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>> #t1 = col::LinkedHashSet::•<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>>();
+ #t1.{core::Set::add}{Invariant}(y.{core::Iterable::first});
+ } =>#t1;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = tearoff self::foo
+}
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect
new file mode 100644
index 0000000..82c52ba
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ : super core::Object::•()
+ ;
+}
+static method foo<Y extends core::Object? = dynamic>(self::foo::Y% y) → self::A<self::foo::Y%>
+ return throw 42;
+static method test() → dynamic {
+ self::A<<Z extends core::Object? = dynamic>(dynamic) → Never> x = self::foo<<Z extends core::Object? = dynamic>(dynamic) → Never>(<Z extends core::Object? = dynamic>(dynamic Z) → Never => throw 42);
+ core::List<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>> y = core::_GrowableList::_literal1<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>>(#C1);
+ core::Set<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>> z = block {
+ final core::Set<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>> #t1 = new col::_CompactLinkedHashSet::•<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>>();
+ #t1.{core::Set::add}{Invariant}(y.{core::Iterable::first});
+ } =>#t1;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = tearoff self::foo
+}
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.textual_outline.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.textual_outline.expect
new file mode 100644
index 0000000..15f399b
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.textual_outline.expect
@@ -0,0 +1,5 @@
+class A<X> {}
+
+A<Y> foo<Y>(Y y) => throw 42;
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..1bbbdaf
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+A<Y> foo<Y>(Y y) => throw 42;
+
+class A<X> {}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.expect
new file mode 100644
index 0000000..19d9303
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ : super core::Object::•()
+ ;
+}
+static method foo<Y extends core::Object? = dynamic>(self::foo::Y% y) → self::A<self::foo::Y%>
+ return throw 42;
+static method test() → dynamic {
+ self::A<<Z extends core::Object? = dynamic>(dynamic) → Never> x = self::foo<<Z extends core::Object? = dynamic>(dynamic) → Never>(<Z extends core::Object? = dynamic>(dynamic Z) → Never => throw 42);
+ core::List<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>> y = <<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>>[#C1];
+ core::Set<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>> z = block {
+ final core::Set<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>> #t1 = col::LinkedHashSet::•<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>>();
+ #t1.{core::Set::add}{Invariant}(y.{core::Iterable::first});
+ } =>#t1;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = tearoff self::foo
+}
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.outline.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.outline.expect
new file mode 100644
index 0000000..e9d3b90
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.outline.expect
@@ -0,0 +1,14 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ ;
+}
+static method foo<Y extends core::Object? = dynamic>(self::foo::Y% y) → self::A<self::foo::Y%>
+ ;
+static method test() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect
new file mode 100644
index 0000000..82c52ba
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ : super core::Object::•()
+ ;
+}
+static method foo<Y extends core::Object? = dynamic>(self::foo::Y% y) → self::A<self::foo::Y%>
+ return throw 42;
+static method test() → dynamic {
+ self::A<<Z extends core::Object? = dynamic>(dynamic) → Never> x = self::foo<<Z extends core::Object? = dynamic>(dynamic) → Never>(<Z extends core::Object? = dynamic>(dynamic Z) → Never => throw 42);
+ core::List<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>> y = core::_GrowableList::_literal1<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>>(#C1);
+ core::Set<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>> z = block {
+ final core::Set<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>> #t1 = new col::_CompactLinkedHashSet::•<<Y extends core::Object? = dynamic>(Y%) → self::A<Y%>>();
+ #t1.{core::Set::add}{Invariant}(y.{core::Iterable::first});
+ } =>#t1;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = tearoff self::foo
+}
diff --git a/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart
new file mode 100644
index 0000000..7f7f46e
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.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 A<X> {}
+
+A<Function<Y>(Y)> foo(A<Function<Y>(Y)> x) => throw 42;
+
+class B extends A<Function<Y>(Y)> {}
+
+class C<Z extends Function<Y>(Y)> {}
+
+bar<V extends Function<Y>(Y)>() => throw 42;
+
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.strong.expect b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.strong.expect
new file mode 100644
index 0000000..0777872
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.strong.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ : super core::Object::•()
+ ;
+}
+class B extends self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> {
+ synthetic constructor •() → self::B
+ : super self::A::•()
+ ;
+}
+class C<Z extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::Z>
+ : super core::Object::•()
+ ;
+}
+static method foo(self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> x) → self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic>
+ return throw 42;
+static method bar<V extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic>() → dynamic
+ return throw 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect
new file mode 100644
index 0000000..0777872
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ : super core::Object::•()
+ ;
+}
+class B extends self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> {
+ synthetic constructor •() → self::B
+ : super self::A::•()
+ ;
+}
+class C<Z extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::Z>
+ : super core::Object::•()
+ ;
+}
+static method foo(self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> x) → self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic>
+ return throw 42;
+static method bar<V extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic>() → dynamic
+ return throw 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.textual_outline.expect b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.textual_outline.expect
new file mode 100644
index 0000000..8acc194
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+class A<X> {}
+
+A<Function<Y>(Y)> foo(A<Function<Y>(Y)> x) => throw 42;
+
+class B extends A<Function<Y>(Y)> {}
+
+class C<Z extends Function<Y>(Y)> {}
+
+bar<V extends Function<Y>(Y)>() => throw 42;
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d712596
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+A<Function<Y>(Y)> foo(A<Function<Y>(Y)> x) => throw 42;
+bar<V extends Function<Y>(Y)>() => throw 42;
+
+class A<X> {}
+
+class B extends A<Function<Y>(Y)> {}
+
+class C<Z extends Function<Y>(Y)> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.weak.expect b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.weak.expect
new file mode 100644
index 0000000..0777872
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.weak.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ : super core::Object::•()
+ ;
+}
+class B extends self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> {
+ synthetic constructor •() → self::B
+ : super self::A::•()
+ ;
+}
+class C<Z extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::Z>
+ : super core::Object::•()
+ ;
+}
+static method foo(self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> x) → self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic>
+ return throw 42;
+static method bar<V extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic>() → dynamic
+ return throw 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.weak.outline.expect b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.weak.outline.expect
new file mode 100644
index 0000000..13fcc95
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.weak.outline.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ ;
+}
+class B extends self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> {
+ synthetic constructor •() → self::B
+ ;
+}
+class C<Z extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::Z>
+ ;
+}
+static method foo(self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> x) → self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic>
+ ;
+static method bar<V extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic>() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect
new file mode 100644
index 0000000..0777872
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/simple_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ : super core::Object::•()
+ ;
+}
+class B extends self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> {
+ synthetic constructor •() → self::B
+ : super self::A::•()
+ ;
+}
+class C<Z extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::Z>
+ : super core::Object::•()
+ ;
+}
+static method foo(self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> x) → self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic>
+ return throw 42;
+static method bar<V extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic>() → dynamic
+ return throw 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart
new file mode 100644
index 0000000..3c977a6
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart
@@ -0,0 +1,17 @@
+// 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.
+
+typedef F = Function<Y>(Y);
+
+class A<X> {}
+
+A<F> foo(A<F> x) => throw 42;
+
+class B extends A<F> {}
+
+class C<Z extends F> {}
+
+bar<V extends F>() => throw 42;
+
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.strong.expect b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.strong.expect
new file mode 100644
index 0000000..dd20ce4
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.strong.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = <Y extends core::Object? = dynamic>(Y%) → dynamic;
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ : super core::Object::•()
+ ;
+}
+class B extends self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> {
+ synthetic constructor •() → self::B
+ : super self::A::•()
+ ;
+}
+class C<Z extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::Z>
+ : super core::Object::•()
+ ;
+}
+static method foo(self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> x) → self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic>
+ return throw 42;
+static method bar<V extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic>() → dynamic
+ return throw 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect
new file mode 100644
index 0000000..dd20ce4
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = <Y extends core::Object? = dynamic>(Y%) → dynamic;
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ : super core::Object::•()
+ ;
+}
+class B extends self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> {
+ synthetic constructor •() → self::B
+ : super self::A::•()
+ ;
+}
+class C<Z extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::Z>
+ : super core::Object::•()
+ ;
+}
+static method foo(self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> x) → self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic>
+ return throw 42;
+static method bar<V extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic>() → dynamic
+ return throw 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.textual_outline.expect b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.textual_outline.expect
new file mode 100644
index 0000000..23b49a3
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.textual_outline.expect
@@ -0,0 +1,12 @@
+typedef F = Function<Y>(Y);
+
+class A<X> {}
+
+A<F> foo(A<F> x) => throw 42;
+
+class B extends A<F> {}
+
+class C<Z extends F> {}
+
+bar<V extends F>() => throw 42;
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7ff1fb8
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+A<F> foo(A<F> x) => throw 42;
+bar<V extends F>() => throw 42;
+
+class A<X> {}
+
+class B extends A<F> {}
+
+class C<Z extends F> {}
+
+main() {}
+typedef F = Function<Y>(Y);
diff --git a/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.weak.expect b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.weak.expect
new file mode 100644
index 0000000..dd20ce4
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.weak.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = <Y extends core::Object? = dynamic>(Y%) → dynamic;
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ : super core::Object::•()
+ ;
+}
+class B extends self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> {
+ synthetic constructor •() → self::B
+ : super self::A::•()
+ ;
+}
+class C<Z extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::Z>
+ : super core::Object::•()
+ ;
+}
+static method foo(self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> x) → self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic>
+ return throw 42;
+static method bar<V extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic>() → dynamic
+ return throw 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.weak.outline.expect b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.weak.outline.expect
new file mode 100644
index 0000000..1fbe2f1
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.weak.outline.expect
@@ -0,0 +1,23 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = <Y extends core::Object? = dynamic>(Y%) → dynamic;
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ ;
+}
+class B extends self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> {
+ synthetic constructor •() → self::B
+ ;
+}
+class C<Z extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::Z>
+ ;
+}
+static method foo(self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> x) → self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic>
+ ;
+static method bar<V extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic>() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect
new file mode 100644
index 0000000..dd20ce4
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/typedef_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = <Y extends core::Object? = dynamic>(Y%) → dynamic;
+class A<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X%>
+ : super core::Object::•()
+ ;
+}
+class B extends self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> {
+ synthetic constructor •() → self::B
+ : super self::A::•()
+ ;
+}
+class C<Z extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::Z>
+ : super core::Object::•()
+ ;
+}
+static method foo(self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic> x) → self::A<<Y extends core::Object? = dynamic>(Y%) → dynamic>
+ return throw 42;
+static method bar<V extends <Y extends core::Object? = dynamic>(Y%) → dynamic = <Y extends core::Object? = dynamic>(Y%) → dynamic>() → dynamic
+ return throw 42;
+static method main() → dynamic {}
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
index f5a3b7f..6505325 100644
--- a/pkg/kernel/lib/src/bounds_checks.dart
+++ b/pkg/kernel/lib/src/bounds_checks.dart
@@ -237,9 +237,11 @@
/// helpful to show the same type to the user.
DartType? invertedType;
+ final bool isGenericTypeAsArgumentIssue;
+
TypeArgumentIssue(
this.index, this.argument, this.typeParameter, this.enclosingType,
- {this.invertedType});
+ {this.invertedType, this.isGenericTypeAsArgumentIssue = false});
int get hashCode {
int hash = 0x3fffffff & index;
@@ -271,9 +273,16 @@
// checks for super-boundness for construction of the auxiliary type. For
// details see Dart Language Specification, Section 14.3.2 The Instantiation to
// Bound Algorithm.
-List<TypeArgumentIssue> findTypeArgumentIssues(Library library, DartType type,
+List<TypeArgumentIssue> findTypeArgumentIssues(DartType type,
TypeEnvironment typeEnvironment, SubtypeCheckMode subtypeCheckMode,
- {bool allowSuperBounded = false}) {
+ {bool allowSuperBounded = false,
+ required bool isNonNullableByDefault,
+ required bool areGenericArgumentsAllowed}) {
+ // ignore: unnecessary_null_comparison
+ assert(isNonNullableByDefault != null);
+ // ignore: unnecessary_null_comparison
+ assert(areGenericArgumentsAllowed != null);
+
List<TypeParameter> variables = const <TypeParameter>[];
List<DartType> arguments = const <DartType>[];
List<TypeArgumentIssue> typedefRhsResult = const <TypeArgumentIssue>[];
@@ -291,8 +300,10 @@
requiredParameterCount: functionType.requiredParameterCount,
typedefType: null);
typedefRhsResult = findTypeArgumentIssues(
- library, cloned, typeEnvironment, subtypeCheckMode,
- allowSuperBounded: true);
+ cloned, typeEnvironment, subtypeCheckMode,
+ allowSuperBounded: true,
+ isNonNullableByDefault: isNonNullableByDefault,
+ areGenericArgumentsAllowed: areGenericArgumentsAllowed);
type = functionType.typedefType!;
}
@@ -307,25 +318,33 @@
for (TypeParameter parameter in type.typeParameters) {
result.addAll(findTypeArgumentIssues(
- library, parameter.bound!, typeEnvironment, subtypeCheckMode,
- allowSuperBounded: true));
+ parameter.bound!, typeEnvironment, subtypeCheckMode,
+ allowSuperBounded: true,
+ isNonNullableByDefault: isNonNullableByDefault,
+ areGenericArgumentsAllowed: areGenericArgumentsAllowed));
}
for (DartType formal in type.positionalParameters) {
result.addAll(findTypeArgumentIssues(
- library, formal, typeEnvironment, subtypeCheckMode,
- allowSuperBounded: true));
+ formal, typeEnvironment, subtypeCheckMode,
+ allowSuperBounded: true,
+ isNonNullableByDefault: isNonNullableByDefault,
+ areGenericArgumentsAllowed: areGenericArgumentsAllowed));
}
for (NamedType named in type.namedParameters) {
result.addAll(findTypeArgumentIssues(
- library, named.type, typeEnvironment, subtypeCheckMode,
- allowSuperBounded: true));
+ named.type, typeEnvironment, subtypeCheckMode,
+ allowSuperBounded: true,
+ isNonNullableByDefault: isNonNullableByDefault,
+ areGenericArgumentsAllowed: areGenericArgumentsAllowed));
}
result.addAll(findTypeArgumentIssues(
- library, type.returnType, typeEnvironment, subtypeCheckMode,
- allowSuperBounded: true));
+ type.returnType, typeEnvironment, subtypeCheckMode,
+ allowSuperBounded: true,
+ isNonNullableByDefault: isNonNullableByDefault,
+ areGenericArgumentsAllowed: areGenericArgumentsAllowed));
return result;
} else if (type is FutureOrType) {
@@ -348,12 +367,13 @@
new Map<TypeParameter, DartType>.fromIterables(variables, arguments);
for (int i = 0; i < arguments.length; ++i) {
DartType argument = arguments[i];
- if (isGenericFunctionTypeOrAlias(argument)) {
+ if (!areGenericArgumentsAllowed && isGenericFunctionTypeOrAlias(argument)) {
// Generic function types aren't allowed as type arguments either.
- result.add(new TypeArgumentIssue(i, argument, variables[i], type));
+ result.add(new TypeArgumentIssue(i, argument, variables[i], type,
+ isGenericTypeAsArgumentIssue: true));
} else if (variables[i].bound is! InvalidType) {
DartType bound = substitute(variables[i].bound!, substitutionMap);
- if (!library.isNonNullableByDefault) {
+ if (!isNonNullableByDefault) {
bound = legacyErasure(bound);
}
if (!typeEnvironment.isSubtypeOf(argument, bound, subtypeCheckMode)) {
@@ -365,8 +385,10 @@
}
argumentsResult.addAll(findTypeArgumentIssues(
- library, argument, typeEnvironment, subtypeCheckMode,
- allowSuperBounded: true));
+ argument, typeEnvironment, subtypeCheckMode,
+ allowSuperBounded: true,
+ isNonNullableByDefault: isNonNullableByDefault,
+ areGenericArgumentsAllowed: areGenericArgumentsAllowed));
}
result.addAll(argumentsResult);
result.addAll(typedefRhsResult);
@@ -376,8 +398,9 @@
if (!allowSuperBounded) return result;
bool isCorrectSuperBounded = true;
- DartType? invertedType =
- convertSuperBoundedToRegularBounded(library, typeEnvironment, type);
+ DartType? invertedType = convertSuperBoundedToRegularBounded(
+ typeEnvironment, type,
+ isNonNullableByDefault: isNonNullableByDefault);
// The auxiliary type is the same as [type]. At this point we know that
// [type] is not regular-bounded, which means that the inverted type is also
@@ -436,14 +459,21 @@
// details see Dart Language Specification, Section 14.3.2 The Instantiation to
// Bound Algorithm.
List<TypeArgumentIssue> findTypeArgumentIssuesForInvocation(
- Library library,
List<TypeParameter> parameters,
List<DartType> arguments,
TypeEnvironment typeEnvironment,
SubtypeCheckMode subtypeCheckMode,
- DartType bottomType) {
+ DartType bottomType,
+ {required bool isNonNullableByDefault,
+ required bool areGenericArgumentsAllowed}) {
+ // ignore: unnecessary_null_comparison
+ assert(isNonNullableByDefault != null);
+ // ignore: unnecessary_null_comparison
+ assert(areGenericArgumentsAllowed != null);
+
assert(arguments.length == parameters.length);
assert(bottomType == const NeverType.nonNullable() || bottomType is NullType);
+
List<TypeArgumentIssue> result = <TypeArgumentIssue>[];
Map<TypeParameter, DartType> substitutionMap = <TypeParameter, DartType>{};
for (int i = 0; i < arguments.length; ++i) {
@@ -452,13 +482,17 @@
for (int i = 0; i < arguments.length; ++i) {
DartType argument = arguments[i];
if (argument is TypeParameterType && argument.promotedBound != null) {
+ // TODO(dmitryas): Consider recognizing this case with a flag on the issue
+ // object.
result.add(new TypeArgumentIssue(i, argument, parameters[i], null));
- } else if (isGenericFunctionTypeOrAlias(argument)) {
+ } else if (!areGenericArgumentsAllowed &&
+ isGenericFunctionTypeOrAlias(argument)) {
// Generic function types aren't allowed as type arguments either.
- result.add(new TypeArgumentIssue(i, argument, parameters[i], null));
+ result.add(new TypeArgumentIssue(i, argument, parameters[i], null,
+ isGenericTypeAsArgumentIssue: true));
} else if (parameters[i].bound is! InvalidType) {
DartType bound = substitute(parameters[i].bound!, substitutionMap);
- if (!library.isNonNullableByDefault) {
+ if (!isNonNullableByDefault) {
bound = legacyErasure(bound);
}
if (!typeEnvironment.isSubtypeOf(argument, bound, subtypeCheckMode)) {
@@ -467,8 +501,10 @@
}
result.addAll(findTypeArgumentIssues(
- library, argument, typeEnvironment, subtypeCheckMode,
- allowSuperBounded: true));
+ argument, typeEnvironment, subtypeCheckMode,
+ allowSuperBounded: true,
+ isNonNullableByDefault: isNonNullableByDefault,
+ areGenericArgumentsAllowed: areGenericArgumentsAllowed));
}
return result;
}
@@ -486,11 +522,14 @@
/// [BottomType] and all contravariant occurrences of `Null` and [BottomType]
/// with `Object`. Returns null if the converted type is the same as [type].
DartType? convertSuperBoundedToRegularBounded(
- Library clientLibrary, TypeEnvironment typeEnvironment, DartType type,
- {int variance = Variance.covariant}) {
+ TypeEnvironment typeEnvironment, DartType type,
+ {int variance = Variance.covariant, required bool isNonNullableByDefault}) {
+ // ignore: unnecessary_null_comparison
+ assert(isNonNullableByDefault != null);
+
return type.accept1(
new _SuperBoundedTypeInverter(typeEnvironment,
- isNonNullableByDefault: clientLibrary.isNonNullableByDefault),
+ isNonNullableByDefault: isNonNullableByDefault),
variance);
}