Skip to content

Commit e84af9b

Browse files
askeksacommit-bot@chromium.org
authored andcommitted
[cfe] Disallow annotations on type parameters of function types
Also, do not copy annotations on type parameters of functions into their inferred types. See dart-lang/language#656 Change-Id: I1460007645a32ac56a505b23ab3ee8a457c3f994 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/123732 Commit-Queue: Aske Simon Christensen <[email protected]> Reviewed-by: Erik Ernst <[email protected]>
1 parent 2b56db6 commit e84af9b

9 files changed

+35
-15
lines changed

pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@ Message _withArgumentsAccessError(String name) {
102102
message: """Access error: '${name}'.""", arguments: {'name': name});
103103
}
104104

105+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
106+
const Code<Null> codeAnnotationOnFunctionTypeTypeVariable =
107+
messageAnnotationOnFunctionTypeTypeVariable;
108+
109+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
110+
const MessageCode messageAnnotationOnFunctionTypeTypeVariable =
111+
const MessageCode("AnnotationOnFunctionTypeTypeVariable",
112+
message:
113+
r"""A type variable on a function type can't have annotations.""");
114+
105115
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
106116
const Code<Null> codeAnonymousBreakTargetOutsideFunction =
107117
messageAnonymousBreakTargetOutsideFunction;

pkg/front_end/lib/src/fasta/kernel/body_builder.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3041,6 +3041,15 @@ class BodyBuilder extends ScopeListener<JumpTarget>
30413041
FormalParameters formals = pop();
30423042
UnresolvedType returnType = pop();
30433043
List<TypeVariableBuilder> typeVariables = pop();
3044+
if (typeVariables != null) {
3045+
for (TypeVariableBuilder builder in typeVariables) {
3046+
if (builder.parameter.annotations.isNotEmpty) {
3047+
addProblem(fasta.messageAnnotationOnFunctionTypeTypeVariable,
3048+
builder.charOffset, builder.name.length);
3049+
builder.parameter.annotations = const <Expression>[];
3050+
}
3051+
}
3052+
}
30443053
UnresolvedType type = formals.toFunctionType(
30453054
returnType,
30463055
libraryBuilder.nullableBuilderIfTrue(questionMark != null),

pkg/front_end/messages.status

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ AccessError/analyzerCode: Fail
1313
AccessError/example: Fail
1414
AmbiguousSupertypes/example: Fail
1515
AnnotationOnEnumConstant/example: Fail
16+
AnnotationOnFunctionTypeTypeVariable/analyzerCode: Fail
1617
AnonymousBreakTargetOutsideFunction/part_wrapped_statement: Fail
1718
AnonymousBreakTargetOutsideFunction/statement: Fail # Duplicated error as parser also complains.
1819
AnonymousContinueTargetOutsideFunction/part_wrapped_statement: Fail

pkg/front_end/messages.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,6 +2061,11 @@ TypeVariableSameNameAsEnclosing:
20612061
template: "A type variable can't have the same name as its enclosing declaration."
20622062
analyzerCode: CONFLICTING_TYPE_VARIABLE_AND_CLASS
20632063

2064+
AnnotationOnFunctionTypeTypeVariable:
2065+
template: "A type variable on a function type can't have annotations."
2066+
script:
2067+
- "main() { Function<@Object() T>() x; }"
2068+
20642069
ExpectedEnumBody:
20652070
template: "Expected a enum body, but got '#lexeme'."
20662071
tip: "An enum definition must have a body with at least one constant name."

pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class Foo {
1111

1212
void test() {
1313
void f<@Foo(/*@ typeArgs=String* */ const []) T>() {}
14-
var /*@ type=<@Foo::•(const <String*>[]) T extends Object* = dynamic>() ->* Null? */ x =
14+
var /*@ type=<T extends Object* = dynamic>() ->* Null? */ x =
1515
<@Foo(/*@ typeArgs=String* */ const []) T> /*@ returnType=Null? */ () {};
1616
}
1717

pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class Foo extends core::Object {
99
}
1010
static method test() → void {
1111
function f<@#C1 T extends core::Object* = dynamic>() → void {}
12-
<@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() →* core::Null? x = <@#C1 T extends core::Object* = dynamic>() → core::Null? {};
12+
<T extends core::Object* = dynamic>() →* core::Null? x = <@#C1 T extends core::Object* = dynamic>() → core::Null? {};
1313
}
1414
static method main() → dynamic {}
1515

pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class Foo extends core::Object {
99
}
1010
static method test() → void {
1111
function f<@#C1 T extends core::Object* = dynamic>() → void {}
12-
<@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() →* core::Null? x = <@#C1 T extends core::Object* = dynamic>() → core::Null? {};
12+
<T extends core::Object* = dynamic>() →* core::Null? x = <@#C1 T extends core::Object* = dynamic>() → core::Null? {};
1313
}
1414
static method main() → dynamic {}
1515

pkg/kernel/lib/type_algebra.dart

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
library kernel.type_algebra;
55

66
import 'ast.dart';
7-
import 'clone.dart';
87

98
/// Returns a type where all occurrences of the given type parameters have been
109
/// replaced with the corresponding types.
@@ -117,7 +116,6 @@ FreshTypeParameters getFreshTypeParameters(List<TypeParameter> typeParameters) {
117116
map[typeParameters[i]] = new TypeParameterType.forAlphaRenaming(
118117
typeParameters[i], freshParameters[i]);
119118
}
120-
CloneVisitor cloner;
121119
for (int i = 0; i < typeParameters.length; ++i) {
122120
TypeParameter typeParameter = typeParameters[i];
123121
TypeParameter freshTypeParameter = freshParameters[i];
@@ -128,16 +126,9 @@ FreshTypeParameters getFreshTypeParameters(List<TypeParameter> typeParameters) {
128126
: null;
129127
freshTypeParameter.variance =
130128
typeParameter.isLegacyCovariant ? null : typeParameter.variance;
131-
if (typeParameter.annotations.isNotEmpty) {
132-
// Annotations can't refer to type parameters, so the cloner shouldn't
133-
// perform the substitution.
134-
// TODO(dmitryas): Consider rewriting getFreshTypeParameters using cloner
135-
// for copying typeParameters as well.
136-
cloner ??= new CloneVisitor();
137-
for (Expression annotation in typeParameter.annotations) {
138-
freshTypeParameter.addAnnotation(cloner.clone(annotation));
139-
}
140-
}
129+
// Annotations on a type parameter are specific to the declaration of the
130+
// type parameter, rather than the type parameter as such, and therefore
131+
// should not be copied here.
141132
}
142133
return new FreshTypeParameters(freshParameters, Substitution.fromMap(map));
143134
}

pkg/kernel/lib/verifier.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ class VerifyingVisitor extends RecursiveVisitor<void> {
351351
declareTypeParameters(node.typeParameters);
352352
for (var typeParameter in node.typeParameters) {
353353
typeParameter.bound?.accept(this);
354+
if (typeParameter.annotations.isNotEmpty) {
355+
problem(
356+
typeParameter, "Annotation on type parameter in function type.");
357+
}
354358
}
355359
visitList(node.positionalParameters, this);
356360
visitList(node.namedParameters, this);

0 commit comments

Comments
 (0)