mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 05:07:52 +00:00
analyzer: Allow generic function types as type arguments in const creations
Fixes https://github.com/dart-lang/sdk/issues/55459 Change-Id: I0903f3784a4f370981926c29561904d61420ef34 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/369121 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Auto-Submit: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
parent
d56cef5b3b
commit
43791032fc
|
@ -549,14 +549,20 @@ class ConstantVerifier extends RecursiveAstVisitor<void> {
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Verify that the given [type] does not reference any type parameters.
|
||||
/// Verify that the given [type] does not reference any type parameters which
|
||||
/// are declared outside [type].
|
||||
///
|
||||
/// A generic function type is allowed to reference its own type parameter(s).
|
||||
///
|
||||
/// See [CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS].
|
||||
void _checkForConstWithTypeParameters(
|
||||
TypeAnnotation type, ErrorCode errorCode) {
|
||||
TypeAnnotation type, ErrorCode errorCode,
|
||||
{Set<TypeParameterElement>? allowedTypeParameters}) {
|
||||
allowedTypeParameters = {...?allowedTypeParameters};
|
||||
if (type is NamedType) {
|
||||
// Should not be a type parameter.
|
||||
if (type.element is TypeParameterElement) {
|
||||
if (type.element is TypeParameterElement &&
|
||||
!allowedTypeParameters.contains(type.element)) {
|
||||
_errorReporter.atNode(
|
||||
type,
|
||||
errorCode,
|
||||
|
@ -566,31 +572,38 @@ class ConstantVerifier extends RecursiveAstVisitor<void> {
|
|||
// Check type arguments.
|
||||
var typeArguments = type.typeArguments;
|
||||
if (typeArguments != null) {
|
||||
for (TypeAnnotation argument in typeArguments.arguments) {
|
||||
_checkForConstWithTypeParameters(argument, errorCode);
|
||||
for (var argument in typeArguments.arguments) {
|
||||
_checkForConstWithTypeParameters(argument, errorCode,
|
||||
allowedTypeParameters: allowedTypeParameters);
|
||||
}
|
||||
}
|
||||
} else if (type is GenericFunctionType) {
|
||||
var returnType = type.returnType;
|
||||
if (returnType != null) {
|
||||
_checkForConstWithTypeParameters(returnType, errorCode);
|
||||
}
|
||||
for (var parameter in type.parameters.parameters) {
|
||||
// [parameter] cannot be a [DefaultFormalParameter], a
|
||||
// [FieldFormalParameter], nor a [FunctionTypedFormalParameter].
|
||||
if (parameter is SimpleFormalParameter) {
|
||||
var parameterType = parameter.type;
|
||||
if (parameterType != null) {
|
||||
_checkForConstWithTypeParameters(parameterType, errorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
var typeParameters = type.typeParameters;
|
||||
if (typeParameters != null) {
|
||||
allowedTypeParameters.addAll(typeParameters.typeParameters
|
||||
.map((tp) => tp.declaredElement)
|
||||
.nonNulls);
|
||||
for (var typeParameter in typeParameters.typeParameters) {
|
||||
var bound = typeParameter.bound;
|
||||
if (bound != null) {
|
||||
_checkForConstWithTypeParameters(bound, errorCode);
|
||||
_checkForConstWithTypeParameters(bound, errorCode,
|
||||
allowedTypeParameters: allowedTypeParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
var returnType = type.returnType;
|
||||
if (returnType != null) {
|
||||
_checkForConstWithTypeParameters(returnType, errorCode,
|
||||
allowedTypeParameters: allowedTypeParameters);
|
||||
}
|
||||
for (var parameter in type.parameters.parameters) {
|
||||
// In a generic function type, [parameter] can only be a
|
||||
// [SimpleFormalParameter].
|
||||
if (parameter is SimpleFormalParameter) {
|
||||
var parameterType = parameter.type;
|
||||
if (parameterType != null) {
|
||||
_checkForConstWithTypeParameters(parameterType, errorCode,
|
||||
allowedTypeParameters: allowedTypeParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,11 +26,7 @@ void g() {
|
|||
const [f as void Function<T>(T, [int])];
|
||||
}
|
||||
''', [
|
||||
// This error is reported because the cast fails if the type on the right
|
||||
// has type parameters.
|
||||
// TODO(srawlins): Deduplicate these two errors.
|
||||
error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 38, 31),
|
||||
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS, 60, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -355,6 +351,39 @@ class A<T> {
|
|||
''');
|
||||
}
|
||||
|
||||
test_indirect_functionType_typeParameter_nestedFunctionType() async {
|
||||
await assertNoErrorsInCode('''
|
||||
class A<T> {
|
||||
const A();
|
||||
void m() {
|
||||
const A<void Function<U>(void Function<V>(U, V))>();
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_indirect_functionType_typeParameter_referencedDirectly() async {
|
||||
await assertNoErrorsInCode('''
|
||||
class A<T> {
|
||||
const A();
|
||||
void m() {
|
||||
const A<U Function<U>()>();
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_indirect_functionType_typeParameter_typeArgumentOfReturnType() async {
|
||||
await assertNoErrorsInCode('''
|
||||
class A<T> {
|
||||
const A();
|
||||
void m() {
|
||||
const A<List<U> Function<U>()>();
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_indirect_functionType_typeParameter_typeParameterBound() async {
|
||||
await assertErrorsInCode('''
|
||||
class A<T> {
|
||||
|
|
Loading…
Reference in a new issue