Version 2.14.0-249.0.dev
Merge commit '2a3e884c80dff9ade28dda397d726ee66c8e5332' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f32243e..94b1829 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,9 +4,9 @@
### `dart:html`
-* [#44319][]: `convertNativeToDart_Dictionary()` now converts objects
- recursively, this fixes APIs like MediaStreamTrack.getCapabilities
- that convert between Maps and browser Dictionaries.
+* [#44319][]: `convertNativeToDart_Dictionary()` now converts objects
+ recursively, this fixes APIs like MediaStreamTrack.getCapabilities
+ that convert between Maps and browser Dictionaries.
[44319]: (https://github.com/dart-lang/sdk/issues/44319)
@@ -23,6 +23,8 @@
#### `dart:core`
+* Introduce `Enum` interface implemented by all `enum` declarations.
+
* The native `DateTime` class now better handles local time around
daylight saving changes that are not precisely one hour.
(No change on the Web which uses the JavaScript `Date` object.)
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index 73824a7..1229ded 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -5176,6 +5176,64 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(int count, int count2)>
+ templateInstantiationTooFewArguments =
+ const Template<Message Function(int count, int count2)>(
+ messageTemplate:
+ r"""Too few type arguments: #count required, #count2 given.""",
+ tipTemplate: r"""Try adding the missing type arguments.""",
+ withArguments: _withArgumentsInstantiationTooFewArguments);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(int count, int count2)>
+ codeInstantiationTooFewArguments =
+ const Code<Message Function(int count, int count2)>(
+ "InstantiationTooFewArguments",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInstantiationTooFewArguments(int count, int count2) {
+ // ignore: unnecessary_null_comparison
+ if (count == null) throw 'No count provided';
+ // ignore: unnecessary_null_comparison
+ if (count2 == null) throw 'No count provided';
+ return new Message(codeInstantiationTooFewArguments,
+ message:
+ """Too few type arguments: ${count} required, ${count2} given.""",
+ tip: """Try adding the missing type arguments.""",
+ arguments: {'count': count, 'count2': count2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(int count, int count2)>
+ templateInstantiationTooManyArguments =
+ const Template<Message Function(int count, int count2)>(
+ messageTemplate:
+ r"""Too many type arguments: #count allowed, but #count2 found.""",
+ tipTemplate: r"""Try removing the extra type arguments.""",
+ withArguments: _withArgumentsInstantiationTooManyArguments);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(int count, int count2)>
+ codeInstantiationTooManyArguments =
+ const Code<Message Function(int count, int count2)>(
+ "InstantiationTooManyArguments",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInstantiationTooManyArguments(int count, int count2) {
+ // ignore: unnecessary_null_comparison
+ if (count == null) throw 'No count provided';
+ // ignore: unnecessary_null_comparison
+ if (count2 == null) throw 'No count provided';
+ return new Message(codeInstantiationTooManyArguments,
+ message:
+ """Too many type arguments: ${count} allowed, but ${count2} found.""",
+ tip: """Try removing the extra type arguments.""",
+ arguments: {'count': count, 'count2': count2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
String
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/core.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/core.dart
index da9e41a..79f1f75 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/core.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/core.dart
@@ -24,6 +24,9 @@
String toString() => '';
}
+/*class: Enum:Enum,Object*/
+abstract class Enum {}
+
/*class: Null:Null,Object*/
class Null {
factory Null._uninstantiable() {
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_out/core.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_out/core.dart
index 0df65e1..2682390 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_out/core.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_out/core.dart
@@ -26,6 +26,9 @@
String toString() => '';
}
+/*class: Enum:Enum,Object*/
+abstract class Enum {}
+
/*class: Null:Null,Object*/
class Null {
factory Null._uninstantiable() {
diff --git a/pkg/analysis_server/test/integration/analysis/get_errors_non_standard_sdk_test.dart b/pkg/analysis_server/test/integration/analysis/get_errors_non_standard_sdk_test.dart
index e8ba7bf..4a0e09d 100644
--- a/pkg/analysis_server/test/integration/analysis/get_errors_non_standard_sdk_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_errors_non_standard_sdk_test.dart
@@ -38,6 +38,7 @@
class int {}
class num {}
class Object {}
+class Enum {}
class Iterable<E> {}
class Map<K, V> {}
class Null {}
diff --git a/pkg/analyzer/lib/dart/element/type_provider.dart b/pkg/analyzer/lib/dart/element/type_provider.dart
index f1fb800..fd72800 100644
--- a/pkg/analyzer/lib/dart/element/type_provider.dart
+++ b/pkg/analyzer/lib/dart/element/type_provider.dart
@@ -31,6 +31,12 @@
/// Return the type representing the built-in type `dynamic`.
DartType get dynamicType;
+ /// Return the element representing the built-in type `Enum`.
+ ClassElement get enumElement;
+
+ /// Return the type representing the built-in type `Enum`.
+ InterfaceType get enumType;
+
/// Return the type representing the built-in type `Function`.
InterfaceType get functionType;
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index bbdc21f..abd2d98 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -2668,7 +2668,8 @@
}
@override
- List<InterfaceType> get allSupertypes => <InterfaceType>[supertype];
+ List<InterfaceType> get allSupertypes =>
+ <InterfaceType>[...interfaces, supertype];
List<FieldElement> get constants {
return fields.where((field) => !field.isSynthetic).toList();
@@ -2700,7 +2701,8 @@
bool get hasStaticMember => true;
@override
- List<InterfaceType> get interfaces => const <InterfaceType>[];
+ List<InterfaceType> get interfaces =>
+ <InterfaceType>[library.typeProvider.enumType];
@override
bool get isAbstract => false;
diff --git a/pkg/analyzer/lib/src/dart/element/type_provider.dart b/pkg/analyzer/lib/src/dart/element/type_provider.dart
index dbc4a34..6f29133 100644
--- a/pkg/analyzer/lib/src/dart/element/type_provider.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_provider.dart
@@ -27,6 +27,7 @@
const Set<String> _nonSubtypableDartCoreClassNames = {
'bool',
'double',
+ 'Enum',
'int',
'Null',
'num',
@@ -104,6 +105,7 @@
ClassElement? _boolElement;
ClassElement? _doubleElement;
+ ClassElement? _enumElement;
ClassElement? _futureElement;
ClassElement? _futureOrElement;
ClassElement? _intElement;
@@ -122,6 +124,7 @@
InterfaceType? _deprecatedType;
InterfaceType? _doubleType;
InterfaceType? _doubleTypeQuestion;
+ InterfaceType? _enumType;
InterfaceType? _functionType;
InterfaceType? _futureDynamicType;
InterfaceType? _futureNullType;
@@ -151,7 +154,7 @@
required LibraryElement coreLibrary,
required LibraryElement asyncLibrary,
required bool isNonNullableByDefault,
- }) : _coreLibrary = coreLibrary,
+ }) : _coreLibrary = coreLibrary,
_asyncLibrary = asyncLibrary,
isNonNullableByDefault = isNonNullableByDefault;
@@ -220,6 +223,16 @@
DartType get dynamicType => DynamicTypeImpl.instance;
@override
+ ClassElement get enumElement {
+ return _enumElement ??= _getClassElement(_coreLibrary, "Enum");
+ }
+
+ @override
+ InterfaceType get enumType {
+ return _enumType ??= _getType(_coreLibrary, "Enum");
+ }
+
+ @override
InterfaceType get functionType {
return _functionType ??= _getType(_coreLibrary, "Function");
}
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index a19caf2..3aa1807 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -523,6 +523,10 @@
external dynamic noSuchMethod(Invocation invocation);
}
+abstract class Enum {
+ int get index;
+}
+
abstract class Pattern {
Iterable<Match> allMatches(String string, [int start = 0]);
}
diff --git a/pkg/analyzer/test/src/dart/resolution/enum_test.dart b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
index c4dc7ed..7a52582 100644
--- a/pkg/analyzer/test/src/dart/resolution/enum_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
@@ -24,7 +24,7 @@
''');
var v = findElement.topVar('v');
- assertType(v.type, 'List<Object>');
+ assertType(v.type, 'List<Enum>');
}
test_isConstantEvaluated() async {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index dc4d4cf..3859042 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -4624,6 +4624,8 @@
enum E @5
codeOffset: 0
codeLength: 26
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -9667,6 +9669,8 @@
synthetic @-1
enums
enum E @30
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -11764,6 +11768,8 @@
definingUnit
enums
enum E @5
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -11816,6 +11822,8 @@
definingUnit
enums
enum E @5
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -14445,6 +14453,8 @@
definingUnit
enums
enum E @5
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -14467,6 +14477,8 @@
synthetic toString @-1
returnType: String
enum E @19
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -14723,6 +14735,8 @@
enums
enum E @65
documentationComment: /**\n * Docs\n */
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -14758,6 +14772,8 @@
definingUnit
enums
enum E @5
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -14804,6 +14820,8 @@
definingUnit
enums
enum E @5
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -14863,6 +14881,8 @@
definingUnit
enums
enum E @5
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -14894,6 +14914,8 @@
definingUnit
enums
enum E1 @5
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -14912,6 +14934,8 @@
synthetic toString @-1
returnType: String
enum E2 @20
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -14997,6 +15021,8 @@
superKeyword: super @0
enums
enum E @5
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -22565,6 +22591,8 @@
definingUnit
enums
enum E @19
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -22634,6 +22662,8 @@
returnType: dynamic
enums
enum E @64
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -22707,6 +22737,8 @@
staticElement: self::@getter::a
staticType: null
token: a @15
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -24202,6 +24234,8 @@
staticElement: self::@getter::foo
staticType: null
token: foo @17
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -25392,6 +25426,8 @@
synthetic @-1
enums
enum E @5
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -26873,6 +26909,8 @@
definingUnit
enums
enum E @5
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -29182,6 +29220,8 @@
synthetic @-1
enums
enum E @16
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -29288,6 +29328,8 @@
synthetic @-1
enums
enum E @27
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -29328,6 +29370,8 @@
synthetic @-1
enums
enum E @42
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -29405,6 +29449,8 @@
synthetic @-1
enums
enum E @27
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -29480,6 +29526,8 @@
synthetic @-1
enums
enum E @27
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
@@ -29623,6 +29671,8 @@
definingUnit
enums
enum E @5
+ interfaces
+ Enum
fields
synthetic final index @-1
type: int
diff --git a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
index f05be5b..f381e96 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -79,6 +79,8 @@
final NamedTypeBuilder objectType;
+ final NamedTypeBuilder enumType;
+
final NamedTypeBuilder listType;
EnumBuilder.internal(
@@ -91,6 +93,7 @@
this.intType,
this.listType,
this.objectType,
+ this.enumType,
this.stringType,
LibraryBuilder parent,
int startCharOffset,
@@ -151,6 +154,12 @@
/* arguments = */ null,
/* fileUri = */ null,
/* charOffset = */ null);
+ NamedTypeBuilder enumType = new NamedTypeBuilder(
+ "Enum",
+ const NullabilityBuilder.omitted(),
+ /* arguments = */ null,
+ /* fileUri = */ null,
+ /* charOffset = */ null);
Class cls = new Class(
name: name, reference: referencesFrom?.reference, fileUri: fileUri);
Map<String, MemberBuilder> members = <String, MemberBuilder>{};
@@ -393,6 +402,7 @@
intType,
listType,
objectType,
+ enumType,
stringType,
parent,
startCharOffsetComputed,
@@ -429,8 +439,12 @@
coreLibrary.scope, charOffset, fileUri, libraryBuilder);
objectType.resolveIn(
coreLibrary.scope, charOffset, fileUri, libraryBuilder);
+ enumType.resolveIn(coreLibrary.scope, charOffset, fileUri, libraryBuilder);
listType.resolveIn(coreLibrary.scope, charOffset, fileUri, libraryBuilder);
+ cls.implementedTypes
+ .add(enumType.buildSupertype(libraryBuilder, charOffset, fileUri));
+
SourceFieldBuilder indexFieldBuilder = firstMemberNamed("index");
indexFieldBuilder.build(libraryBuilder);
Field indexField = indexFieldBuilder.field;
diff --git a/pkg/front_end/lib/src/fasta/denylisted_classes.dart b/pkg/front_end/lib/src/fasta/denylisted_classes.dart
index 345ec12..5df3707 100644
--- a/pkg/front_end/lib/src/fasta/denylisted_classes.dart
+++ b/pkg/front_end/lib/src/fasta/denylisted_classes.dart
@@ -8,6 +8,7 @@
"int",
"num",
"double",
+ "Enum",
"String",
"Null"
];
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
index 4efd282..5674281 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
@@ -1786,6 +1786,111 @@
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(DartType _type, DartType _type2, String name,
+ DartType _type3, bool isNonNullableByDefault)>
+ templateIncorrectTypeArgumentInstantiation = const Template<
+ Message Function(DartType _type, DartType _type2, String name,
+ DartType _type3, bool isNonNullableByDefault)>(
+ messageTemplate:
+ r"""Type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#type3'.""",
+ tipTemplate:
+ r"""Try changing type arguments so that they conform to the bounds.""",
+ withArguments: _withArgumentsIncorrectTypeArgumentInstantiation);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+ Message Function(DartType _type, DartType _type2, String name,
+ DartType _type3, bool isNonNullableByDefault)>
+ codeIncorrectTypeArgumentInstantiation = const Code<
+ Message Function(DartType _type, DartType _type2, String name,
+ DartType _type3, bool isNonNullableByDefault)>(
+ "IncorrectTypeArgumentInstantiation",
+ analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIncorrectTypeArgumentInstantiation(
+ DartType _type,
+ DartType _type2,
+ String name,
+ DartType _type3,
+ bool isNonNullableByDefault) {
+ TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+ List<Object> typeParts = labeler.labelType(_type);
+ List<Object> type2Parts = labeler.labelType(_type2);
+ if (name.isEmpty) throw 'No name provided';
+ name = demangleMixinApplicationName(name);
+ List<Object> type3Parts = labeler.labelType(_type3);
+ String type = typeParts.join();
+ String type2 = type2Parts.join();
+ String type3 = type3Parts.join();
+ return new Message(codeIncorrectTypeArgumentInstantiation,
+ message:
+ """Type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${type3}'.""" +
+ labeler.originMessages,
+ tip: """Try changing type arguments so that they conform to the bounds.""",
+ arguments: {
+ 'type': _type,
+ 'type2': _type2,
+ 'name': name,
+ 'type3': _type3
+ });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+ Message Function(DartType _type, DartType _type2, String name,
+ DartType _type3, bool isNonNullableByDefault)>
+ templateIncorrectTypeArgumentInstantiationInferred = const Template<
+ Message Function(DartType _type, DartType _type2, String name,
+ DartType _type3, bool isNonNullableByDefault)>(
+ messageTemplate:
+ r"""Inferred type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#type3'.""",
+ tipTemplate:
+ r"""Try specifying type arguments explicitly so that they conform to the bounds.""",
+ withArguments:
+ _withArgumentsIncorrectTypeArgumentInstantiationInferred);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+ Message Function(DartType _type, DartType _type2, String name,
+ DartType _type3, bool isNonNullableByDefault)>
+ codeIncorrectTypeArgumentInstantiationInferred = const Code<
+ Message Function(DartType _type, DartType _type2, String name,
+ DartType _type3, bool isNonNullableByDefault)>(
+ "IncorrectTypeArgumentInstantiationInferred",
+ analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIncorrectTypeArgumentInstantiationInferred(
+ DartType _type,
+ DartType _type2,
+ String name,
+ DartType _type3,
+ bool isNonNullableByDefault) {
+ TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+ List<Object> typeParts = labeler.labelType(_type);
+ List<Object> type2Parts = labeler.labelType(_type2);
+ if (name.isEmpty) throw 'No name provided';
+ name = demangleMixinApplicationName(name);
+ List<Object> type3Parts = labeler.labelType(_type3);
+ String type = typeParts.join();
+ String type2 = type2Parts.join();
+ String type3 = type3Parts.join();
+ return new Message(codeIncorrectTypeArgumentInstantiationInferred,
+ message:
+ """Inferred type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${type3}'.""" +
+ labeler.originMessages,
+ tip: """Try specifying type arguments explicitly so that they conform to the bounds.""",
+ arguments: {
+ 'type': _type,
+ 'type2': _type2,
+ 'name': name,
+ 'type3': _type3
+ });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+ Message Function(DartType _type, DartType _type2, String name,
DartType _type3, String name2, bool isNonNullableByDefault)>
templateIncorrectTypeArgumentQualified = const Template<
Message Function(DartType _type, DartType _type2, String name,
@@ -1940,6 +2045,37 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(DartType _type, bool isNonNullableByDefault)>
+ templateInstantiationNonGenericFunctionType = const Template<
+ Message Function(DartType _type, bool isNonNullableByDefault)>(
+ messageTemplate:
+ r"""The static type of the explicit instantiation operand must be a generic function type but is '#type'.""",
+ tipTemplate:
+ r"""Try changing the operand or remove the type arguments.""",
+ withArguments: _withArgumentsInstantiationNonGenericFunctionType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, bool isNonNullableByDefault)>
+ codeInstantiationNonGenericFunctionType =
+ const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
+ "InstantiationNonGenericFunctionType",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInstantiationNonGenericFunctionType(
+ DartType _type, bool isNonNullableByDefault) {
+ TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+ List<Object> typeParts = labeler.labelType(_type);
+ String type = typeParts.join();
+ return new Message(codeInstantiationNonGenericFunctionType,
+ message:
+ """The static type of the explicit instantiation operand must be a generic function type but is '${type}'.""" +
+ labeler.originMessages,
+ tip: """Try changing the operand or remove the type arguments.""",
+ arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
String string, DartType _type, bool isNonNullableByDefault)>
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index fa29641..2336024 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -6302,13 +6302,21 @@
@override
void handleTypeArgumentApplication(Token openAngleBracket) {
- /// TODO(johnniwinther, paulberry): add support for this construct when the
- /// "constructor-tearoffs" feature is enabled.
+ assert(checkState(openAngleBracket, [
+ ValueKinds.TypeArguments,
+ unionOfKinds([ValueKinds.Generator, ValueKinds.Expression])
+ ]));
List<UnresolvedType> typeArguments = pop(); // typeArguments
if (libraryBuilder.enableConstructorTearOffsInLibrary) {
- Generator generator = pop();
- push(generator.applyTypeArguments(
- openAngleBracket.charOffset, typeArguments));
+ Object operand = pop();
+ if (operand is Generator) {
+ push(operand.applyTypeArguments(
+ openAngleBracket.charOffset, typeArguments));
+ } else {
+ push(new Instantiation(
+ toValue(operand), buildDartTypeArguments(typeArguments))
+ ..fileOffset = openAngleBracket.charOffset);
+ }
} else {
addProblem(
templateExperimentNotEnabled.withArguments(
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 1c7f034..737f649 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -86,6 +86,7 @@
required bool desugarSets,
required bool enableTripleShift,
required bool enableConstFunctions,
+ required bool enableConstructorTearOff,
required bool errorOnUnevaluatedConstant,
CoreTypes? coreTypes,
ClassHierarchy? hierarchy}) {
@@ -99,6 +100,8 @@
assert(enableConstFunctions != null);
// ignore: unnecessary_null_comparison
assert(errorOnUnevaluatedConstant != null);
+ // ignore: unnecessary_null_comparison
+ assert(enableConstructorTearOff != null);
coreTypes ??= new CoreTypes(component);
hierarchy ??= new ClassHierarchy(component, coreTypes);
@@ -110,7 +113,8 @@
enableTripleShift: enableTripleShift,
enableConstFunctions: enableConstFunctions,
errorOnUnevaluatedConstant: errorOnUnevaluatedConstant,
- evaluateAnnotations: evaluateAnnotations);
+ evaluateAnnotations: evaluateAnnotations,
+ enableConstructorTearOff: enableConstructorTearOff);
return component;
}
@@ -124,7 +128,8 @@
{required bool evaluateAnnotations,
required bool enableTripleShift,
required bool enableConstFunctions,
- required bool errorOnUnevaluatedConstant}) {
+ required bool errorOnUnevaluatedConstant,
+ required bool enableConstructorTearOff}) {
// ignore: unnecessary_null_comparison
assert(evaluateAnnotations != null);
// ignore: unnecessary_null_comparison
@@ -133,12 +138,15 @@
assert(enableConstFunctions != null);
// ignore: unnecessary_null_comparison
assert(errorOnUnevaluatedConstant != null);
+ // ignore: unnecessary_null_comparison
+ assert(enableConstructorTearOff != null);
final ConstantsTransformer constantsTransformer = new ConstantsTransformer(
backend,
environmentDefines,
evaluateAnnotations,
enableTripleShift,
enableConstFunctions,
+ enableConstructorTearOff,
errorOnUnevaluatedConstant,
typeEnvironment,
errorReporter,
@@ -156,10 +164,11 @@
TypeEnvironment typeEnvironment,
ErrorReporter errorReporter,
EvaluationMode evaluationMode,
- {bool evaluateAnnotations: true,
- bool enableTripleShift: false,
- bool enableConstFunctions: false,
- bool errorOnUnevaluatedConstant: false}) {
+ {required bool evaluateAnnotations,
+ required bool enableTripleShift,
+ required bool enableConstFunctions,
+ required bool enableConstructorTearOff,
+ required bool errorOnUnevaluatedConstant}) {
// ignore: unnecessary_null_comparison
assert(evaluateAnnotations != null);
// ignore: unnecessary_null_comparison
@@ -168,12 +177,15 @@
assert(enableConstFunctions != null);
// ignore: unnecessary_null_comparison
assert(errorOnUnevaluatedConstant != null);
+ // ignore: unnecessary_null_comparison
+ assert(enableConstructorTearOff != null);
final ConstantsTransformer constantsTransformer = new ConstantsTransformer(
backend,
environmentDefines,
evaluateAnnotations,
enableTripleShift,
enableConstFunctions,
+ enableConstructorTearOff,
errorOnUnevaluatedConstant,
typeEnvironment,
errorReporter,
@@ -360,6 +372,7 @@
final bool evaluateAnnotations;
final bool enableTripleShift;
final bool enableConstFunctions;
+ final bool enableConstructorTearOff;
final bool errorOnUnevaluatedConstant;
ConstantsTransformer(
@@ -368,6 +381,7 @@
this.evaluateAnnotations,
this.enableTripleShift,
this.enableConstFunctions,
+ this.enableConstructorTearOff,
this.errorOnUnevaluatedConstant,
this.typeEnvironment,
ErrorReporter errorReporter,
@@ -696,6 +710,18 @@
}
@override
+ TreeNode visitInstantiation(Instantiation node, TreeNode? removalSentinel) {
+ Instantiation result =
+ super.visitInstantiation(node, removalSentinel) as Instantiation;
+ if (enableConstructorTearOff &&
+ result.expression is ConstantExpression &&
+ result.typeArguments.every(isInstantiated)) {
+ return evaluateAndTransformWithContext(node, result);
+ }
+ return node;
+ }
+
+ @override
TreeNode visitSwitchCase(SwitchCase node, TreeNode? removalSentinel) {
transformExpressions(node.expressions, node);
return super.visitSwitchCase(node, removalSentinel);
@@ -872,9 +898,6 @@
final bool enableTripleShift;
final bool enableConstFunctions;
- final bool Function(DartType) isInstantiated =
- new IsInstantiatedVisitor().isInstantiated;
-
final Map<Constant, Constant> canonicalizationCache;
final Map<Node, Constant?> nodeCache;
final CloneVisitorNotMembers cloner = new CloneVisitorNotMembers();
@@ -4479,6 +4502,10 @@
}
}
+bool isInstantiated(DartType type) {
+ return type.accept(new IsInstantiatedVisitor());
+}
+
class IsInstantiatedVisitor extends DartTypeVisitor<bool> {
final _availableVariables = new Set<TypeParameter>();
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 ff56187..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
@@ -153,9 +153,6 @@
bodyBuilder.parseFieldInitializer(initializerToken);
initializerToken = null;
- // The type is needed in the inference below, so the helper should be set.
- typeInferrer.helper = bodyBuilder;
-
ExpressionInferenceResult result = typeInferrer.inferExpression(
initializer, const UnknownType(), true,
isVoidAllowed: true);
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 a78e798..3ff0062 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -63,10 +63,35 @@
InferenceVisitor(this.inferrer);
+ /// Computes uri and offset for [node] for internal errors in a way that is
+ /// safe for both top-level and full inference.
+ _UriOffset _computeUriOffset(TreeNode node) {
+ Uri uri;
+ int fileOffset;
+ if (!inferrer.isTopLevel) {
+ // In local inference we have access to the current file uri.
+ uri = inferrer.helper.uri;
+ fileOffset = node.fileOffset;
+ } else {
+ Location location = node.location;
+ if (location != null) {
+ // Use the location file uri, if available.
+ uri = location.file;
+ fileOffset = node.fileOffset;
+ } else {
+ // Otherwise use the library file uri with no offset.
+ uri = inferrer.library.fileUri;
+ fileOffset = TreeNode.noOffset;
+ }
+ }
+ return new _UriOffset(uri, fileOffset);
+ }
+
ExpressionInferenceResult _unhandledExpression(
Expression node, DartType typeContext) {
- unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
- inferrer.helper.uri);
+ _UriOffset uriOffset = _computeUriOffset(node);
+ unhandled("${node.runtimeType}", "InferenceVisitor", uriOffset.fileOffset,
+ uriOffset.uri);
}
@override
@@ -190,12 +215,6 @@
}
@override
- ExpressionInferenceResult visitInstantiation(
- Instantiation node, DartType typeContext) {
- return _unhandledExpression(node, typeContext);
- }
-
- @override
ExpressionInferenceResult visitConstructorTearOff(
ConstructorTearOff node, DartType typeContext) {
return _unhandledExpression(node, typeContext);
@@ -220,8 +239,9 @@
}
StatementInferenceResult _unhandledStatement(Statement node) {
- return unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
- inferrer.helper.uri);
+ _UriOffset uriOffset = _computeUriOffset(node);
+ return unhandled("${node.runtimeType}", "InferenceVisitor",
+ uriOffset.fileOffset, uriOffset.uri);
}
@override
@@ -273,6 +293,63 @@
}
@override
+ ExpressionInferenceResult visitInstantiation(
+ Instantiation node, DartType typeContext) {
+ ExpressionInferenceResult operandResult = inferrer.inferExpression(
+ node.expression, const UnknownType(), true,
+ isVoidAllowed: true);
+ node.expression = operandResult.expression..parent = node;
+ DartType operandType = operandResult.inferredType;
+ Expression result = node;
+ DartType resultType = const InvalidType();
+ if (operandType is FunctionType) {
+ if (operandType.typeParameters.length == node.typeArguments.length) {
+ inferrer.checkBoundsInInstantiation(
+ operandType, node.typeArguments, node.fileOffset,
+ inferred: false);
+ resultType = Substitution.fromPairs(
+ operandType.typeParameters, node.typeArguments)
+ .substituteType(operandType.withoutTypeParameters);
+ } else {
+ if (!inferrer.isTopLevel) {
+ if (operandType.typeParameters.isEmpty) {
+ result = inferrer.helper.buildProblem(
+ templateInstantiationNonGenericFunctionType.withArguments(
+ operandType, inferrer.isNonNullableByDefault),
+ node.fileOffset,
+ noLength);
+ } else if (operandType.typeParameters.length >
+ node.typeArguments.length) {
+ result = inferrer.helper.buildProblem(
+ templateInstantiationTooFewArguments.withArguments(
+ operandType.typeParameters.length,
+ node.typeArguments.length),
+ node.fileOffset,
+ noLength);
+ } else if (operandType.typeParameters.length <
+ node.typeArguments.length) {
+ result = inferrer.helper.buildProblem(
+ templateInstantiationTooManyArguments.withArguments(
+ operandType.typeParameters.length,
+ node.typeArguments.length),
+ node.fileOffset,
+ noLength);
+ }
+ }
+ }
+ } else {
+ if (!inferrer.isTopLevel) {
+ result = inferrer.helper.buildProblem(
+ templateInstantiationNonGenericFunctionType.withArguments(
+ operandType, inferrer.isNonNullableByDefault),
+ node.fileOffset,
+ noLength);
+ }
+ }
+ return new ExpressionInferenceResult(resultType, result);
+ }
+
+ @override
ExpressionInferenceResult visitIntLiteral(
IntLiteral node, DartType typeContext) {
return new ExpressionInferenceResult(
@@ -991,11 +1068,12 @@
} else if (syntheticAssignment is InvalidExpression || hasProblem) {
return new InvalidForInVariable(syntheticAssignment);
} else {
+ _UriOffset uriOffset = _computeUriOffset(syntheticAssignment);
return unhandled(
"${syntheticAssignment.runtimeType}",
"handleForInStatementWithoutVariable",
- syntheticAssignment.fileOffset,
- inferrer.helper.uri);
+ uriOffset.fileOffset,
+ uriOffset.uri);
}
}
@@ -7262,3 +7340,10 @@
Expression inferAssignment(TypeInferrerImpl inferrer, DartType rhsType) =>
expression;
}
+
+class _UriOffset {
+ final Uri uri;
+ final int fileOffset;
+
+ _UriOffset(this.uri, this.fileOffset);
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index eb47f3f..3fe1f73 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -1214,6 +1214,8 @@
isExperimentEnabledGlobally(ExperimentalFlag.tripleShift),
enableConstFunctions:
isExperimentEnabledGlobally(ExperimentalFlag.constFunctions),
+ enableConstructorTearOff:
+ isExperimentEnabledGlobally(ExperimentalFlag.constructorTearoffs),
errorOnUnevaluatedConstant: errorOnUnevaluatedConstant);
ticker.logMs("Evaluated constants");
@@ -1255,18 +1257,21 @@
constants.EvaluationMode evaluationMode = _getConstantEvaluationMode();
constants.transformProcedure(
- procedure,
- backendTarget.constantsBackend(loader.coreTypes),
- environmentDefines,
- environment,
- new KernelConstantErrorReporter(loader),
- evaluationMode,
- evaluateAnnotations: true,
- enableTripleShift:
- isExperimentEnabledGlobally(ExperimentalFlag.tripleShift),
- enableConstFunctions:
- isExperimentEnabledGlobally(ExperimentalFlag.constFunctions),
- errorOnUnevaluatedConstant: errorOnUnevaluatedConstant);
+ procedure,
+ backendTarget.constantsBackend(loader.coreTypes),
+ environmentDefines,
+ environment,
+ new KernelConstantErrorReporter(loader),
+ evaluationMode,
+ evaluateAnnotations: true,
+ enableTripleShift:
+ isExperimentEnabledGlobally(ExperimentalFlag.tripleShift),
+ enableConstFunctions:
+ isExperimentEnabledGlobally(ExperimentalFlag.constFunctions),
+ enableConstructorTearOff:
+ isExperimentEnabledGlobally(ExperimentalFlag.constructorTearoffs),
+ errorOnUnevaluatedConstant: errorOnUnevaluatedConstant,
+ );
ticker.logMs("Evaluated constants");
backendTarget.performTransformationsOnProcedure(
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 bffa568..00e4320 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
@@ -3533,23 +3533,43 @@
typeParameter = null;
} else {
if (issue.enclosingType == null && targetReceiver != null) {
- if (issueInferred) {
- message =
- templateIncorrectTypeArgumentQualifiedInferred.withArguments(
- argument,
- typeParameter.bound,
- typeParameter.name,
- targetReceiver,
- targetName,
- isNonNullableByDefault);
+ if (targetName != null) {
+ if (issueInferred) {
+ message =
+ templateIncorrectTypeArgumentQualifiedInferred.withArguments(
+ argument,
+ typeParameter.bound,
+ typeParameter.name,
+ targetReceiver,
+ targetName,
+ isNonNullableByDefault);
+ } else {
+ message = templateIncorrectTypeArgumentQualified.withArguments(
+ argument,
+ typeParameter.bound,
+ typeParameter.name,
+ targetReceiver,
+ targetName,
+ isNonNullableByDefault);
+ }
} else {
- message = templateIncorrectTypeArgumentQualified.withArguments(
- argument,
- typeParameter.bound,
- typeParameter.name,
- targetReceiver,
- targetName,
- isNonNullableByDefault);
+ if (issueInferred) {
+ message = templateIncorrectTypeArgumentInstantiationInferred
+ .withArguments(
+ argument,
+ typeParameter.bound,
+ typeParameter.name,
+ targetReceiver,
+ isNonNullableByDefault);
+ } else {
+ message =
+ templateIncorrectTypeArgumentInstantiation.withArguments(
+ argument,
+ typeParameter.bound,
+ typeParameter.name,
+ targetReceiver,
+ isNonNullableByDefault);
+ }
}
} else {
String enclosingName = issue.enclosingType == null
@@ -4046,6 +4066,41 @@
targetName: localName ?? 'call');
}
+ void checkBoundsInInstantiation(
+ TypeEnvironment typeEnvironment,
+ ClassHierarchy hierarchy,
+ TypeInferrerImpl typeInferrer,
+ FunctionType functionType,
+ List<DartType> typeArguments,
+ Uri fileUri,
+ int offset,
+ {bool inferred}) {
+ assert(inferred != null);
+ if (typeArguments.isEmpty) return;
+
+ List<TypeParameter> functionTypeParameters = functionType.typeParameters;
+ // The error is to be reported elsewhere.
+ if (functionTypeParameters.length != typeArguments.length) return;
+ final DartType bottomType = isNonNullableByDefault
+ ? const NeverType.nonNullable()
+ : const NullType();
+ List<TypeArgumentIssue> issues = findTypeArgumentIssuesForInvocation(
+ functionTypeParameters,
+ typeArguments,
+ typeEnvironment,
+ isNonNullableByDefault
+ ? SubtypeCheckMode.withNullabilities
+ : SubtypeCheckMode.ignoringNullabilities,
+ bottomType,
+ isNonNullableByDefault: library.isNonNullableByDefault,
+ areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
+ reportTypeArgumentIssues(issues, fileUri, offset,
+ targetReceiver: functionType,
+ typeArgumentsInfo: inferred
+ ? const AllInferredTypeArgumentsInfo()
+ : const NoneInferredTypeArgumentsInfo());
+ }
+
void checkTypesInOutline(TypeEnvironment typeEnvironment) {
Iterator<Builder> iterator = this.iterator;
while (iterator.moveNext()) {
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 03c4d7d..ddf578b 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -1578,6 +1578,9 @@
bool operator==(dynamic) {}
}
+abstract class Enum {
+}
+
class String {}
class Symbol {}
diff --git a/pkg/front_end/lib/src/fasta/source/value_kinds.dart b/pkg/front_end/lib/src/fasta/source/value_kinds.dart
index 1f59675..03261c1 100644
--- a/pkg/front_end/lib/src/fasta/source/value_kinds.dart
+++ b/pkg/front_end/lib/src/fasta/source/value_kinds.dart
@@ -85,6 +85,8 @@
static const ValueKind Token = const SingleValueKind<type.Token>();
static const ValueKind TokenOrNull =
const SingleValueKind<type.Token>(NullValue.Token);
+ static const ValueKind TypeArguments =
+ const SingleValueKind<List<type.UnresolvedType>>();
static const ValueKind TypeArgumentsOrNull =
const SingleValueKind<List<type.UnresolvedType>>(NullValue.TypeArguments);
static const ValueKind TypeBuilder =
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 a02f453..5424d61 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
@@ -3752,6 +3752,19 @@
}
}
+ void checkBoundsInInstantiation(
+ FunctionType functionType, List<DartType> arguments, int fileOffset,
+ {bool inferred}) {
+ assert(inferred != null);
+ // If [arguments] were inferred, check them.
+ if (!isTopLevel) {
+ // We only perform checks in full inference.
+ library.checkBoundsInInstantiation(typeSchemaEnvironment, classHierarchy,
+ this, functionType, arguments, helper.uri, fileOffset,
+ inferred: inferred);
+ }
+ }
+
void _checkBoundsInFunctionInvocation(FunctionType functionType,
String localName, Arguments arguments, int fileOffset) {
// If [arguments] were inferred, check them.
@@ -3910,6 +3923,9 @@
typeSchemaEnvironment.inferGenericFunctionOrType(instantiatedType,
typeParameters, [], [], context, inferredTypes, library.library);
if (!isTopLevel) {
+ checkBoundsInInstantiation(
+ functionType, inferredTypes, expression.fileOffset,
+ inferred: true);
expression = new Instantiation(expression, inferredTypes)
..fileOffset = expression.fileOffset;
}
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 709f244..18c7bae 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -434,6 +434,9 @@
InitializerOutsideConstructor/example: Fail
InputFileNotFound/analyzerCode: Fail
InputFileNotFound/example: Fail
+InstantiationNonGenericFunctionType/analyzerCode: Fail
+InstantiationTooFewArguments/analyzerCode: Fail
+InstantiationTooManyArguments/analyzerCode: Fail
IntegerLiteralIsOutOfRange/example: Fail
InterfaceCheck/analyzerCode: Fail
InterfaceCheck/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index c411adb..8045d59 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -4291,6 +4291,27 @@
class A<T extends A<T>> {}
class B extends A {}
+IncorrectTypeArgumentInstantiation:
+ template: "Type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#type3'."
+ tip: "Try changing type arguments so that they conform to the bounds."
+ analyzerCode: TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
+ experiments: constructor-tearoffs
+ script: |
+ X bounded<X extends num>(X x) => x;
+ main() {
+ bounded<String>;
+ }
+
+IncorrectTypeArgumentInstantiationInferred:
+ template: "Inferred type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#type3'."
+ tip: "Try specifying type arguments explicitly so that they conform to the bounds."
+ analyzerCode: TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
+ script: |
+ X bounded<X extends num>(X x) => x;
+ main() {
+ String Function(String) c = bounded;
+ }
+
IncorrectTypeArgumentVariable:
template: "This is the type variable whose bound isn't conformed to."
severity: CONTEXT
@@ -5187,3 +5208,27 @@
severity: INFO
script: |
import 'dart-ext:foo.dart';
+
+InstantiationNonGenericFunctionType:
+ template: "The static type of the explicit instantiation operand must be a generic function type but is '#type'."
+ tip: "Try changing the operand or remove the type arguments."
+ experiments: constructor-tearoffs
+ script: |
+ f() {}
+ main() => f<int>;
+
+InstantiationTooFewArguments:
+ template: "Too few type arguments: #count required, #count2 given."
+ tip: "Try adding the missing type arguments."
+ experiments: constructor-tearoffs
+ script: |
+ f<X, Y>() {}
+ main() => f<int>;
+
+InstantiationTooManyArguments:
+ template: "Too many type arguments: #count allowed, but #count2 found."
+ tip: "Try removing the extra type arguments."
+ experiments: constructor-tearoffs
+ script: |
+ f<X>() {}
+ main() => f<int, String>;
diff --git a/pkg/front_end/test/constant_evaluator_benchmark.dart b/pkg/front_end/test/constant_evaluator_benchmark.dart
index c1eb8fb..4595cf8 100644
--- a/pkg/front_end/test/constant_evaluator_benchmark.dart
+++ b/pkg/front_end/test/constant_evaluator_benchmark.dart
@@ -103,6 +103,8 @@
.isExperimentEnabledGlobally(ExperimentalFlag.tripleShift),
enableConstFunctions: target
.isExperimentEnabledGlobally(ExperimentalFlag.constFunctions),
+ enableConstructorTearOff: target.isExperimentEnabledGlobally(
+ ExperimentalFlag.constructorTearoffs),
errorOnUnevaluatedConstant:
incrementalCompiler.context.options.errorOnUnevaluatedConstant);
print("Transformed constants with $environmentDefinesDescription"
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 2ff813f..c957a82 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -267,9 +267,11 @@
ec
echo
edits
+einst
elapse
elegantly
ell
+emethod
entrypoint
entrypoints
eoo
@@ -278,6 +280,7 @@
erased
err
esc
+estat
et
everytime
evicting
@@ -294,6 +297,10 @@
expansive
explainer
extern
+f1
+f2
+f3
+f4
fac
faking
falling
@@ -530,6 +537,7 @@
minimize
minimizer
minimizing
+minst
mintty
minutes
mismatched
@@ -539,11 +547,13 @@
misspelled
mistake
mistakes
+mmethod
mod
modelled
month
moo
mouse
+mstat
mul
mx
mxn
diff --git a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.expect b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.expect
index 3f856cd..a52e3ca 100644
--- a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.expect
+++ b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.expect
@@ -16,7 +16,7 @@
import self as mai;
import "dart:core" as core;
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<mai::Enum> values = #C4;
diff --git a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect
index 4306d18..f92bdce 100644
--- a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect
@@ -17,7 +17,7 @@
import self as mai;
import "dart:core" as core;
-abstract class Enum extends core::Object {
+abstract class Enum extends core::Object implements core::Enum {
}
class Class extends core::Object {
synthetic constructor •() → mai::Class
diff --git a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.weak.expect b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.weak.expect
index de7f194..c05364c 100644
--- a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.weak.expect
+++ b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.weak.expect
@@ -16,7 +16,7 @@
import self as mai;
import "dart:core" as core;
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<mai::Enum> values = #C4;
diff --git a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.weak.outline.expect b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.weak.outline.expect
index 21ae4a4..1dd0498 100644
--- a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.weak.outline.expect
@@ -10,7 +10,7 @@
import self as self2;
import "dart:core" as core;
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self2::Enum> values = #C4;
diff --git a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.weak.transformed.expect b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.weak.transformed.expect
index e779a8d..33ef7bc 100644
--- a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.weak.transformed.expect
@@ -17,7 +17,7 @@
import self as mai;
import "dart:core" as core;
-abstract class Enum extends core::Object {
+abstract class Enum extends core::Object implements core::Enum {
abstract get /*isLegacy*/ index() → core::int;
}
class Class extends core::Object {
diff --git a/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.expect b/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.expect
index be139bc..961f514 100644
--- a/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.expect
+++ b/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.expect
@@ -5,7 +5,7 @@
import "org-dartlang-testcase:///main_lib.dart";
-class UnusedEnum extends core::Object /*isEnum*/ {
+class UnusedEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::UnusedEnum> values = #C7;
@@ -17,7 +17,7 @@
method toString() → core::String
return this.{self::UnusedEnum::_name}{core::String};
}
-class UsedEnum extends core::Object /*isEnum*/ {
+class UsedEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::UsedEnum> values = #C12;
@@ -67,7 +67,7 @@
import self as mai;
import "dart:core" as core;
-class ConstEnum extends core::Object /*isEnum*/ {
+class ConstEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<mai::ConstEnum> values = #C15;
diff --git a/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect b/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect
index bc950b3..077bd72 100644
--- a/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect
@@ -6,9 +6,9 @@
import "org-dartlang-testcase:///main_lib.dart";
-abstract class UnusedEnum extends core::Object {
+abstract class UnusedEnum extends core::Object implements core::Enum {
}
-class UsedEnum extends core::Object /*isEnum*/ {
+class UsedEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
method toString() → core::String
@@ -43,7 +43,7 @@
import self as mai;
import "dart:core" as core;
-abstract class ConstEnum extends core::Object {
+abstract class ConstEnum extends core::Object implements core::Enum {
}
class ConstClass extends core::Object {
synthetic constructor •() → mai::ConstClass
diff --git a/pkg/front_end/testcases/aot/tree_shake/main.dart.weak.expect b/pkg/front_end/testcases/aot/tree_shake/main.dart.weak.expect
index 9b15013..cd3c2b4 100644
--- a/pkg/front_end/testcases/aot/tree_shake/main.dart.weak.expect
+++ b/pkg/front_end/testcases/aot/tree_shake/main.dart.weak.expect
@@ -5,7 +5,7 @@
import "org-dartlang-testcase:///main_lib.dart";
-class UnusedEnum extends core::Object /*isEnum*/ {
+class UnusedEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::UnusedEnum> values = #C7;
@@ -17,7 +17,7 @@
method toString() → core::String
return this.{self::UnusedEnum::_name}{core::String};
}
-class UsedEnum extends core::Object /*isEnum*/ {
+class UsedEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::UsedEnum> values = #C12;
@@ -67,7 +67,7 @@
import self as mai;
import "dart:core" as core;
-class ConstEnum extends core::Object /*isEnum*/ {
+class ConstEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<mai::ConstEnum> values = #C15;
diff --git a/pkg/front_end/testcases/aot/tree_shake/main.dart.weak.outline.expect b/pkg/front_end/testcases/aot/tree_shake/main.dart.weak.outline.expect
index 4e85b30..a041682 100644
--- a/pkg/front_end/testcases/aot/tree_shake/main.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/aot/tree_shake/main.dart.weak.outline.expect
@@ -4,7 +4,7 @@
import "org-dartlang-testcase:///main_lib.dart";
-class UnusedEnum extends core::Object /*isEnum*/ {
+class UnusedEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::UnusedEnum> values = const <self::UnusedEnum>[self::UnusedEnum::a, self::UnusedEnum::b];
@@ -16,7 +16,7 @@
method toString() → core::String
return this.{self::UnusedEnum::_name}{core::String};
}
-class UsedEnum extends core::Object /*isEnum*/ {
+class UsedEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::UsedEnum> values = const <self::UsedEnum>[self::UsedEnum::unusedValue, self::UsedEnum::usedValue];
@@ -55,7 +55,7 @@
import self as self2;
import "dart:core" as core;
-class ConstEnum extends core::Object /*isEnum*/ {
+class ConstEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self2::ConstEnum> values = #C4;
diff --git a/pkg/front_end/testcases/aot/tree_shake/main.dart.weak.transformed.expect b/pkg/front_end/testcases/aot/tree_shake/main.dart.weak.transformed.expect
index 0ab2aae..9382897 100644
--- a/pkg/front_end/testcases/aot/tree_shake/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/aot/tree_shake/main.dart.weak.transformed.expect
@@ -6,9 +6,9 @@
import "org-dartlang-testcase:///main_lib.dart";
-abstract class UnusedEnum extends core::Object {
+abstract class UnusedEnum extends core::Object implements core::Enum {
}
-class UsedEnum extends core::Object /*isEnum*/ {
+class UsedEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
method toString() → core::String
@@ -43,7 +43,7 @@
import self as mai;
import "dart:core" as core;
-abstract class ConstEnum extends core::Object {
+abstract class ConstEnum extends core::Object implements core::Enum {
abstract get /*isLegacy*/ index() → core::int;
}
class ConstClass extends core::Object {
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart
new file mode 100644
index 0000000..6d8b22b
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart
@@ -0,0 +1,9 @@
+// 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.
+
+T func<T>(T value) => value;
+var funcValue = func;
+int Function(int) f = funcValue.call; // Disallowed!
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.expect
new file mode 100644
index 0000000..2d0b3bf
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:7:33: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
+// int Function(int) f = funcValue.call; // Disallowed!
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static field <T extends core::Object? = dynamic>(T%) → T% funcValue = #C1;
+static field (core::int) → core::int f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:7:33: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
+int Function(int) f = funcValue.call; // Disallowed!
+ ^" in self::funcValue.call as{TypeError,ForNonNullableByDefault} (core::int) → core::int;
+static method func<T extends core::Object? = dynamic>(self::func::T% value) → self::func::T%
+ return value;
+static method main() → dynamic {}
+
+constants {
+ #C1 = tearoff self::func
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.transformed.expect
new file mode 100644
index 0000000..2d0b3bf
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.transformed.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:7:33: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
+// int Function(int) f = funcValue.call; // Disallowed!
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static field <T extends core::Object? = dynamic>(T%) → T% funcValue = #C1;
+static field (core::int) → core::int f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:7:33: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
+int Function(int) f = funcValue.call; // Disallowed!
+ ^" in self::funcValue.call as{TypeError,ForNonNullableByDefault} (core::int) → core::int;
+static method func<T extends core::Object? = dynamic>(self::func::T% value) → self::func::T%
+ return value;
+static method main() → dynamic {}
+
+constants {
+ #C1 = tearoff self::func
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline.expect
new file mode 100644
index 0000000..26c075f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+T func<T>(T value) => value;
+var funcValue = func;
+int Function(int) f = funcValue.call;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fa69e2d
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline_modelled.expect
@@ -0,0 +1,4 @@
+T func<T>(T value) => value;
+int Function(int) f = funcValue.call;
+main() {}
+var funcValue = func;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.expect
new file mode 100644
index 0000000..2d0b3bf
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:7:33: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
+// int Function(int) f = funcValue.call; // Disallowed!
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static field <T extends core::Object? = dynamic>(T%) → T% funcValue = #C1;
+static field (core::int) → core::int f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:7:33: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
+int Function(int) f = funcValue.call; // Disallowed!
+ ^" in self::funcValue.call as{TypeError,ForNonNullableByDefault} (core::int) → core::int;
+static method func<T extends core::Object? = dynamic>(self::func::T% value) → self::func::T%
+ return value;
+static method main() → dynamic {}
+
+constants {
+ #C1 = tearoff self::func
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.outline.expect
new file mode 100644
index 0000000..cce6eb8
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.outline.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static field <T extends core::Object? = dynamic>(T%) → T% funcValue;
+static field (core::int) → core::int f;
+static method func<T extends core::Object? = dynamic>(self::func::T% value) → self::func::T%
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.transformed.expect
new file mode 100644
index 0000000..2d0b3bf
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.transformed.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:7:33: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
+// int Function(int) f = funcValue.call; // Disallowed!
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static field <T extends core::Object? = dynamic>(T%) → T% funcValue = #C1;
+static field (core::int) → core::int f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:7:33: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
+int Function(int) f = funcValue.call; // Disallowed!
+ ^" in self::funcValue.call as{TypeError,ForNonNullableByDefault} (core::int) → core::int;
+static method func<T extends core::Object? = dynamic>(self::func::T% value) → self::func::T%
+ return value;
+static method main() → dynamic {}
+
+constants {
+ #C1 = tearoff self::func
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart
new file mode 100644
index 0000000..10102d5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart
@@ -0,0 +1,71 @@
+// 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 ListList<T> = List<List<T>>;
+
+T top<T>(T value) => value;
+
+class C {
+ static T stat<T>(T value) => value;
+ T inst<T>(T value) => value;
+ void method() {
+ var f1 = stat<int>;
+ var f1TypeName = stat<int>.runtimeType.toString();
+ var f2 = inst<int>;
+ var f2TypeName = inst<int>.runtimeType.toString();
+ var f3 = this.inst<int>;
+ var f3TypeName = this.inst<int>.runtimeType.toString();
+ }
+}
+
+mixin M on C {
+ static T mstat<T>(T value) => value;
+ T minst<T>(T value) => value;
+ void mmethod() {
+ var f1 = mstat<int>;
+ var f1TypeName = mstat<int>.runtimeType.toString();
+ var f2 = minst<int>;
+ var f2TypeName = minst<int>.runtimeType.toString();
+ var f3 = this.minst<int>;
+ var f3TypeName = this.minst<int>.runtimeType.toString();
+ }
+}
+
+extension Ext on C {
+ static T estat<T>(T value) => value;
+ T einst<T>(T value) => value;
+ void emethod() {
+ var f1 = estat<int>; // works like (int $) => Ext.estat<int>($)
+ var f1TypeName = estat<int>.runtimeType.toString();
+ var f2 = einst<int>; // works like (int $) => Ext(this).einst<int>($)
+ var f2TypeName = einst<int>.runtimeType.toString();
+ var f3 = this.einst<int>; // works like (int $) => Ext(this).einst<int>($)
+ var f3TypeName = this.einst<int>.runtimeType.toString();
+ }
+}
+class D extends C with M {
+ void method() {
+ var f4 = super.inst<int>; // works like (int $) => super.inst<int>($)
+ var f4TypeName = super.inst<int>.runtimeType.toString();
+ }
+}
+void main() {
+ // Type literals.
+ var t1 = List<int>; // Type object for `List<int>`.
+ var t2 = ListList<int>; // Type object for `List<List<int>>`.
+
+ // Instantiated function tear-offs.
+ T local<T>(T value) => value;
+
+ const f1 = top<int>; // int Function(int), works like (int $) => top<int>($);
+ const f2 = C.stat<int>; // int Function(int), works like (int $) => C.stat<int>($);
+ var f3 = local<int>; // int Function(int), works like (int $) => local<int>($);
+ var d = D();
+ var f4 = d.inst<int>; // int Function(int), works like (int $) => c.inst<int>($);
+ var f5 = d.minst<int>; // int Function(int), works like (int $) => c.minst<int>($);
+ var f6 = d.einst<int>; // int Function(int), works like (int $) => Ext(c).einst<int>($);
+
+ var typeName = (List<int>).toString();
+ var functionTypeName = local<int>.runtimeType.toString();
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.expect
new file mode 100644
index 0000000..efd5a53
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.expect
@@ -0,0 +1,103 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef ListList<T extends core::Object? = dynamic> = core::List<core::List<T%>>;
+class C extends core::Object {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method stat<T extends core::Object? = dynamic>(self::C::stat::T% value) → self::C::stat::T%
+ return value;
+ method inst<T extends core::Object? = dynamic>(self::C::inst::T% value) → self::C::inst::T%
+ return value;
+ method method() → void {
+ (core::int) → core::int f1 = #C2;
+ core::String f1TypeName = (#C2).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f2TypeName = (this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f3TypeName = (this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+}
+abstract class M extends self::C /*isMixinDeclaration*/ {
+ static method mstat<T extends core::Object? = dynamic>(self::M::mstat::T% value) → self::M::mstat::T%
+ return value;
+ method minst<T extends core::Object? = dynamic>(self::M::minst::T% value) → self::M::minst::T%
+ return value;
+ method mmethod() → void {
+ (core::int) → core::int f1 = #C4;
+ core::String f1TypeName = (#C4).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f2TypeName = (this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f3TypeName = (this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+}
+abstract class _D&C&M = self::C with self::M /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_D&C&M
+ : super self::C::•()
+ ;
+ mixin-super-stub method minst<T extends core::Object? = dynamic>(self::_D&C&M::minst::T% value) → self::_D&C&M::minst::T%
+ return super.{self::M::minst}<self::_D&C&M::minst::T%>(value);
+ mixin-super-stub method mmethod() → void
+ return super.{self::M::mmethod}();
+}
+class D extends self::_D&C&M {
+ synthetic constructor •() → self::D
+ : super self::_D&C&M::•()
+ ;
+ method method() → void {
+ (core::int) → core::int f4 = super.{self::C::inst}<core::int>;
+ core::String f4TypeName = (super.{self::C::inst}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+}
+extension Ext on self::C {
+ static method estat = self::Ext|estat;
+ method einst = self::Ext|einst;
+ tearoff einst = self::Ext|get#einst;
+ method emethod = self::Ext|emethod;
+ tearoff emethod = self::Ext|get#emethod;
+}
+static method top<T extends core::Object? = dynamic>(self::top::T% value) → self::top::T%
+ return value;
+static method Ext|estat<T extends core::Object? = dynamic>(self::Ext|estat::T% value) → self::Ext|estat::T%
+ return value;
+static method Ext|einst<T extends core::Object? = dynamic>(lowered final self::C #this, self::Ext|einst::T% value) → self::Ext|einst::T%
+ return value;
+static method Ext|get#einst(lowered final self::C #this) → <T extends core::Object? = dynamic>(T%) → T%
+ return <T extends core::Object? = dynamic>(T% value) → T% => self::Ext|einst<T%>(#this, value);
+static method Ext|emethod(lowered final self::C #this) → void {
+ (core::int) → core::int f1 = #C6;
+ core::String f1TypeName = (#C6).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = self::Ext|get#einst(#this)<core::int>;
+ core::String f2TypeName = (self::Ext|get#einst(#this)<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = self::Ext|get#einst(#this)<core::int>;
+ core::String f3TypeName = (self::Ext|get#einst(#this)<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+}
+static method Ext|get#emethod(lowered final self::C #this) → () → void
+ return () → void => self::Ext|emethod(#this);
+static method main() → void {
+ core::Type t1 = #C7;
+ core::Type t2 = #C8;
+ function local<T extends core::Object? = dynamic>(T% value) → T%
+ return value;
+ (core::int) → core::int f3 = local<core::int>;
+ self::D d = new self::D::•();
+ (core::int) → core::int f4 = d.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ (core::int) → core::int f5 = d.{self::_D&C&M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ (core::int) → core::int f6 = self::Ext|get#einst(d)<core::int>;
+ core::String typeName = (#C7).{core::Type::toString}(){() → core::String};
+ core::String functionTypeName = (local<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+}
+
+constants {
+ #C1 = tearoff self::C::stat
+ #C2 = partial-instantiation self::C::stat <core::int>
+ #C3 = tearoff self::M::mstat
+ #C4 = partial-instantiation self::M::mstat <core::int>
+ #C5 = tearoff self::Ext|estat
+ #C6 = partial-instantiation self::Ext|estat <core::int>
+ #C7 = TypeLiteralConstant(core::List<core::int>)
+ #C8 = TypeLiteralConstant(core::List<core::List<core::int>>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.transformed.expect
new file mode 100644
index 0000000..ba6e6f0
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.transformed.expect
@@ -0,0 +1,111 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef ListList<T extends core::Object? = dynamic> = core::List<core::List<T%>>;
+class C extends core::Object {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method stat<T extends core::Object? = dynamic>(self::C::stat::T% value) → self::C::stat::T%
+ return value;
+ method inst<T extends core::Object? = dynamic>(self::C::inst::T% value) → self::C::inst::T%
+ return value;
+ method method() → void {
+ (core::int) → core::int f1 = #C2;
+ core::String f1TypeName = (#C2).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f2TypeName = (this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f3TypeName = (this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+}
+abstract class M extends self::C /*isMixinDeclaration*/ {
+ static method mstat<T extends core::Object? = dynamic>(self::M::mstat::T% value) → self::M::mstat::T%
+ return value;
+ method minst<T extends core::Object? = dynamic>(self::M::minst::T% value) → self::M::minst::T%
+ return value;
+ method mmethod() → void {
+ (core::int) → core::int f1 = #C4;
+ core::String f1TypeName = (#C4).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f2TypeName = (this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f3TypeName = (this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+}
+abstract class _D&C&M extends self::C implements self::M /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_D&C&M
+ : super self::C::•()
+ ;
+ method minst<T extends core::Object? = dynamic>(self::_D&C&M::minst::T% value) → self::_D&C&M::minst::T%
+ return value;
+ method mmethod() → void {
+ (core::int) → core::int f1 = #C4;
+ core::String f1TypeName = (#C4).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f2TypeName = (this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f3TypeName = (this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+ static method mstat<T extends core::Object? = dynamic>(self::_D&C&M::mstat::T% value) → self::_D&C&M::mstat::T%
+ return value;
+}
+class D extends self::_D&C&M {
+ synthetic constructor •() → self::D
+ : super self::_D&C&M::•()
+ ;
+ method method() → void {
+ (core::int) → core::int f4 = super.{self::C::inst}<core::int>;
+ core::String f4TypeName = (super.{self::C::inst}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+}
+extension Ext on self::C {
+ static method estat = self::Ext|estat;
+ method einst = self::Ext|einst;
+ tearoff einst = self::Ext|get#einst;
+ method emethod = self::Ext|emethod;
+ tearoff emethod = self::Ext|get#emethod;
+}
+static method top<T extends core::Object? = dynamic>(self::top::T% value) → self::top::T%
+ return value;
+static method Ext|estat<T extends core::Object? = dynamic>(self::Ext|estat::T% value) → self::Ext|estat::T%
+ return value;
+static method Ext|einst<T extends core::Object? = dynamic>(lowered final self::C #this, self::Ext|einst::T% value) → self::Ext|einst::T%
+ return value;
+static method Ext|get#einst(lowered final self::C #this) → <T extends core::Object? = dynamic>(T%) → T%
+ return <T extends core::Object? = dynamic>(T% value) → T% => self::Ext|einst<T%>(#this, value);
+static method Ext|emethod(lowered final self::C #this) → void {
+ (core::int) → core::int f1 = #C6;
+ core::String f1TypeName = (#C6).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = self::Ext|get#einst(#this)<core::int>;
+ core::String f2TypeName = (self::Ext|get#einst(#this)<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = self::Ext|get#einst(#this)<core::int>;
+ core::String f3TypeName = (self::Ext|get#einst(#this)<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+}
+static method Ext|get#emethod(lowered final self::C #this) → () → void
+ return () → void => self::Ext|emethod(#this);
+static method main() → void {
+ core::Type t1 = #C7;
+ core::Type t2 = #C8;
+ function local<T extends core::Object? = dynamic>(T% value) → T%
+ return value;
+ (core::int) → core::int f3 = local<core::int>;
+ self::D d = new self::D::•();
+ (core::int) → core::int f4 = d.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ (core::int) → core::int f5 = d.{self::_D&C&M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ (core::int) → core::int f6 = self::Ext|get#einst(d)<core::int>;
+ core::String typeName = (#C7).{core::Type::toString}(){() → core::String};
+ core::String functionTypeName = (local<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+}
+
+constants {
+ #C1 = tearoff self::C::stat
+ #C2 = partial-instantiation self::C::stat <core::int>
+ #C3 = tearoff self::M::mstat
+ #C4 = partial-instantiation self::M::mstat <core::int>
+ #C5 = tearoff self::Ext|estat
+ #C6 = partial-instantiation self::Ext|estat <core::int>
+ #C7 = TypeLiteralConstant(core::List<core::int>)
+ #C8 = TypeLiteralConstant(core::List<core::List<core::int>>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.textual_outline.expect
new file mode 100644
index 0000000..809236b
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.textual_outline.expect
@@ -0,0 +1,26 @@
+typedef ListList<T> = List<List<T>>;
+T top<T>(T value) => value;
+
+class C {
+ static T stat<T>(T value) => value;
+ T inst<T>(T value) => value;
+ void method() {}
+}
+
+mixin M on C {
+ static T mstat<T>(T value) => value;
+ T minst<T>(T value) => value;
+ void mmethod() {}
+}
+
+extension Ext on C {
+ static T estat<T>(T value) => value;
+ T einst<T>(T value) => value;
+ void emethod() {}
+}
+
+class D extends C with M {
+ void method() {}
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0322870
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+T top<T>(T value) => value;
+
+class C {
+ T inst<T>(T value) => value;
+ static T stat<T>(T value) => value;
+ void method() {}
+}
+
+class D extends C with M {
+ void method() {}
+}
+
+extension Ext on C {
+ T einst<T>(T value) => value;
+ static T estat<T>(T value) => value;
+ void emethod() {}
+}
+
+mixin M on C {
+ T minst<T>(T value) => value;
+ static T mstat<T>(T value) => value;
+ void mmethod() {}
+}
+typedef ListList<T> = List<List<T>>;
+void main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.expect
new file mode 100644
index 0000000..70f8b63
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.expect
@@ -0,0 +1,103 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef ListList<T extends core::Object? = dynamic> = core::List<core::List<T%>>;
+class C extends core::Object {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method stat<T extends core::Object? = dynamic>(self::C::stat::T% value) → self::C::stat::T%
+ return value;
+ method inst<T extends core::Object? = dynamic>(self::C::inst::T% value) → self::C::inst::T%
+ return value;
+ method method() → void {
+ (core::int) → core::int f1 = #C2;
+ core::String f1TypeName = (#C2).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f2TypeName = (this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f3TypeName = (this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+}
+abstract class M extends self::C /*isMixinDeclaration*/ {
+ static method mstat<T extends core::Object? = dynamic>(self::M::mstat::T% value) → self::M::mstat::T%
+ return value;
+ method minst<T extends core::Object? = dynamic>(self::M::minst::T% value) → self::M::minst::T%
+ return value;
+ method mmethod() → void {
+ (core::int) → core::int f1 = #C4;
+ core::String f1TypeName = (#C4).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f2TypeName = (this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f3TypeName = (this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+}
+abstract class _D&C&M = self::C with self::M /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_D&C&M
+ : super self::C::•()
+ ;
+ mixin-super-stub method minst<T extends core::Object? = dynamic>(self::_D&C&M::minst::T% value) → self::_D&C&M::minst::T%
+ return super.{self::M::minst}<self::_D&C&M::minst::T%>(value);
+ mixin-super-stub method mmethod() → void
+ return super.{self::M::mmethod}();
+}
+class D extends self::_D&C&M {
+ synthetic constructor •() → self::D
+ : super self::_D&C&M::•()
+ ;
+ method method() → void {
+ (core::int) → core::int f4 = super.{self::C::inst}<core::int>;
+ core::String f4TypeName = (super.{self::C::inst}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+}
+extension Ext on self::C {
+ static method estat = self::Ext|estat;
+ method einst = self::Ext|einst;
+ tearoff einst = self::Ext|get#einst;
+ method emethod = self::Ext|emethod;
+ tearoff emethod = self::Ext|get#emethod;
+}
+static method top<T extends core::Object? = dynamic>(self::top::T% value) → self::top::T%
+ return value;
+static method Ext|estat<T extends core::Object? = dynamic>(self::Ext|estat::T% value) → self::Ext|estat::T%
+ return value;
+static method Ext|einst<T extends core::Object? = dynamic>(lowered final self::C #this, self::Ext|einst::T% value) → self::Ext|einst::T%
+ return value;
+static method Ext|get#einst(lowered final self::C #this) → <T extends core::Object? = dynamic>(T%) → T%
+ return <T extends core::Object? = dynamic>(T% value) → T% => self::Ext|einst<T%>(#this, value);
+static method Ext|emethod(lowered final self::C #this) → void {
+ (core::int) → core::int f1 = #C6;
+ core::String f1TypeName = (#C6).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = self::Ext|get#einst(#this)<core::int>;
+ core::String f2TypeName = (self::Ext|get#einst(#this)<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = self::Ext|get#einst(#this)<core::int>;
+ core::String f3TypeName = (self::Ext|get#einst(#this)<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+}
+static method Ext|get#emethod(lowered final self::C #this) → () → void
+ return () → void => self::Ext|emethod(#this);
+static method main() → void {
+ core::Type t1 = #C7;
+ core::Type t2 = #C8;
+ function local<T extends core::Object? = dynamic>(T% value) → T%
+ return value;
+ (core::int) → core::int f3 = local<core::int>;
+ self::D d = new self::D::•();
+ (core::int) → core::int f4 = d.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ (core::int) → core::int f5 = d.{self::_D&C&M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ (core::int) → core::int f6 = self::Ext|get#einst(d)<core::int>;
+ core::String typeName = (#C7).{core::Type::toString}(){() → core::String};
+ core::String functionTypeName = (local<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+}
+
+constants {
+ #C1 = tearoff self::C::stat
+ #C2 = partial-instantiation self::C::stat <core::int*>
+ #C3 = tearoff self::M::mstat
+ #C4 = partial-instantiation self::M::mstat <core::int*>
+ #C5 = tearoff self::Ext|estat
+ #C6 = partial-instantiation self::Ext|estat <core::int*>
+ #C7 = TypeLiteralConstant(core::List<core::int*>*)
+ #C8 = TypeLiteralConstant(core::List<core::List<core::int*>*>*)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.outline.expect
new file mode 100644
index 0000000..6476dce
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.outline.expect
@@ -0,0 +1,59 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef ListList<T extends core::Object? = dynamic> = core::List<core::List<T%>>;
+class C extends core::Object {
+ synthetic constructor •() → self::C
+ ;
+ static method stat<T extends core::Object? = dynamic>(self::C::stat::T% value) → self::C::stat::T%
+ ;
+ method inst<T extends core::Object? = dynamic>(self::C::inst::T% value) → self::C::inst::T%
+ ;
+ method method() → void
+ ;
+}
+abstract class M extends self::C /*isMixinDeclaration*/ {
+ static method mstat<T extends core::Object? = dynamic>(self::M::mstat::T% value) → self::M::mstat::T%
+ ;
+ method minst<T extends core::Object? = dynamic>(self::M::minst::T% value) → self::M::minst::T%
+ ;
+ method mmethod() → void
+ ;
+}
+abstract class _D&C&M = self::C with self::M /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_D&C&M
+ : super self::C::•()
+ ;
+ mixin-super-stub method minst<T extends core::Object? = dynamic>(self::_D&C&M::minst::T% value) → self::_D&C&M::minst::T%
+ return super.{self::M::minst}<self::_D&C&M::minst::T%>(value);
+ mixin-super-stub method mmethod() → void
+ return super.{self::M::mmethod}();
+}
+class D extends self::_D&C&M {
+ synthetic constructor •() → self::D
+ ;
+ method method() → void
+ ;
+}
+extension Ext on self::C {
+ static method estat = self::Ext|estat;
+ method einst = self::Ext|einst;
+ tearoff einst = self::Ext|get#einst;
+ method emethod = self::Ext|emethod;
+ tearoff emethod = self::Ext|get#emethod;
+}
+static method top<T extends core::Object? = dynamic>(self::top::T% value) → self::top::T%
+ ;
+static method Ext|estat<T extends core::Object? = dynamic>(self::Ext|estat::T% value) → self::Ext|estat::T%
+ ;
+static method Ext|einst<T extends core::Object? = dynamic>(lowered final self::C #this, self::Ext|einst::T% value) → self::Ext|einst::T%
+ ;
+static method Ext|get#einst(lowered final self::C #this) → <T extends core::Object? = dynamic>(T%) → T%
+ return <T extends core::Object? = dynamic>(T% value) → T% => self::Ext|einst<T%>(#this, value);
+static method Ext|emethod(lowered final self::C #this) → void
+ ;
+static method Ext|get#emethod(lowered final self::C #this) → () → void
+ return () → void => self::Ext|emethod(#this);
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.transformed.expect
new file mode 100644
index 0000000..217f0b6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.transformed.expect
@@ -0,0 +1,111 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef ListList<T extends core::Object? = dynamic> = core::List<core::List<T%>>;
+class C extends core::Object {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method stat<T extends core::Object? = dynamic>(self::C::stat::T% value) → self::C::stat::T%
+ return value;
+ method inst<T extends core::Object? = dynamic>(self::C::inst::T% value) → self::C::inst::T%
+ return value;
+ method method() → void {
+ (core::int) → core::int f1 = #C2;
+ core::String f1TypeName = (#C2).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f2TypeName = (this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f3TypeName = (this.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+}
+abstract class M extends self::C /*isMixinDeclaration*/ {
+ static method mstat<T extends core::Object? = dynamic>(self::M::mstat::T% value) → self::M::mstat::T%
+ return value;
+ method minst<T extends core::Object? = dynamic>(self::M::minst::T% value) → self::M::minst::T%
+ return value;
+ method mmethod() → void {
+ (core::int) → core::int f1 = #C4;
+ core::String f1TypeName = (#C4).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f2TypeName = (this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f3TypeName = (this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+}
+abstract class _D&C&M extends self::C implements self::M /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_D&C&M
+ : super self::C::•()
+ ;
+ method minst<T extends core::Object? = dynamic>(self::_D&C&M::minst::T% value) → self::_D&C&M::minst::T%
+ return value;
+ method mmethod() → void {
+ (core::int) → core::int f1 = #C4;
+ core::String f1TypeName = (#C4).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f2TypeName = (this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ core::String f3TypeName = (this.{self::M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+ static method mstat<T extends core::Object? = dynamic>(self::_D&C&M::mstat::T% value) → self::_D&C&M::mstat::T%
+ return value;
+}
+class D extends self::_D&C&M {
+ synthetic constructor •() → self::D
+ : super self::_D&C&M::•()
+ ;
+ method method() → void {
+ (core::int) → core::int f4 = super.{self::C::inst}<core::int>;
+ core::String f4TypeName = (super.{self::C::inst}<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ }
+}
+extension Ext on self::C {
+ static method estat = self::Ext|estat;
+ method einst = self::Ext|einst;
+ tearoff einst = self::Ext|get#einst;
+ method emethod = self::Ext|emethod;
+ tearoff emethod = self::Ext|get#emethod;
+}
+static method top<T extends core::Object? = dynamic>(self::top::T% value) → self::top::T%
+ return value;
+static method Ext|estat<T extends core::Object? = dynamic>(self::Ext|estat::T% value) → self::Ext|estat::T%
+ return value;
+static method Ext|einst<T extends core::Object? = dynamic>(lowered final self::C #this, self::Ext|einst::T% value) → self::Ext|einst::T%
+ return value;
+static method Ext|get#einst(lowered final self::C #this) → <T extends core::Object? = dynamic>(T%) → T%
+ return <T extends core::Object? = dynamic>(T% value) → T% => self::Ext|einst<T%>(#this, value);
+static method Ext|emethod(lowered final self::C #this) → void {
+ (core::int) → core::int f1 = #C6;
+ core::String f1TypeName = (#C6).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f2 = self::Ext|get#einst(#this)<core::int>;
+ core::String f2TypeName = (self::Ext|get#einst(#this)<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+ (core::int) → core::int f3 = self::Ext|get#einst(#this)<core::int>;
+ core::String f3TypeName = (self::Ext|get#einst(#this)<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+}
+static method Ext|get#emethod(lowered final self::C #this) → () → void
+ return () → void => self::Ext|emethod(#this);
+static method main() → void {
+ core::Type t1 = #C7;
+ core::Type t2 = #C8;
+ function local<T extends core::Object? = dynamic>(T% value) → T%
+ return value;
+ (core::int) → core::int f3 = local<core::int>;
+ self::D d = new self::D::•();
+ (core::int) → core::int f4 = d.{self::C::inst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ (core::int) → core::int f5 = d.{self::_D&C&M::minst}{<T extends core::Object? = dynamic>(T%) → T%}<core::int>;
+ (core::int) → core::int f6 = self::Ext|get#einst(d)<core::int>;
+ core::String typeName = (#C7).{core::Type::toString}(){() → core::String};
+ core::String functionTypeName = (local<core::int>).{core::Object::runtimeType}{core::Type}.{core::Type::toString}(){() → core::String};
+}
+
+constants {
+ #C1 = tearoff self::C::stat
+ #C2 = partial-instantiation self::C::stat <core::int*>
+ #C3 = tearoff self::M::mstat
+ #C4 = partial-instantiation self::M::mstat <core::int*>
+ #C5 = tearoff self::Ext|estat
+ #C6 = partial-instantiation self::Ext|estat <core::int*>
+ #C7 = TypeLiteralConstant(core::List<core::int*>*)
+ #C8 = TypeLiteralConstant(core::List<core::List<core::int*>*>*)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart
new file mode 100644
index 0000000..7a1e566
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart
@@ -0,0 +1,31 @@
+// 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.
+
+X id<X>(X x) => x;
+
+void method<X, Y>() {}
+
+X boundedMethod<X extends num>(X x) => x;
+
+test() {
+ var a = id; // ok
+ var b = a<int>; // ok
+ var c = id<int>; // ok
+ var d = id<int, String>; // error - too many args
+ var e = method<int>; // error - too few args
+ var f = 0<int>; // error - non-function type operand
+ var g = main<int>; // error - non-generic function type operand
+ var h = boundedMethod<String>; // error - invalid bound
+}
+
+var a = id; // ok
+var b = a<int>; // ok
+var c = id<int>; // ok
+var d = id<int, String>; // error - too many args
+var e = method<int>; // error - too few args
+var f = 0<int>; // error - non-function type operand
+var g = main<int>; // error - non-generic function type operand
+var h = boundedMethod<String>; // error - invalid bound
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.expect
new file mode 100644
index 0000000..7d47228
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.expect
@@ -0,0 +1,112 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:15:13: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var d = id<int, String>; // error - too many args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:16:17: Error: Too few type arguments: 2 required, 1 given.
+// Try adding the missing type arguments.
+// var e = method<int>; // error - too few args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:17:12: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+// Try changing the operand or remove the type arguments.
+// var f = 0<int>; // error - non-function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:18:15: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+// Try changing the operand or remove the type arguments.
+// var g = main<int>; // error - non-generic function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:19:24: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'X Function<X extends num>(X)'.
+// Try changing type arguments so that they conform to the bounds.
+// var h = boundedMethod<String>; // error - invalid bound
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:25:11: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var d = id<int, String>; // error - too many args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:26:15: Error: Too few type arguments: 2 required, 1 given.
+// Try adding the missing type arguments.
+// var e = method<int>; // error - too few args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:27:10: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+// Try changing the operand or remove the type arguments.
+// var f = 0<int>; // error - non-function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:28:13: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+// Try changing the operand or remove the type arguments.
+// var g = main<int>; // error - non-generic function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:29:22: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'X Function<X extends num>(X)'.
+// Try changing type arguments so that they conform to the bounds.
+// var h = boundedMethod<String>; // error - invalid bound
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static field <X extends core::Object? = dynamic>(X%) → X% a = #C1;
+static field (core::int) → core::int b = self::a<core::int>;
+static field (core::int) → core::int c = #C2;
+static field invalid-type d = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:25:11: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+var d = id<int, String>; // error - too many args
+ ^";
+static field invalid-type e = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:26:15: Error: Too few type arguments: 2 required, 1 given.
+Try adding the missing type arguments.
+var e = method<int>; // error - too few args
+ ^";
+static field invalid-type f = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:27:10: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+Try changing the operand or remove the type arguments.
+var f = 0<int>; // error - non-function type operand
+ ^";
+static field invalid-type g = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:28:13: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+Try changing the operand or remove the type arguments.
+var g = main<int>; // error - non-generic function type operand
+ ^";
+static field (core::String) → core::String h = #C4;
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ return x;
+static method method<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → void {}
+static method boundedMethod<X extends core::num>(self::boundedMethod::X x) → self::boundedMethod::X
+ return x;
+static method test() → dynamic {
+ <X extends core::Object? = dynamic>(X%) → X% a = #C1;
+ (core::int) → core::int b = a<core::int>;
+ (core::int) → core::int c = #C2;
+ invalid-type d = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:15:13: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var d = id<int, String>; // error - too many args
+ ^";
+ invalid-type e = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:16:17: Error: Too few type arguments: 2 required, 1 given.
+Try adding the missing type arguments.
+ var e = method<int>; // error - too few args
+ ^";
+ invalid-type f = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:17:12: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+Try changing the operand or remove the type arguments.
+ var f = 0<int>; // error - non-function type operand
+ ^";
+ invalid-type g = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:18:15: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+Try changing the operand or remove the type arguments.
+ var g = main<int>; // error - non-generic function type operand
+ ^";
+ (core::String) → core::String h = #C4;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = tearoff self::id
+ #C2 = partial-instantiation self::id <core::int>
+ #C3 = tearoff self::boundedMethod
+ #C4 = partial-instantiation self::boundedMethod <core::String>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.transformed.expect
new file mode 100644
index 0000000..7d47228
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.transformed.expect
@@ -0,0 +1,112 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:15:13: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var d = id<int, String>; // error - too many args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:16:17: Error: Too few type arguments: 2 required, 1 given.
+// Try adding the missing type arguments.
+// var e = method<int>; // error - too few args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:17:12: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+// Try changing the operand or remove the type arguments.
+// var f = 0<int>; // error - non-function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:18:15: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+// Try changing the operand or remove the type arguments.
+// var g = main<int>; // error - non-generic function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:19:24: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'X Function<X extends num>(X)'.
+// Try changing type arguments so that they conform to the bounds.
+// var h = boundedMethod<String>; // error - invalid bound
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:25:11: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var d = id<int, String>; // error - too many args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:26:15: Error: Too few type arguments: 2 required, 1 given.
+// Try adding the missing type arguments.
+// var e = method<int>; // error - too few args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:27:10: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+// Try changing the operand or remove the type arguments.
+// var f = 0<int>; // error - non-function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:28:13: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+// Try changing the operand or remove the type arguments.
+// var g = main<int>; // error - non-generic function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:29:22: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'X Function<X extends num>(X)'.
+// Try changing type arguments so that they conform to the bounds.
+// var h = boundedMethod<String>; // error - invalid bound
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static field <X extends core::Object? = dynamic>(X%) → X% a = #C1;
+static field (core::int) → core::int b = self::a<core::int>;
+static field (core::int) → core::int c = #C2;
+static field invalid-type d = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:25:11: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+var d = id<int, String>; // error - too many args
+ ^";
+static field invalid-type e = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:26:15: Error: Too few type arguments: 2 required, 1 given.
+Try adding the missing type arguments.
+var e = method<int>; // error - too few args
+ ^";
+static field invalid-type f = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:27:10: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+Try changing the operand or remove the type arguments.
+var f = 0<int>; // error - non-function type operand
+ ^";
+static field invalid-type g = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:28:13: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+Try changing the operand or remove the type arguments.
+var g = main<int>; // error - non-generic function type operand
+ ^";
+static field (core::String) → core::String h = #C4;
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ return x;
+static method method<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → void {}
+static method boundedMethod<X extends core::num>(self::boundedMethod::X x) → self::boundedMethod::X
+ return x;
+static method test() → dynamic {
+ <X extends core::Object? = dynamic>(X%) → X% a = #C1;
+ (core::int) → core::int b = a<core::int>;
+ (core::int) → core::int c = #C2;
+ invalid-type d = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:15:13: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var d = id<int, String>; // error - too many args
+ ^";
+ invalid-type e = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:16:17: Error: Too few type arguments: 2 required, 1 given.
+Try adding the missing type arguments.
+ var e = method<int>; // error - too few args
+ ^";
+ invalid-type f = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:17:12: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+Try changing the operand or remove the type arguments.
+ var f = 0<int>; // error - non-function type operand
+ ^";
+ invalid-type g = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:18:15: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+Try changing the operand or remove the type arguments.
+ var g = main<int>; // error - non-generic function type operand
+ ^";
+ (core::String) → core::String h = #C4;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = tearoff self::id
+ #C2 = partial-instantiation self::id <core::int>
+ #C3 = tearoff self::boundedMethod
+ #C4 = partial-instantiation self::boundedMethod <core::String>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.textual_outline.expect
new file mode 100644
index 0000000..ee11ff6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.textual_outline.expect
@@ -0,0 +1,13 @@
+X id<X>(X x) => x;
+void method<X, Y>() {}
+X boundedMethod<X extends num>(X x) => x;
+test() {}
+var a = id;
+var b = a<int>;
+var c = id<int>;
+var d = id<int, String>;
+var e = method<int>;
+var f = 0<int>;
+var g = main<int>;
+var h = boundedMethod<String>;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.expect
new file mode 100644
index 0000000..c32e295
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.expect
@@ -0,0 +1,112 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:15:13: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var d = id<int, String>; // error - too many args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:16:17: Error: Too few type arguments: 2 required, 1 given.
+// Try adding the missing type arguments.
+// var e = method<int>; // error - too few args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:17:12: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+// Try changing the operand or remove the type arguments.
+// var f = 0<int>; // error - non-function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:18:15: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+// Try changing the operand or remove the type arguments.
+// var g = main<int>; // error - non-generic function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:19:24: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'X Function<X extends num>(X)'.
+// Try changing type arguments so that they conform to the bounds.
+// var h = boundedMethod<String>; // error - invalid bound
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:25:11: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var d = id<int, String>; // error - too many args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:26:15: Error: Too few type arguments: 2 required, 1 given.
+// Try adding the missing type arguments.
+// var e = method<int>; // error - too few args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:27:10: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+// Try changing the operand or remove the type arguments.
+// var f = 0<int>; // error - non-function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:28:13: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+// Try changing the operand or remove the type arguments.
+// var g = main<int>; // error - non-generic function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:29:22: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'X Function<X extends num>(X)'.
+// Try changing type arguments so that they conform to the bounds.
+// var h = boundedMethod<String>; // error - invalid bound
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static field <X extends core::Object? = dynamic>(X%) → X% a = #C1;
+static field (core::int) → core::int b = self::a<core::int>;
+static field (core::int) → core::int c = #C2;
+static field invalid-type d = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:25:11: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+var d = id<int, String>; // error - too many args
+ ^";
+static field invalid-type e = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:26:15: Error: Too few type arguments: 2 required, 1 given.
+Try adding the missing type arguments.
+var e = method<int>; // error - too few args
+ ^";
+static field invalid-type f = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:27:10: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+Try changing the operand or remove the type arguments.
+var f = 0<int>; // error - non-function type operand
+ ^";
+static field invalid-type g = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:28:13: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+Try changing the operand or remove the type arguments.
+var g = main<int>; // error - non-generic function type operand
+ ^";
+static field (core::String) → core::String h = #C4;
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ return x;
+static method method<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → void {}
+static method boundedMethod<X extends core::num>(self::boundedMethod::X x) → self::boundedMethod::X
+ return x;
+static method test() → dynamic {
+ <X extends core::Object? = dynamic>(X%) → X% a = #C1;
+ (core::int) → core::int b = a<core::int>;
+ (core::int) → core::int c = #C2;
+ invalid-type d = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:15:13: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var d = id<int, String>; // error - too many args
+ ^";
+ invalid-type e = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:16:17: Error: Too few type arguments: 2 required, 1 given.
+Try adding the missing type arguments.
+ var e = method<int>; // error - too few args
+ ^";
+ invalid-type f = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:17:12: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+Try changing the operand or remove the type arguments.
+ var f = 0<int>; // error - non-function type operand
+ ^";
+ invalid-type g = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:18:15: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+Try changing the operand or remove the type arguments.
+ var g = main<int>; // error - non-generic function type operand
+ ^";
+ (core::String) → core::String h = #C4;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = tearoff self::id
+ #C2 = partial-instantiation self::id <core::int*>
+ #C3 = tearoff self::boundedMethod
+ #C4 = partial-instantiation self::boundedMethod <core::String*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.outline.expect
new file mode 100644
index 0000000..f85acff
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.outline.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static field <X extends core::Object? = dynamic>(X%) → X% a;
+static field (core::int) → core::int b;
+static field (core::int) → core::int c;
+static field invalid-type d;
+static field invalid-type e;
+static field invalid-type f;
+static field invalid-type g;
+static field (core::String) → core::String h;
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ ;
+static method method<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → void
+ ;
+static method boundedMethod<X extends core::num>(self::boundedMethod::X x) → self::boundedMethod::X
+ ;
+static method test() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.transformed.expect
new file mode 100644
index 0000000..c32e295
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.transformed.expect
@@ -0,0 +1,112 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:15:13: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var d = id<int, String>; // error - too many args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:16:17: Error: Too few type arguments: 2 required, 1 given.
+// Try adding the missing type arguments.
+// var e = method<int>; // error - too few args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:17:12: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+// Try changing the operand or remove the type arguments.
+// var f = 0<int>; // error - non-function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:18:15: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+// Try changing the operand or remove the type arguments.
+// var g = main<int>; // error - non-generic function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:19:24: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'X Function<X extends num>(X)'.
+// Try changing type arguments so that they conform to the bounds.
+// var h = boundedMethod<String>; // error - invalid bound
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:25:11: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var d = id<int, String>; // error - too many args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:26:15: Error: Too few type arguments: 2 required, 1 given.
+// Try adding the missing type arguments.
+// var e = method<int>; // error - too few args
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:27:10: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+// Try changing the operand or remove the type arguments.
+// var f = 0<int>; // error - non-function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:28:13: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+// Try changing the operand or remove the type arguments.
+// var g = main<int>; // error - non-generic function type operand
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:29:22: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'X Function<X extends num>(X)'.
+// Try changing type arguments so that they conform to the bounds.
+// var h = boundedMethod<String>; // error - invalid bound
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static field <X extends core::Object? = dynamic>(X%) → X% a = #C1;
+static field (core::int) → core::int b = self::a<core::int>;
+static field (core::int) → core::int c = #C2;
+static field invalid-type d = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:25:11: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+var d = id<int, String>; // error - too many args
+ ^";
+static field invalid-type e = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:26:15: Error: Too few type arguments: 2 required, 1 given.
+Try adding the missing type arguments.
+var e = method<int>; // error - too few args
+ ^";
+static field invalid-type f = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:27:10: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+Try changing the operand or remove the type arguments.
+var f = 0<int>; // error - non-function type operand
+ ^";
+static field invalid-type g = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:28:13: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+Try changing the operand or remove the type arguments.
+var g = main<int>; // error - non-generic function type operand
+ ^";
+static field (core::String) → core::String h = #C4;
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ return x;
+static method method<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → void {}
+static method boundedMethod<X extends core::num>(self::boundedMethod::X x) → self::boundedMethod::X
+ return x;
+static method test() → dynamic {
+ <X extends core::Object? = dynamic>(X%) → X% a = #C1;
+ (core::int) → core::int b = a<core::int>;
+ (core::int) → core::int c = #C2;
+ invalid-type d = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:15:13: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var d = id<int, String>; // error - too many args
+ ^";
+ invalid-type e = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:16:17: Error: Too few type arguments: 2 required, 1 given.
+Try adding the missing type arguments.
+ var e = method<int>; // error - too few args
+ ^";
+ invalid-type f = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:17:12: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int'.
+Try changing the operand or remove the type arguments.
+ var f = 0<int>; // error - non-function type operand
+ ^";
+ invalid-type g = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart:18:15: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic Function()'.
+Try changing the operand or remove the type arguments.
+ var g = main<int>; // error - non-generic function type operand
+ ^";
+ (core::String) → core::String h = #C4;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = tearoff self::id
+ #C2 = partial-instantiation self::id <core::int*>
+ #C3 = tearoff self::boundedMethod
+ #C4 = partial-instantiation self::boundedMethod <core::String*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart
new file mode 100644
index 0000000..6cb7494
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart
@@ -0,0 +1,54 @@
+// 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.
+
+T id<T>(T t) => t;
+
+int Function(int) implicitInstantiation = id;
+var explicitInstantiation = id<int>;
+const int Function(int) implicitConstInstantiation = id;
+const explicitConstInstantiation = id<int>;
+
+T Function(T) create<T>() => id<T>;
+
+main() {
+ expect(true, identical(implicitInstantiation, implicitInstantiation));
+ expect(true, identical(implicitInstantiation, explicitInstantiation));
+ expect(true, identical(implicitInstantiation, implicitConstInstantiation));
+ expect(true, identical(implicitInstantiation, explicitConstInstantiation));
+ expect(true, identical(implicitInstantiation, id<int>));
+ expect(false, identical(implicitInstantiation, id<String>));
+ expect(false, identical(implicitInstantiation, create<int>()));
+
+ expect(true, identical(explicitInstantiation, implicitInstantiation));
+ expect(true, identical(explicitInstantiation, explicitInstantiation));
+ expect(true, identical(explicitInstantiation, implicitConstInstantiation));
+ expect(true, identical(explicitInstantiation, explicitConstInstantiation));
+ expect(true, identical(explicitInstantiation, id<int>));
+ expect(false, identical(explicitInstantiation, id<String>));
+ expect(false, identical(explicitInstantiation, create<int>()));
+
+ expect(true, identical(implicitConstInstantiation, implicitInstantiation));
+ expect(true, identical(implicitConstInstantiation, explicitInstantiation));
+ expect(true, identical(implicitConstInstantiation,
+ implicitConstInstantiation));
+ expect(true, identical(implicitConstInstantiation,
+ explicitConstInstantiation));
+ expect(true, identical(implicitConstInstantiation, id<int>));
+ expect(false, identical(implicitConstInstantiation, id<String>));
+ expect(false, identical(implicitConstInstantiation, create<int>()));
+
+ expect(true, identical(explicitConstInstantiation, implicitInstantiation));
+ expect(true, identical(explicitConstInstantiation, explicitInstantiation));
+ expect(true, identical(explicitConstInstantiation,
+ implicitConstInstantiation));
+ expect(true, identical(explicitConstInstantiation,
+ explicitConstInstantiation));
+ expect(true, identical(explicitConstInstantiation, id<int>));
+ expect(false, identical(explicitConstInstantiation, id<String>));
+ expect(false, identical(explicitConstInstantiation, create<int>()));
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.expect
new file mode 100644
index 0000000..8df289d3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.expect
@@ -0,0 +1,52 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static field (core::int) → core::int implicitInstantiation = #C2;
+static field (core::int) → core::int explicitInstantiation = #C2;
+static const field (core::int) → core::int implicitConstInstantiation = #C2;
+static const field (core::int) → core::int explicitConstInstantiation = #C2;
+static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
+ return t;
+static method create<T extends core::Object? = dynamic>() → (self::create::T%) → self::create::T%
+ return #C1<self::create::T%>;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::implicitInstantiation, self::implicitInstantiation));
+ self::expect(true, core::identical(self::implicitInstantiation, self::explicitInstantiation));
+ self::expect(true, core::identical(self::implicitInstantiation, #C2));
+ self::expect(true, core::identical(self::implicitInstantiation, #C2));
+ self::expect(true, core::identical(self::implicitInstantiation, #C2));
+ self::expect(false, core::identical(self::implicitInstantiation, #C3));
+ self::expect(false, core::identical(self::implicitInstantiation, self::create<core::int>()));
+ self::expect(true, core::identical(self::explicitInstantiation, self::implicitInstantiation));
+ self::expect(true, core::identical(self::explicitInstantiation, self::explicitInstantiation));
+ self::expect(true, core::identical(self::explicitInstantiation, #C2));
+ self::expect(true, core::identical(self::explicitInstantiation, #C2));
+ self::expect(true, core::identical(self::explicitInstantiation, #C2));
+ self::expect(false, core::identical(self::explicitInstantiation, #C3));
+ self::expect(false, core::identical(self::explicitInstantiation, self::create<core::int>()));
+ self::expect(true, core::identical(#C2, self::implicitInstantiation));
+ self::expect(true, core::identical(#C2, self::explicitInstantiation));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(false, core::identical(#C2, #C3));
+ self::expect(false, core::identical(#C2, self::create<core::int>()));
+ self::expect(true, core::identical(#C2, self::implicitInstantiation));
+ self::expect(true, core::identical(#C2, self::explicitInstantiation));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(false, core::identical(#C2, #C3));
+ self::expect(false, core::identical(#C2, self::create<core::int>()));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = tearoff self::id
+ #C2 = partial-instantiation self::id <core::int>
+ #C3 = partial-instantiation self::id <core::String>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.transformed.expect
new file mode 100644
index 0000000..3afa4cf
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.transformed.expect
@@ -0,0 +1,63 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static field (core::int) → core::int implicitInstantiation = #C2;
+static field (core::int) → core::int explicitInstantiation = #C2;
+static const field (core::int) → core::int implicitConstInstantiation = #C2;
+static const field (core::int) → core::int explicitConstInstantiation = #C2;
+static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
+ return t;
+static method create<T extends core::Object? = dynamic>() → (self::create::T%) → self::create::T%
+ return #C1<self::create::T%>;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::implicitInstantiation, self::implicitInstantiation));
+ self::expect(true, core::identical(self::implicitInstantiation, self::explicitInstantiation));
+ self::expect(true, core::identical(self::implicitInstantiation, #C2));
+ self::expect(true, core::identical(self::implicitInstantiation, #C2));
+ self::expect(true, core::identical(self::implicitInstantiation, #C2));
+ self::expect(false, core::identical(self::implicitInstantiation, #C3));
+ self::expect(false, core::identical(self::implicitInstantiation, self::create<core::int>()));
+ self::expect(true, core::identical(self::explicitInstantiation, self::implicitInstantiation));
+ self::expect(true, core::identical(self::explicitInstantiation, self::explicitInstantiation));
+ self::expect(true, core::identical(self::explicitInstantiation, #C2));
+ self::expect(true, core::identical(self::explicitInstantiation, #C2));
+ self::expect(true, core::identical(self::explicitInstantiation, #C2));
+ self::expect(false, core::identical(self::explicitInstantiation, #C3));
+ self::expect(false, core::identical(self::explicitInstantiation, self::create<core::int>()));
+ self::expect(true, core::identical(#C2, self::implicitInstantiation));
+ self::expect(true, core::identical(#C2, self::explicitInstantiation));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(false, core::identical(#C2, #C3));
+ self::expect(false, core::identical(#C2, self::create<core::int>()));
+ self::expect(true, core::identical(#C2, self::implicitInstantiation));
+ self::expect(true, core::identical(#C2, self::explicitInstantiation));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(false, core::identical(#C2, #C3));
+ self::expect(false, core::identical(#C2, self::create<core::int>()));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = tearoff self::id
+ #C2 = partial-instantiation self::id <core::int>
+ #C3 = partial-instantiation self::id <core::String>
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:33:16 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:35:16 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:37:16 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:38:17 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:43:16 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:45:16 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:47:16 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:48:17 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 92, effectively constant: 8
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.textual_outline.expect
new file mode 100644
index 0000000..558b2b1
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+T id<T>(T t) => t;
+int Function(int) implicitInstantiation = id;
+var explicitInstantiation = id<int>;
+const int Function(int) implicitConstInstantiation = id;
+const explicitConstInstantiation = id<int>;
+T Function(T) create<T>() => id<T>;
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.expect
new file mode 100644
index 0000000..c33a355
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.expect
@@ -0,0 +1,52 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static field (core::int) → core::int implicitInstantiation = #C2;
+static field (core::int) → core::int explicitInstantiation = #C2;
+static const field (core::int) → core::int implicitConstInstantiation = #C2;
+static const field (core::int) → core::int explicitConstInstantiation = #C2;
+static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
+ return t;
+static method create<T extends core::Object? = dynamic>() → (self::create::T%) → self::create::T%
+ return #C1<self::create::T%>;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::implicitInstantiation, self::implicitInstantiation));
+ self::expect(true, core::identical(self::implicitInstantiation, self::explicitInstantiation));
+ self::expect(true, core::identical(self::implicitInstantiation, #C2));
+ self::expect(true, core::identical(self::implicitInstantiation, #C2));
+ self::expect(true, core::identical(self::implicitInstantiation, #C2));
+ self::expect(false, core::identical(self::implicitInstantiation, #C3));
+ self::expect(false, core::identical(self::implicitInstantiation, self::create<core::int>()));
+ self::expect(true, core::identical(self::explicitInstantiation, self::implicitInstantiation));
+ self::expect(true, core::identical(self::explicitInstantiation, self::explicitInstantiation));
+ self::expect(true, core::identical(self::explicitInstantiation, #C2));
+ self::expect(true, core::identical(self::explicitInstantiation, #C2));
+ self::expect(true, core::identical(self::explicitInstantiation, #C2));
+ self::expect(false, core::identical(self::explicitInstantiation, #C3));
+ self::expect(false, core::identical(self::explicitInstantiation, self::create<core::int>()));
+ self::expect(true, core::identical(#C2, self::implicitInstantiation));
+ self::expect(true, core::identical(#C2, self::explicitInstantiation));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(false, core::identical(#C2, #C3));
+ self::expect(false, core::identical(#C2, self::create<core::int>()));
+ self::expect(true, core::identical(#C2, self::implicitInstantiation));
+ self::expect(true, core::identical(#C2, self::explicitInstantiation));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(false, core::identical(#C2, #C3));
+ self::expect(false, core::identical(#C2, self::create<core::int>()));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = tearoff self::id
+ #C2 = partial-instantiation self::id <core::int*>
+ #C3 = partial-instantiation self::id <core::String*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.outline.expect
new file mode 100644
index 0000000..d3f2e88
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.outline.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static field (core::int) → core::int implicitInstantiation;
+static field (core::int) → core::int explicitInstantiation;
+static const field (core::int) → core::int implicitConstInstantiation = self::id<core::int>;
+static const field (core::int) → core::int explicitConstInstantiation = self::id<core::int>;
+static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
+ ;
+static method create<T extends core::Object? = dynamic>() → (self::create::T%) → self::create::T%
+ ;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: Instantiation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:9:54 -> PartialInstantiationConstant(id<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:10:38 -> PartialInstantiationConstant(id<int*>)
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
new file mode 100644
index 0000000..9cdfa3c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
@@ -0,0 +1,63 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static field (core::int) → core::int implicitInstantiation = #C2;
+static field (core::int) → core::int explicitInstantiation = #C2;
+static const field (core::int) → core::int implicitConstInstantiation = #C2;
+static const field (core::int) → core::int explicitConstInstantiation = #C2;
+static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
+ return t;
+static method create<T extends core::Object? = dynamic>() → (self::create::T%) → self::create::T%
+ return #C1<self::create::T%>;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::implicitInstantiation, self::implicitInstantiation));
+ self::expect(true, core::identical(self::implicitInstantiation, self::explicitInstantiation));
+ self::expect(true, core::identical(self::implicitInstantiation, #C2));
+ self::expect(true, core::identical(self::implicitInstantiation, #C2));
+ self::expect(true, core::identical(self::implicitInstantiation, #C2));
+ self::expect(false, core::identical(self::implicitInstantiation, #C3));
+ self::expect(false, core::identical(self::implicitInstantiation, self::create<core::int>()));
+ self::expect(true, core::identical(self::explicitInstantiation, self::implicitInstantiation));
+ self::expect(true, core::identical(self::explicitInstantiation, self::explicitInstantiation));
+ self::expect(true, core::identical(self::explicitInstantiation, #C2));
+ self::expect(true, core::identical(self::explicitInstantiation, #C2));
+ self::expect(true, core::identical(self::explicitInstantiation, #C2));
+ self::expect(false, core::identical(self::explicitInstantiation, #C3));
+ self::expect(false, core::identical(self::explicitInstantiation, self::create<core::int>()));
+ self::expect(true, core::identical(#C2, self::implicitInstantiation));
+ self::expect(true, core::identical(#C2, self::explicitInstantiation));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(false, core::identical(#C2, #C3));
+ self::expect(false, core::identical(#C2, self::create<core::int>()));
+ self::expect(true, core::identical(#C2, self::implicitInstantiation));
+ self::expect(true, core::identical(#C2, self::explicitInstantiation));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(false, core::identical(#C2, #C3));
+ self::expect(false, core::identical(#C2, self::create<core::int>()));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = tearoff self::id
+ #C2 = partial-instantiation self::id <core::int*>
+ #C3 = partial-instantiation self::id <core::String*>
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:33:16 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:35:16 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:37:16 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:38:17 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:43:16 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:45:16 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:47:16 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:48:17 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 92, effectively constant: 8
diff --git a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.weak.expect b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.weak.expect
index 8a535a9..bd3e8df 100644
--- a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.weak.expect
+++ b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.weak.expect
@@ -18,7 +18,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Foo extends core::Object /*isEnum*/ {
+class Foo extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Foo*>* values = #C10;
diff --git a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.weak.outline.expect b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.weak.outline.expect
index 9467f32..3b90344 100644
--- a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.weak.outline.expect
@@ -18,7 +18,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Foo extends core::Object /*isEnum*/ {
+class Foo extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Foo*>* values = const <self::Foo*>[self::Foo::bar, self::Foo::baz, self::Foo::cafebabe];
diff --git a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.weak.transformed.expect b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.weak.transformed.expect
index 8a535a9..bd3e8df 100644
--- a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.weak.transformed.expect
@@ -18,7 +18,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Foo extends core::Object /*isEnum*/ {
+class Foo extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Foo*>* values = #C10;
diff --git a/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart b/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart
new file mode 100644
index 0000000..d0c6c8e
--- /dev/null
+++ b/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart
@@ -0,0 +1,13 @@
+// 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.
+
+test() {
+ X bounded<X extends num>(X x) => x;
+ String a = bounded('');
+ String b = bounded<String>('');
+ String Function(String) c = bounded;
+ String d = c('');
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart.textual_outline.expect b/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart.textual_outline.expect
new file mode 100644
index 0000000..ec6b9e0
--- /dev/null
+++ b/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f67dbb0
--- /dev/null
+++ b/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart.textual_outline_modelled.expect
@@ -0,0 +1,2 @@
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart.weak.expect b/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart.weak.expect
new file mode 100644
index 0000000..cf6e3f3
--- /dev/null
+++ b/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart.weak.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/bounded_implicit_instantiation.dart:7:22: Error: The argument type 'String' can't be assigned to the parameter type 'Never'.
+// String a = bounded('');
+// ^
+//
+// pkg/front_end/testcases/general/bounded_implicit_instantiation.dart:8:21: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'bounded'.
+// Try changing type arguments so that they conform to the bounds.
+// String b = bounded<String>('');
+// ^
+//
+// pkg/front_end/testcases/general/bounded_implicit_instantiation.dart:9:31: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'X Function<X extends num>(X)'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// String Function(String) c = bounded;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method test() → dynamic {
+ function bounded<X extends core::num>(X x) → X
+ return x;
+ core::String a = let final Never #t1 = bounded<Never>(let final Never #t2 = invalid-expression "pkg/front_end/testcases/general/bounded_implicit_instantiation.dart:7:22: Error: The argument type 'String' can't be assigned to the parameter type 'Never'.
+ String a = bounded('');
+ ^" in "" as{TypeError,ForNonNullableByDefault} Never){(Never) → Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+ core::String b = bounded<core::String>(""){(core::String) → core::String};
+ (core::String) → core::String c = bounded<core::String>;
+ core::String d = c(""){(core::String) → core::String};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart.weak.outline.expect b/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart.weak.outline.expect
new file mode 100644
index 0000000..64923de
--- /dev/null
+++ b/pkg/front_end/testcases/general/bounded_implicit_instantiation.dart.weak.outline.expect
@@ -0,0 +1,7 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method test() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.expect b/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.expect
index 280c716..ce50dfd 100644
--- a/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.expect
+++ b/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.expect
@@ -481,7 +481,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Enum#4 extends core::Object /*isEnum*/ { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#4 extends core::Object implements core::Enum /*isEnum*/ { // from org-dartlang-testcase:///duplicated_declarations_part.dart
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Enum#4*>* values = #C4;
@@ -501,7 +501,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Enum#3 extends core::Object /*isEnum*/ { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#3 extends core::Object implements core::Enum /*isEnum*/ { // from org-dartlang-testcase:///duplicated_declarations_part.dart
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Enum#3*>* values = #C12;
@@ -523,7 +523,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Enum#2 extends core::Object /*isEnum*/ { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#2 extends core::Object implements core::Enum /*isEnum*/ { // from org-dartlang-testcase:///duplicated_declarations_part.dart
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Enum#2*>* values = #C17;
@@ -545,7 +545,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Enum#1 extends core::Object /*isEnum*/ {
+class Enum#1 extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Enum#1*>* values = #C21;
@@ -567,7 +567,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Enum*>* values = #C25;
@@ -589,7 +589,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class AnotherEnum extends core::Object /*isEnum*/ {
+class AnotherEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::AnotherEnum*>* values = #C32;
diff --git a/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.outline.expect b/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.outline.expect
index 325b6441..1113a3a 100644
--- a/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.outline.expect
@@ -419,7 +419,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Enum#4 extends core::Object /*isEnum*/ { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#4 extends core::Object implements core::Enum /*isEnum*/ { // from org-dartlang-testcase:///duplicated_declarations_part.dart
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Enum#4*>* values = const <self::Enum#4*>[self::Enum#4::a];
@@ -439,7 +439,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Enum#3 extends core::Object /*isEnum*/ { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#3 extends core::Object implements core::Enum /*isEnum*/ { // from org-dartlang-testcase:///duplicated_declarations_part.dart
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Enum#3*>* values = const <self::Enum#3*>[self::Enum#3::a, self::Enum#3::b, self::Enum#3::c];
@@ -461,7 +461,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Enum#2 extends core::Object /*isEnum*/ { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#2 extends core::Object implements core::Enum /*isEnum*/ { // from org-dartlang-testcase:///duplicated_declarations_part.dart
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Enum#2*>* values = const <self::Enum#2*>[self::Enum#2::Enum, self::Enum#2::a, self::Enum#2::b];
@@ -483,7 +483,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Enum#1 extends core::Object /*isEnum*/ {
+class Enum#1 extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Enum#1*>* values = const <self::Enum#1*>[self::Enum#1::a, self::Enum#1::b, self::Enum#1::c];
@@ -505,7 +505,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Enum*>* values = const <self::Enum*>[self::Enum::Enum, self::Enum::a, self::Enum::b];
@@ -527,7 +527,7 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-class AnotherEnum extends core::Object /*isEnum*/ {
+class AnotherEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::AnotherEnum*>* values = const <self::AnotherEnum*>[self::AnotherEnum::a, self::AnotherEnum::b, self::AnotherEnum::c];
diff --git a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart
new file mode 100644
index 0000000..955feff
--- /dev/null
+++ b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart
@@ -0,0 +1,34 @@
+// 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.
+
+// @dart=2.13
+
+// This test is similar to
+//
+// constructor_tearoffs/identical_instantiated_function_tearoffs.dart
+//
+// but verifies that before the constructor-tearoffs experiment was enabled,
+// instantiations in non-constant context were not canonicalized.
+
+T id<T>(T t) => t;
+
+int Function(int) implicitInstantiation = id;
+const int Function(int) implicitConstInstantiation = id;
+
+T Function(T) create<T>() => id;
+
+main() {
+ expect(true, identical(implicitInstantiation, implicitInstantiation));
+ expect(false, identical(implicitInstantiation, implicitConstInstantiation));
+ expect(false, identical(implicitInstantiation, create<int>()));
+
+ expect(false, identical(implicitConstInstantiation, implicitInstantiation));
+ expect(
+ true, identical(implicitConstInstantiation, implicitConstInstantiation));
+ expect(false, identical(implicitConstInstantiation, create<int>()));
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.textual_outline.expect b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.textual_outline.expect
new file mode 100644
index 0000000..90e26eb
--- /dev/null
+++ b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.textual_outline.expect
@@ -0,0 +1,7 @@
+// @dart = 2.13
+T id<T>(T t) => t;
+int Function(int) implicitInstantiation = id;
+const int Function(int) implicitConstInstantiation = id;
+T Function(T) create<T>() => id;
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a0e9251
--- /dev/null
+++ b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+// @dart = 2.13
+T Function(T) create<T>() => id;
+T id<T>(T t) => t;
+const int Function(int) implicitConstInstantiation = id;
+expect(expected, actual) {}
+int Function(int) implicitInstantiation = id;
+main() {}
diff --git a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.expect b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.expect
new file mode 100644
index 0000000..daf6f36
--- /dev/null
+++ b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static field (core::int) → core::int implicitInstantiation = #C1<core::int>;
+static const field (core::int) → core::int implicitConstInstantiation = #C2;
+static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
+ return t;
+static method create<T extends core::Object? = dynamic>() → (self::create::T%) → self::create::T%
+ return #C1<self::create::T%>;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::implicitInstantiation, self::implicitInstantiation));
+ self::expect(false, core::identical(self::implicitInstantiation, #C2));
+ self::expect(false, core::identical(self::implicitInstantiation, self::create<core::int>()));
+ self::expect(false, core::identical(#C2, self::implicitInstantiation));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(false, core::identical(#C2, self::create<core::int>()));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = tearoff self::id
+ #C2 = partial-instantiation self::id <core::int*>
+}
diff --git a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.outline.expect b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.outline.expect
new file mode 100644
index 0000000..02a352f
--- /dev/null
+++ b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.outline.expect
@@ -0,0 +1,19 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static field (core::int) → core::int implicitInstantiation;
+static const field (core::int) → core::int implicitConstInstantiation = self::id<core::int>;
+static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
+ ;
+static method create<T extends core::Object? = dynamic>() → (self::create::T%) → self::create::T%
+ ;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: Instantiation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:17:54 -> PartialInstantiationConstant(id<int*>)
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.transformed.expect b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
new file mode 100644
index 0000000..ad67316
--- /dev/null
+++ b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static field (core::int) → core::int implicitInstantiation = #C1<core::int>;
+static const field (core::int) → core::int implicitConstInstantiation = #C2;
+static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
+ return t;
+static method create<T extends core::Object? = dynamic>() → (self::create::T%) → self::create::T%
+ return #C1<self::create::T%>;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::implicitInstantiation, self::implicitInstantiation));
+ self::expect(false, core::identical(self::implicitInstantiation, #C2));
+ self::expect(false, core::identical(self::implicitInstantiation, self::create<core::int>()));
+ self::expect(false, core::identical(#C2, self::implicitInstantiation));
+ self::expect(true, core::identical(#C2, #C2));
+ self::expect(false, core::identical(#C2, self::create<core::int>()));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = tearoff self::id
+ #C2 = partial-instantiation self::id <core::int*>
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:28:13 -> BoolConstant(true)
+Evaluated: Instantiation @ org-dartlang-testcase:///identical_instantiated_function_tearoffs.dart:16:43 -> PartialInstantiationConstant(id<int*>)
+Extra constant evaluation: evaluated: 30, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/metadata_enum.dart.weak.expect b/pkg/front_end/testcases/general/metadata_enum.dart.weak.expect
index 226967f..16f3460 100644
--- a/pkg/front_end/testcases/general/metadata_enum.dart.weak.expect
+++ b/pkg/front_end/testcases/general/metadata_enum.dart.weak.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
@#C1
-class E extends core::Object /*isEnum*/ {
+class E extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::E*>* values = #C11;
diff --git a/pkg/front_end/testcases/general/metadata_enum.dart.weak.outline.expect b/pkg/front_end/testcases/general/metadata_enum.dart.weak.outline.expect
index eccf60e..44f4d21 100644
--- a/pkg/front_end/testcases/general/metadata_enum.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/metadata_enum.dart.weak.outline.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
@self::a
-class E extends core::Object /*isEnum*/ {
+class E extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::E*>* values = const <self::E*>[self::E::E1, self::E::E2, self::E::E3];
diff --git a/pkg/front_end/testcases/general/metadata_enum.dart.weak.transformed.expect b/pkg/front_end/testcases/general/metadata_enum.dart.weak.transformed.expect
index 226967f..16f3460 100644
--- a/pkg/front_end/testcases/general/metadata_enum.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/metadata_enum.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
@#C1
-class E extends core::Object /*isEnum*/ {
+class E extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::E*>* values = #C11;
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_2.yaml.world.1.expect
index 5c66b3c..f919f21 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_2.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_2.yaml.world.1.expect
@@ -30,7 +30,7 @@
abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
}
- class CompilationStrategy extends dart.core::Object /*isEnum*/ {
+ class CompilationStrategy extends dart.core::Object implements dart.core::Enum /*isEnum*/ {
final field dart.core::int* index;
final field dart.core::String* _name;
static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_2.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_2.yaml.world.2.expect
index 654e34c..0b4afaf 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_2.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_2.yaml.world.2.expect
@@ -30,7 +30,7 @@
abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
}
- class CompilationStrategy extends dart.core::Object /*isEnum*/ {
+ class CompilationStrategy extends dart.core::Object implements dart.core::Enum /*isEnum*/ {
final field dart.core::int* index;
final field dart.core::String* _name;
static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_6.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_6.yaml.world.1.expect
index fa8fec9..46a055a 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_6.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_6.yaml.world.1.expect
@@ -37,7 +37,7 @@
abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
}
- class CompilationStrategy extends dart.core::Object /*isEnum*/ {
+ class CompilationStrategy extends dart.core::Object implements dart.core::Enum /*isEnum*/ {
final field dart.core::int* index;
final field dart.core::String* _name;
static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_6.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_6.yaml.world.2.expect
index 2311e2e..f17b4d8 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_6.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_6.yaml.world.2.expect
@@ -37,7 +37,7 @@
abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
}
- class CompilationStrategy extends dart.core::Object /*isEnum*/ {
+ class CompilationStrategy extends dart.core::Object implements dart.core::Enum /*isEnum*/ {
final field dart.core::int* index;
final field dart.core::String* _name;
static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_6.yaml.world.3.expect b/pkg/front_end/testcases/incremental/no_outline_change_6.yaml.world.3.expect
index 395e141..de577dd 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_6.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_6.yaml.world.3.expect
@@ -30,7 +30,7 @@
abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
}
- class CompilationStrategy extends dart.core::Object /*isEnum*/ {
+ class CompilationStrategy extends dart.core::Object implements dart.core::Enum /*isEnum*/ {
final field dart.core::int* index;
final field dart.core::String* _name;
static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_7.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_7.yaml.world.1.expect
index 28c10a2..73cad31 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_7.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_7.yaml.world.1.expect
@@ -42,7 +42,7 @@
}
}
@#C1
- class CompilationStrategy extends dart.core::Object /*isEnum*/ {
+ class CompilationStrategy extends dart.core::Object implements dart.core::Enum /*isEnum*/ {
final field dart.core::int* index;
final field dart.core::String* _name;
static const field dart.core::List<main::CompilationStrategy*>* values = #C15;
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_7.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_7.yaml.world.2.expect
index 28c10a2..73cad31 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_7.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_7.yaml.world.2.expect
@@ -42,7 +42,7 @@
}
}
@#C1
- class CompilationStrategy extends dart.core::Object /*isEnum*/ {
+ class CompilationStrategy extends dart.core::Object implements dart.core::Enum /*isEnum*/ {
final field dart.core::int* index;
final field dart.core::String* _name;
static const field dart.core::List<main::CompilationStrategy*>* values = #C15;
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.expect
index 22921fb..2c7b116 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.expect
@@ -2,6 +2,12 @@
//
// Problems in library:
//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:26:70: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// takeOOI(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/ math.max);
+// ^
+//
// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:28:73: Error: The argument type 'num Function(num, num)' can't be assigned to the parameter type 'int Function(double, int)'.
// /*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ math.max);
// ^
@@ -10,6 +16,24 @@
// /*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ math.max);
// ^
//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:31:70: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// takeOON(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/ math.max);
+// ^
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:32:70: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// takeOOO(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/ math.max);
+// ^
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:45:65: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// takeOOI(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/ min);
+// ^
+//
// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:46:72: Error: The argument type 'num Function(num, num)' can't be assigned to the parameter type 'int Function(double, int)'.
// takeIDI(/*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ min);
// ^
@@ -18,6 +42,36 @@
// takeDID(/*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ min);
// ^
//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:48:65: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// takeOON(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/ min);
+// ^
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:49:65: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// takeOOO(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/ min);
+// ^
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:73:25: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// . /*@target=C.m*/ m);
+// ^
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:75:25: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// . /*@target=C.m*/ m);
+// ^
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:82:25: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// . /*@target=C.m*/ m);
+// ^
+//
// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:86:29: Error: The argument type 'num Function(num, num)' can't be assigned to the parameter type 'int Function(double, int)'.
// . /*@target=C.m*/ m);
// ^
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.transformed.expect
index 5857dad..d465ca9 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.transformed.expect
@@ -2,6 +2,12 @@
//
// Problems in library:
//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:26:70: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// takeOOI(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/ math.max);
+// ^
+//
// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:28:73: Error: The argument type 'num Function(num, num)' can't be assigned to the parameter type 'int Function(double, int)'.
// /*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ math.max);
// ^
@@ -10,6 +16,24 @@
// /*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ math.max);
// ^
//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:31:70: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// takeOON(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/ math.max);
+// ^
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:32:70: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// takeOOO(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/ math.max);
+// ^
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:45:65: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// takeOOI(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/ min);
+// ^
+//
// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:46:72: Error: The argument type 'num Function(num, num)' can't be assigned to the parameter type 'int Function(double, int)'.
// takeIDI(/*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ min);
// ^
@@ -18,6 +42,36 @@
// takeDID(/*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ min);
// ^
//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:48:65: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// takeOON(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/ min);
+// ^
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:49:65: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// takeOOO(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/ min);
+// ^
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:73:25: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// . /*@target=C.m*/ m);
+// ^
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:75:25: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// . /*@target=C.m*/ m);
+// ^
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:82:25: Error: Inferred type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'T Function<T extends num>(T, T)'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// . /*@target=C.m*/ m);
+// ^
+//
// pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart:86:29: Error: The argument type 'num Function(num, num)' can't be assigned to the parameter type 'int Function(double, int)'.
// . /*@target=C.m*/ m);
// ^
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.weak.expect
index b8edb82..84bd9ed 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.weak.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class E extends core::Object /*isEnum*/ {
+class E extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::E*>* values = #C4;
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.weak.outline.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.weak.outline.expect
index e92663e..0f72ee9 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.weak.outline.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class E extends core::Object /*isEnum*/ {
+class E extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::E*>* values = const <self::E*>[self::E::v1];
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.weak.transformed.expect
index b8edb82..84bd9ed 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.weak.transformed.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class E extends core::Object /*isEnum*/ {
+class E extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::E*>* values = #C4;
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.weak.expect
index 5bb945f..827859e 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.weak.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class E extends core::Object /*isEnum*/ {
+class E extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::E*>* values = #C4;
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.weak.outline.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.weak.outline.expect
index 4584120..f462cb1 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.weak.outline.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class E extends core::Object /*isEnum*/ {
+class E extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::E*>* values = const <self::E*>[self::E::v1];
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.weak.transformed.expect
index 5bb945f..827859e 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.weak.transformed.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class E extends core::Object /*isEnum*/ {
+class E extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::E*>* values = #C4;
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect b/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect
index 95f3397..2c50f0d 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect
@@ -58,7 +58,7 @@
import "dart:async";
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::Enum> values = #C7;
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
index 81d9731..0aaa16b 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
@@ -58,7 +58,7 @@
import "dart:async";
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::Enum> values = #C7;
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect b/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect
index 65b134d..d2df46e 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect
@@ -59,7 +59,7 @@
import "dart:async";
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::Enum> values = #C7;
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.weak.outline.expect b/pkg/front_end/testcases/nnbd/return_null.dart.weak.outline.expect
index 04d2e5b..29d9ba1 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.weak.outline.expect
@@ -5,7 +5,7 @@
import "dart:async";
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::Enum> values = const <self::Enum>[self::Enum::a, self::Enum::b];
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
index 51a7d44..b0fa47a 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
@@ -59,7 +59,7 @@
import "dart:async";
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::Enum> values = #C7;
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.expect
index 7ad41a1..3435d06 100644
--- a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.expect
@@ -9,7 +9,7 @@
import self as self;
import "dart:core" as core;
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::Enum> values = #C7;
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.transformed.expect
index 7ad41a1..3435d06 100644
--- a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.transformed.expect
@@ -9,7 +9,7 @@
import self as self;
import "dart:core" as core;
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::Enum> values = #C7;
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.expect
index 61fa678..6d0b4f2 100644
--- a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.expect
@@ -10,7 +10,7 @@
import "dart:core" as core;
import "dart:_internal" as _in;
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::Enum> values = #C7;
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.outline.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.outline.expect
index d3643d7..ed400bb 100644
--- a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.outline.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::Enum> values = const <self::Enum>[self::Enum::e1, self::Enum::e2];
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.transformed.expect
index 61fa678..6d0b4f2 100644
--- a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.transformed.expect
@@ -10,7 +10,7 @@
import "dart:core" as core;
import "dart:_internal" as _in;
-class Enum extends core::Object /*isEnum*/ {
+class Enum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::Enum> values = #C7;
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
index b130d3b..ead85b1 100644
--- a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
@@ -428,7 +428,7 @@
: uns::OptInClass6b::field = field, super core::Object::•()
;
}
-class E extends core::Object /*isEnum*/ {
+class E extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<uns::E> values = #C8;
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.outline.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.outline.expect
index d853a42..2a7d4ca 100644
--- a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.outline.expect
@@ -201,7 +201,7 @@
constructor •(core::int field) → self2::OptInClass6b
;
}
-class E extends core::Object /*isEnum*/ {
+class E extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self2::E> values = const <self2::E>[self2::E::e1, self2::E::e2];
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.transformed.expect
index f635ea8..ede6557 100644
--- a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.transformed.expect
@@ -428,7 +428,7 @@
: uns::OptInClass6b::field = field, super core::Object::•()
;
}
-class E extends core::Object /*isEnum*/ {
+class E extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<uns::E> values = #C8;
diff --git a/pkg/front_end/testcases/rasta/enum.dart.weak.expect b/pkg/front_end/testcases/rasta/enum.dart.weak.expect
index 71f1044..99090fe 100644
--- a/pkg/front_end/testcases/rasta/enum.dart.weak.expect
+++ b/pkg/front_end/testcases/rasta/enum.dart.weak.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class Foo extends core::Object /*isEnum*/ {
+class Foo extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Foo*>* values = #C7;
diff --git a/pkg/front_end/testcases/rasta/enum.dart.weak.outline.expect b/pkg/front_end/testcases/rasta/enum.dart.weak.outline.expect
index 5df7acc..3d39d28 100644
--- a/pkg/front_end/testcases/rasta/enum.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/rasta/enum.dart.weak.outline.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class Foo extends core::Object /*isEnum*/ {
+class Foo extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Foo*>* values = const <self::Foo*>[self::Foo::ec1, self::Foo::ec2];
diff --git a/pkg/front_end/testcases/rasta/enum.dart.weak.transformed.expect b/pkg/front_end/testcases/rasta/enum.dart.weak.transformed.expect
index 71f1044..99090fe 100644
--- a/pkg/front_end/testcases/rasta/enum.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/rasta/enum.dart.weak.transformed.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class Foo extends core::Object /*isEnum*/ {
+class Foo extends core::Object implements core::Enum /*isEnum*/ {
final field core::int* index;
final field core::String* _name;
static const field core::List<self::Foo*>* values = #C7;
diff --git a/pkg/front_end/testcases/static_field_lowering/enum.dart.strong.expect b/pkg/front_end/testcases/static_field_lowering/enum.dart.strong.expect
index 6115731..6d82f2d 100644
--- a/pkg/front_end/testcases/static_field_lowering/enum.dart.strong.expect
+++ b/pkg/front_end/testcases/static_field_lowering/enum.dart.strong.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class A extends core::Object /*isEnum*/ {
+class A extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::A> values = #C7;
diff --git a/pkg/front_end/testcases/static_field_lowering/enum.dart.strong.transformed.expect b/pkg/front_end/testcases/static_field_lowering/enum.dart.strong.transformed.expect
index 6115731..6d82f2d 100644
--- a/pkg/front_end/testcases/static_field_lowering/enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/static_field_lowering/enum.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class A extends core::Object /*isEnum*/ {
+class A extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::A> values = #C7;
diff --git a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.expect b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.expect
index bece663..7609699 100644
--- a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.expect
+++ b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class A extends core::Object /*isEnum*/ {
+class A extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::A> values = #C7;
diff --git a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.outline.expect b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.outline.expect
index a6cad98..23e0446 100644
--- a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.outline.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class A extends core::Object /*isEnum*/ {
+class A extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::A> values = const <self::A>[self::A::a, self::A::b];
diff --git a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.transformed.expect b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.transformed.expect
index bece663..7609699 100644
--- a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.transformed.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-class A extends core::Object /*isEnum*/ {
+class A extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::A> values = #C7;
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 24201ec..c7df9c9 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -22,6 +22,7 @@
general/accessors: RuntimeError
general/ambiguous_exports: RuntimeError
general/await_in_non_async: RuntimeError
+general/bounded_implicit_instantiation: TypeCheckError
general/bug30695: TypeCheckError
general/bug31124: RuntimeError
general/call: TypeCheckError
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index fd8e874..29acb62 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -23,8 +23,10 @@
const_functions/const_functions_const_ctor: FormatterCrash
const_functions/const_functions_const_ctor_error: FormatterCrash
const_functions/const_functions_const_factory: FormatterCrash
+constructor_tearoffs/explicit_instantiation_errors: FormatterCrash
constructor_tearoffs/generic_tearoff_with_context: FormatterCrash
constructor_tearoffs/generic_tearoff_without_context: FormatterCrash
+constructor_tearoffs/identical_instantiated_function_tearoffs: FormatterCrash
constructor_tearoffs/instantiation: FormatterCrash
constructor_tearoffs/nongeneric_tearoff_with_context: FormatterCrash
constructor_tearoffs/nongeneric_tearoff_without_context: FormatterCrash
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 3c2c427..82c2ba6 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -27,6 +27,7 @@
general/accessors: RuntimeError
general/ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
general/await_in_non_async: RuntimeError # Expected.
+general/bounded_implicit_instantiation: TypeCheckError
general/bug30695: TypeCheckError
general/bug31124: RuntimeError # Test has no main method (and we shouldn't add one).
general/call: TypeCheckError
diff --git a/pkg/vm/testcases/transformations/to_string_transformer/not_transformed.expect b/pkg/vm/testcases/transformations/to_string_transformer/not_transformed.expect
index 38a3e92..37d5226 100644
--- a/pkg/vm/testcases/transformations/to_string_transformer/not_transformed.expect
+++ b/pkg/vm/testcases/transformations/to_string_transformer/not_transformed.expect
@@ -19,7 +19,7 @@
method toString() → core::String
return "I am a Foo";
}
-class FooEnum extends core::Object /*isEnum*/ {
+class FooEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::FooEnum> values = #C11;
diff --git a/pkg/vm/testcases/transformations/to_string_transformer/transformed.expect b/pkg/vm/testcases/transformations/to_string_transformer/transformed.expect
index a858cd6..d5bbdbf 100644
--- a/pkg/vm/testcases/transformations/to_string_transformer/transformed.expect
+++ b/pkg/vm/testcases/transformations/to_string_transformer/transformed.expect
@@ -19,7 +19,7 @@
method toString() → core::String
return super.toString();
}
-class FooEnum extends core::Object /*isEnum*/ {
+class FooEnum extends core::Object implements core::Enum /*isEnum*/ {
final field core::int index;
final field core::String _name;
static const field core::List<self::FooEnum> values = #C11;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
index 4487ac5..1a8dce9 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
@@ -11,7 +11,7 @@
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] method getBar() → core::String*
return "bar";
}
-class B extends core::Object /*isEnum*/ {
+class B extends core::Object implements core::Enum /*isEnum*/ {
[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] final field core::int* index;
[@vm.inferred-type.metadata=dart.core::_OneByteString (value: "B.b2")] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] final field core::String* _name;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method toString() → core::String*
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_used_as_type.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/enum_used_as_type.dart.expect
index 92f5135..ac4bbc2 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_used_as_type.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_used_as_type.dart.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
import "dart:_internal" as _in;
-abstract class Enum extends core::Object {
+abstract class Enum extends core::Object implements core::Enum {
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] abstract get index() → core::int*;
}
class Class extends core::Object {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart.expect
index 82c5c73..6ca7b29 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-abstract class A extends core::Object {
+abstract class A extends core::Object implements core::Enum {
}
abstract class B extends core::Object {
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → void;
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
index 07ed13e..64a9777 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
@@ -95,7 +95,13 @@
@patch
static apply(Function function, List<dynamic>? positionalArguments,
[Map<Symbol, dynamic>? namedArguments]) {
- positionalArguments ??= [];
+ if (positionalArguments == null) {
+ positionalArguments = [];
+ } else if (JS<bool>('!', '!Array.isArray(#)', positionalArguments)) {
+ // dcall expects the positionalArguments as a JS array.
+ positionalArguments = List.of(positionalArguments);
+ }
+
// dcall expects the namedArguments as a JS map in the last slot.
if (namedArguments != null && namedArguments.isNotEmpty) {
var map = JS('', '{}');
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
index 174b2ff..0c30b2c 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
@@ -320,7 +320,7 @@
let errorMessage = $_argumentErrors($ftype, $args, $named);
if (errorMessage == null) {
if ($typeArgs != null) $args = $typeArgs.concat($args);
- if ($named != null) $args.push($named);
+ if ($named != null) $args = $args.concat($named);
return $f.apply($obj, $args);
}
return callNSM(errorMessage);
diff --git a/sdk/lib/core/core.dart b/sdk/lib/core/core.dart
index 7e96d5c..3799c08 100644
--- a/sdk/lib/core/core.dart
+++ b/sdk/lib/core/core.dart
@@ -178,6 +178,7 @@
part "date_time.dart";
part "double.dart";
part "duration.dart";
+part "enum.dart";
part "errors.dart";
part "exceptions.dart";
part "expando.dart";
diff --git a/sdk/lib/core/core_sources.gni b/sdk/lib/core/core_sources.gni
index ce2785e..66362e9 100644
--- a/sdk/lib/core/core_sources.gni
+++ b/sdk/lib/core/core_sources.gni
@@ -13,6 +13,7 @@
"date_time.dart",
"double.dart",
"duration.dart",
+ "enum.dart",
"errors.dart",
"exceptions.dart",
"expando.dart",
diff --git a/sdk/lib/core/enum.dart b/sdk/lib/core/enum.dart
new file mode 100644
index 0000000..c220b42
--- /dev/null
+++ b/sdk/lib/core/enum.dart
@@ -0,0 +1,23 @@
+// 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.
+
+part of dart.core;
+
+/// An enumerated value.
+///
+/// This class is implemented by all types and values
+/// introduced using an `enum` declaration.
+/// Non-platform classes cannot implement, extend or
+/// mix in this class.
+@Since("2.14")
+abstract class Enum {
+ /// A numeric identifier for the enumerated value.
+ ///
+ /// The values of a single enumeration are numbered
+ /// consecutively from zero to one less than the
+ /// number of values.
+ /// This is also the index of the value in the
+ /// enumerated type's static `values` list.
+ int get index;
+}
diff --git a/tests/language/closure/partial_instantiation_static_bounds_check_test.dart b/tests/language/closure/partial_instantiation_static_bounds_check_test.dart
index 38192ba..435918e 100644
--- a/tests/language/closure/partial_instantiation_static_bounds_check_test.dart
+++ b/tests/language/closure/partial_instantiation_static_bounds_check_test.dart
@@ -17,6 +17,7 @@
void Function(int) k = instanceFn;
// ^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+ // [cfe] Inferred type argument 'int' doesn't conform to the bound 'T' of the type variable 'S' on 'dynamic Function<S extends T>(S)'.
}
}
@@ -28,7 +29,9 @@
void Function(String) k0 = localFn;
// ^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+ // [cfe] Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'Null Function<T extends num>(T)'.
void Function(String) k1 = topFn;
// ^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+ // [cfe] Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'dynamic Function<T extends num>(T)'.
}
diff --git a/tests/language/enum/enum_test.dart b/tests/language/enum/enum_test.dart
index 87d6d65..8b21613 100644
--- a/tests/language/enum/enum_test.dart
+++ b/tests/language/enum/enum_test.dart
@@ -88,6 +88,11 @@
expectIs(value, (e) => e is JSFunctionPrototype);
}
Expect.equals(JSFunctionPrototype.length, JSFunctionPrototype.values[0]);
+
+ // Enums implement Enum.
+ Expect.type<Enum>(Enum1._);
+ Enum enumValue = Enum1._;
+ Expect.equals(0, enumValue.index);
}
test1(Enum1 e) {
diff --git a/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart b/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart
index 8de7729..968ae22 100644
--- a/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart
+++ b/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart
@@ -17,7 +17,7 @@
R instanceMethod<R, T>(T value, [T? other]) => value as R;
void tearOffsOnThis() {
- const staticTearoff = staticMethod<int, String>;
+ const staticTearOff = staticMethod<int, String>;
staticMethod<int, String>
.expectStaticType<Exactly<int Function(String, [String?])>>();
instanceMethod<int, String>
@@ -37,7 +37,7 @@
R mixinInstanceMethod<R, T>(T value, [T? other]) => value as R;
void mixinTearOffsOnThis() {
- const staticTearoff = staticMethod<int, String>;
+ const staticTearOff = staticMethod<int, String>;
staticMethod<int, String>
.expectStaticType<Exactly<int Function(String, [String?])>>();
mixinInstanceMethod<int, String>
@@ -57,8 +57,8 @@
static R staticMethod<R, T>(T value, [T? other]) => value as R;
R extInstanceMethod<R, T>(T value, [T? other]) => value as R;
- void extenstionTearOffsOnThis() {
- const staticTearoff = staticMethod<int, String>;
+ void extensionTearOffsOnThis() {
+ const staticTearOff = staticMethod<int, String>;
staticMethod<int, String>
.expectStaticType<Exactly<int Function(String, [String?])>>();
extInstanceMethod<int, String>
@@ -87,10 +87,10 @@
R local<R, T>(T value, [T? other]) => value as R;
// Check that some tear-offs are constant.
- const topTearoff = toplevel<int, String>;
- const staticTearoff = C.staticMethod<int, String>;
- const mixinStaticTearoff = M.staticMethod<int, String>;
- const extensionStaticTearoff = E.staticMethod<int, String>;
+ const topTearOff = toplevel<int, String>;
+ const staticTearOff = C.staticMethod<int, String>;
+ const mixinStaticTearOff = M.staticMethod<int, String>;
+ const extensionStaticTearOff = E.staticMethod<int, String>;
// Check that the tear-offs have the correct static type.
@@ -105,23 +105,23 @@
E
.staticMethod<int, String>
.expectStaticType<Exactly<int Function(String, [String?])>>();
- c
+ o
.instanceMethod<int, String>
.expectStaticType<Exactly<int Function(String, [String?])>>();
- c
+ o
.mixinInstanceMethod<int, String>
.expectStaticType<Exactly<int Function(String, [String?])>>();
- c
+ o
.extInstanceMethod<int, String>
.expectStaticType<Exactly<int Function(String, [String?])>>();
local<int, String>
.expectStaticType<Exactly<int Function(String, [String?])>>();
// Check that the tear-offs are canonicalized where possible.
- Expect.identical(toplevel<int, String>, topTearoff);
- Expect.identical(C.staticMethod<int, String>, staticTearoff);
- Expect.identical(M.staticMethod<int, String>, mixinStaticTearoff);
- Expect.identical(E.staticMethod<int, String>, extensionStaticTearoff);
+ Expect.identical(toplevel<int, String>, topTearOff);
+ Expect.identical(C.staticMethod<int, String>, staticTearOff);
+ Expect.identical(M.staticMethod<int, String>, mixinStaticTearOff);
+ Expect.identical(E.staticMethod<int, String>, extensionStaticTearOff);
// Instantiated local methods may or may not be equal.
// (Specification makes no promise about equality.).
@@ -161,7 +161,7 @@
}<int>());
o.tearOffsOnThis();
- o.tearOffOnSuper();
- o.mixinTearOffOnThis();
- o.extensionTearOffOnThis();
+ o.tearOffsOnSuper();
+ o.mixinTearOffsOnThis();
+ o.extensionTearOffsOnThis();
}
diff --git a/tests/language/unsorted/inference_enum_list_test.dart b/tests/language/unsorted/inference_enum_list_test.dart
index dc7b7bd3..0502272 100644
--- a/tests/language/unsorted/inference_enum_list_test.dart
+++ b/tests/language/unsorted/inference_enum_list_test.dart
@@ -4,11 +4,12 @@
enum E1 { a, b }
enum E2 { a, b }
+enum E3 { a, b }
var v = [E1.a, E2.b];
main() {
- // Test that v is `List<Object>`, so any of these assignemnts are OK.
- v[0] = 0;
- v[1] = '1';
+ // Test that v is `List<Enum>`, so these assignments are OK.
+ v[0] = E3.a;
+ List<Enum> w = v;
}
diff --git a/tests/language_2/closure/partial_instantiation_static_bounds_check_test.dart b/tests/language_2/closure/partial_instantiation_static_bounds_check_test.dart
index 2810e7a..34e6b18 100644
--- a/tests/language_2/closure/partial_instantiation_static_bounds_check_test.dart
+++ b/tests/language_2/closure/partial_instantiation_static_bounds_check_test.dart
@@ -19,6 +19,7 @@
void Function(int) k = instanceFn;
// ^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+ // [cfe] Inferred type argument 'int' doesn't conform to the bound 'T' of the type variable 'S' on 'dynamic Function<S extends T>(S)'.
}
}
@@ -30,7 +31,9 @@
void Function(String) k0 = localFn;
// ^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+ // [cfe] Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'Null Function<T extends num>(T)'.
void Function(String) k1 = topFn;
// ^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+ // [cfe] Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'dynamic Function<T extends num>(T)'.
}
diff --git a/tests/language_2/enum/enum_test.dart b/tests/language_2/enum/enum_test.dart
index eb0d039..8eb762f 100644
--- a/tests/language_2/enum/enum_test.dart
+++ b/tests/language_2/enum/enum_test.dart
@@ -90,6 +90,11 @@
expectIs(value, (e) => e is JSFunctionPrototype);
}
Expect.equals(JSFunctionPrototype.length, JSFunctionPrototype.values[0]);
+
+ // Enums implement Enum.
+ Expect.type<Enum>(Enum1._);
+ Enum enumValue = Enum1._;
+ Expect.equals(0, enumValue.index);
}
test1(Enum1 e) {
diff --git a/tests/language_2/unsorted/inference_enum_list_test.dart b/tests/language_2/unsorted/inference_enum_list_test.dart
index 66e7a00..45ec575 100644
--- a/tests/language_2/unsorted/inference_enum_list_test.dart
+++ b/tests/language_2/unsorted/inference_enum_list_test.dart
@@ -6,11 +6,12 @@
enum E1 { a, b }
enum E2 { a, b }
+enum E3 { a, b }
var v = [E1.a, E2.b];
main() {
- // Test that v is `List<Object>`, so any of these assignemnts are OK.
- v[0] = 0;
- v[1] = '1';
+ // Test that v is `List<Enum>`, so these assignments are OK.
+ v[0] = E3.a;
+ List<Enum> w = v;
}
diff --git a/tests/web/internal/mock_libraries.dart b/tests/web/internal/mock_libraries.dart
index f747443..9f0be35 100644
--- a/tests/web/internal/mock_libraries.dart
+++ b/tests/web/internal/mock_libraries.dart
@@ -50,6 +50,10 @@
static var nan = 0;
static parse(s) {}
}''',
+ 'Enum': r'''
+ abstract class Enum {
+ int get index;
+ }''',
'Function': r'''
class Function {
static apply(Function fn, List positional, [Map named]) => null;
diff --git a/tools/VERSION b/tools/VERSION
index 2264ce2..54a920f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 248
+PRERELEASE 249
PRERELEASE_PATCH 0
\ No newline at end of file