[cfe] Support explicit instantiation

+ add bounds check for implicit instantiation

Closes #46458

Change-Id: I032f79d8ae4ed6944fbad999e067976ff72d94fe
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/204802
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
Johnni Winther 2021-06-25 14:47:45 +00:00 committed by commit-bot@chromium.org
parent 43cff26365
commit 268290725d
45 changed files with 1626 additions and 45 deletions

View file

@ -5175,6 +5175,64 @@ Message _withArgumentsInputFileNotFound(Uri uri_) {
message: """Input file not found: ${uri}.""", arguments: {'uri': uri_});
}
// 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(

View file

@ -1783,6 +1783,111 @@ Message _withArgumentsIncorrectTypeArgumentInferred(DartType _type,
});
}
// 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,
@ -1939,6 +2044,37 @@ Message _withArgumentsInitializingFormalTypeMismatch(
arguments: {'name': name, 'type': _type, 'type2': _type2});
}
// 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(

View file

@ -6302,13 +6302,21 @@ class BodyBuilder extends ScopeListener<JumpTarget>
@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(

View file

@ -214,12 +214,6 @@ class InferenceVisitor
return _unhandledExpression(node, typeContext);
}
@override
ExpressionInferenceResult visitInstantiation(
Instantiation node, DartType typeContext) {
return _unhandledExpression(node, typeContext);
}
@override
ExpressionInferenceResult visitConstructorTearOff(
ConstructorTearOff node, DartType typeContext) {
@ -298,6 +292,63 @@ class InferenceVisitor
return new ExpressionInferenceResult(const DynamicType(), node);
}
@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) {

View file

@ -3533,23 +3533,43 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
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 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
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()) {

View file

@ -85,6 +85,8 @@ class ValueKinds {
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 =

View file

@ -3752,6 +3752,19 @@ class TypeInferrerImpl implements TypeInferrer {
}
}
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 @@ class TypeInferrerImpl implements TypeInferrer {
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;
}

View file

@ -434,6 +434,9 @@ InitializerForStaticField/example: Fail
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

View file

@ -4291,6 +4291,27 @@ IncorrectTypeArgumentInSupertypeInferred:
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 @@ DeprecateDartExt:
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>;

View file

@ -267,9 +267,11 @@ ease
ec
echo
edits
einst
elapse
elegantly
ell
emethod
entrypoint
entrypoints
eoo
@ -278,6 +280,7 @@ erase
erased
err
esc
estat
et
everytime
evicting
@ -294,6 +297,10 @@ expanded
expansive
explainer
extern
f1
f2
f3
f4
fac
faking
falling
@ -530,6 +537,7 @@ micro
minimize
minimizer
minimizing
minst
mintty
minutes
mismatched
@ -539,11 +547,13 @@ misses
misspelled
mistake
mistakes
mmethod
mod
modelled
month
moo
mouse
mstat
mul
mx
mxn

View file

@ -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() {}

View file

@ -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
}

View file

@ -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
}

View file

@ -0,0 +1,4 @@
T func<T>(T value) => value;
var funcValue = func;
int Function(int) f = funcValue.call;
main() {}

View file

@ -0,0 +1,4 @@
T func<T>(T value) => value;
int Function(int) f = funcValue.call;
main() {}
var funcValue = func;

View file

@ -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
}

View file

@ -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
;

View file

@ -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
}

View file

@ -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();
}

View file

@ -0,0 +1,100 @@
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 = #C1<core::int>;
core::String f1TypeName = (#C1<core::int>).{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 = #C2<core::int>;
core::String f1TypeName = (#C2<core::int>).{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 = #C3<core::int>;
core::String f1TypeName = (#C3<core::int>).{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 = #C4;
core::Type t2 = #C5;
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 = (#C4).{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 = tearoff self::M::mstat
#C3 = tearoff self::Ext|estat
#C4 = TypeLiteralConstant(core::List<core::int>)
#C5 = TypeLiteralConstant(core::List<core::List<core::int>>)
}

View file

@ -0,0 +1,119 @@
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 = #C1<core::int>;
core::String f1TypeName = (#C1<core::int>).{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 = #C2<core::int>;
core::String f1TypeName = (#C2<core::int>).{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 = #C2<core::int>;
core::String f1TypeName = (#C2<core::int>).{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 = #C3<core::int>;
core::String f1TypeName = (#C3<core::int>).{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 = #C4;
core::Type t2 = #C5;
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 = (#C4).{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 = tearoff self::M::mstat
#C3 = tearoff self::Ext|estat
#C4 = TypeLiteralConstant(core::List<core::int>)
#C5 = TypeLiteralConstant(core::List<core::List<core::int>>)
}
Extra constant evaluation status:
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:13:18 -> PartialInstantiationConstant(C.stat<int>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:14:26 -> PartialInstantiationConstant(C.stat<int>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:26:19 -> PartialInstantiationConstant(M.mstat<int>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:27:27 -> PartialInstantiationConstant(M.mstat<int>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:26:19 -> PartialInstantiationConstant(M.mstat<int>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:27:27 -> PartialInstantiationConstant(M.mstat<int>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:39:19 -> PartialInstantiationConstant(Ext|estat<int>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:40:27 -> PartialInstantiationConstant(Ext|estat<int>)
Extra constant evaluation: evaluated: 120, effectively constant: 8

View file

@ -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() {}

View file

@ -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() {}

View file

@ -0,0 +1,100 @@
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 = #C1<core::int>;
core::String f1TypeName = (#C1<core::int>).{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 = #C2<core::int>;
core::String f1TypeName = (#C2<core::int>).{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 = #C3<core::int>;
core::String f1TypeName = (#C3<core::int>).{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 = #C4;
core::Type t2 = #C5;
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 = (#C4).{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 = tearoff self::M::mstat
#C3 = tearoff self::Ext|estat
#C4 = TypeLiteralConstant(core::List<core::int*>*)
#C5 = TypeLiteralConstant(core::List<core::List<core::int*>*>*)
}

View file

@ -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
;

View file

@ -0,0 +1,119 @@
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 = #C1<core::int>;
core::String f1TypeName = (#C1<core::int>).{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 = #C2<core::int>;
core::String f1TypeName = (#C2<core::int>).{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 = #C2<core::int>;
core::String f1TypeName = (#C2<core::int>).{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 = #C3<core::int>;
core::String f1TypeName = (#C3<core::int>).{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 = #C4;
core::Type t2 = #C5;
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 = (#C4).{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 = tearoff self::M::mstat
#C3 = tearoff self::Ext|estat
#C4 = TypeLiteralConstant(core::List<core::int*>*)
#C5 = TypeLiteralConstant(core::List<core::List<core::int*>*>*)
}
Extra constant evaluation status:
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:13:18 -> PartialInstantiationConstant(C.stat<int*>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:14:26 -> PartialInstantiationConstant(C.stat<int*>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:26:19 -> PartialInstantiationConstant(M.mstat<int*>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:27:27 -> PartialInstantiationConstant(M.mstat<int*>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:26:19 -> PartialInstantiationConstant(M.mstat<int*>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:27:27 -> PartialInstantiationConstant(M.mstat<int*>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:39:19 -> PartialInstantiationConstant(Ext|estat<int*>)
Evaluated: Instantiation @ org-dartlang-testcase:///explicit_instantiation.dart:40:27 -> PartialInstantiationConstant(Ext|estat<int*>)
Extra constant evaluation: evaluated: 120, effectively constant: 8

View file

@ -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() {}

View file

@ -0,0 +1,110 @@
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 = #C1<core::int>;
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 = #C2<core::String>;
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 = #C1<core::int>;
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 = #C2<core::String>;
}
static method main() → dynamic {}
constants {
#C1 = tearoff self::id
#C2 = tearoff self::boundedMethod
}

View file

@ -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() {}

View file

@ -0,0 +1,110 @@
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 = #C1<core::int>;
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 = #C2<core::String>;
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 = #C1<core::int>;
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 = #C2<core::String>;
}
static method main() → dynamic {}
constants {
#C1 = tearoff self::id
#C2 = tearoff self::boundedMethod
}

View file

@ -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
;

View file

@ -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() {}

View file

@ -0,0 +1,2 @@
test() {}
main() {}

View file

@ -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 {}

View file

@ -0,0 +1,7 @@
library /*isNonNullableByDefault*/;
import self as self;
static method test() → dynamic
;
static method main() → dynamic
;

View file

@ -2,6 +2,12 @@ library test;
//
// 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 @@ library test;
// /*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 @@ library test;
// 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);
// ^

View file

@ -2,6 +2,12 @@ library test;
//
// 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 @@ library test;
// /*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 @@ library test;
// 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);
// ^

View file

@ -8,6 +8,7 @@
dart2js/late_statics: SemiFuzzFailure # dartbug.com/45854
constructor_tearoffs/explicit_instantiation_errors: TypeCheckError
constructor_tearoffs/redirecting_constructors: RuntimeError
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.

View file

@ -6,6 +6,7 @@
# the round trip for Kernel textual serialization where the initial binary
# Kernel files are produced by compiling Dart code via Fasta.
constructor_tearoffs/explicit_instantiation_errors: TypeCheckError
constructor_tearoffs/redirecting_constructors: RuntimeError
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
@ -22,6 +23,7 @@ general/abstract_members: TypeCheckError
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

View file

@ -23,6 +23,7 @@ regress/utf_16_le_content.crash: EmptyOutput
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/instantiation: FormatterCrash

View file

@ -11,6 +11,7 @@ general/error_recovery/issue_39058.crash: SemiFuzzFailure
regress/utf_16_le_content.crash: SemiFuzzCrash
dart2js/late_statics: SemiFuzzFailure # dartbug.com/45854
constructor_tearoffs/explicit_instantiation_errors: TypeCheckError
constructor_tearoffs/redirecting_constructors: RuntimeError
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
@ -27,6 +28,7 @@ general/abstract_members: TypeCheckError
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

View file

@ -17,6 +17,7 @@ class D<T> extends C<T> {
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 main() {
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)'.
}

View file

@ -17,7 +17,7 @@ class C {
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 @@ mixin M on C {
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 @@ extension E on C {
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 @@ void main() {
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 @@ void main() {
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 @@ void main() {
}<int>());
o.tearOffsOnThis();
o.tearOffOnSuper();
o.mixinTearOffOnThis();
o.extensionTearOffOnThis();
o.tearOffsOnSuper();
o.mixinTearOffsOnThis();
o.extensionTearOffsOnThis();
}

View file

@ -19,6 +19,7 @@ class D<T> extends C<T> {
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 main() {
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)'.
}