[fasta] Reland "Handle annotations on formals and variables"
The original CL: https://dart-review.googlesource.com/c/sdk/+/51840
Bug: http://dartbug.com/28434
Change-Id: I0812ef4223337f5bf72218dfac0f26f76a6b9df1
Reviewed-on: https://dart-review.googlesource.com/52449
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
Reviewed-by: Jenny Messerly <jmesserly@google.com>
diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart
index 742508b..fd456d2 100644
--- a/pkg/dev_compiler/test/nullable_inference_test.dart
+++ b/pkg/dev_compiler/test/nullable_inference_test.dart
@@ -413,27 +413,25 @@
useAnnotations = false;
});
var imports = "import 'package:meta/meta.dart';";
- group('(kernel annotation bug)', () {
- test('variable wihout initializer', () async {
- await expectNotNull('$imports main() { @notNull var x; print(x); }',
- ''); // should be: 'x'
+ group('(previously known kernel annotation bug)', () {
+ test('variable without initializer', () async {
+ await expectNotNull(
+ '$imports main() { @notNull var x; print(x); }', 'x');
});
test('variable with initializer', () async {
// TODO(jmesserly): this does not work in the Analyzer backend.
await expectNotNull(
- '$imports main() { @notNull var x = null; print(x); }',
- ''); // should be: 'x'
+ '$imports main() { @notNull var x = null; print(x); }', 'x');
});
test('parameters', () async {
await expectNotNull(
'$imports f(@notNull x, [@notNull y, @notNull z = 42]) '
'{ x; y; z; }',
- '42, z'); // should be: '42, x, y, z'
+ '42, x, y, z');
});
test('named parameters', () async {
await expectNotNull(
- '$imports f({@notNull x, @notNull y: 42}) { x; y; }',
- '42, y'); // should be: '42, x, y'
+ '$imports f({@notNull x, @notNull y: 42}) { x; y; }', '42, x, y');
});
});
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 02d9745..c8c3b63 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -1699,7 +1699,14 @@
constantContext = pop();
currentLocalVariableType = pop();
currentLocalVariableModifiers = pop();
- pop(); // Metadata.
+ List<Expression> annotations = pop();
+ if (annotations != null) {
+ for (VariableDeclaration variable in variables) {
+ for (Expression annotation in annotations) {
+ variable.addAnnotation(annotation);
+ }
+ }
+ }
if (variables.length != 1) {
push(variables);
} else {
@@ -2134,7 +2141,7 @@
}
bool isConst = (modifiers & constMask) != 0;
bool isFinal = (modifiers & finalMask) != 0;
- ignore(Unhandled.Metadata);
+ List annotations = pop();
VariableDeclaration variable;
if (!inCatchClause &&
functionNestingLevel == 0 &&
@@ -2162,6 +2169,14 @@
variable.fileOffset = offsetForToken(name.token);
}
}
+ if (annotations != null) {
+ if (functionNestingLevel == 0) {
+ _typeInferrer.inferMetadata(this, annotations);
+ }
+ for (Expression annotation in annotations) {
+ variable.addAnnotation(annotation);
+ }
+ }
push(variable);
}
@@ -2942,8 +2957,9 @@
returnType ??= const DynamicType();
exitFunction();
List<TypeParameter> typeParameters = typeVariableBuildersToKernel(pop());
+ List<Expression> annotations;
if (!isFunctionExpression) {
- pop(); // Metadata.
+ annotations = pop(); // Metadata.
}
FunctionNode function = formals.addToFunction(new FunctionNode(body,
typeParameters: typeParameters,
@@ -2954,6 +2970,11 @@
if (declaration is FunctionDeclaration) {
VariableDeclaration variable = declaration.variable;
+ if (annotations != null) {
+ for (Expression annotation in annotations) {
+ variable.addAnnotation(annotation);
+ }
+ }
ShadowFunctionDeclaration.setHasImplicitReturnType(
declaration, hasImplicitReturnType);
@@ -3545,8 +3566,7 @@
debugEvent("TypeVariable");
DartType bound = pop();
Identifier name = pop();
- // TODO(ahe): Do not discard metadata.
- pop(); // Metadata.
+ List<Expression> annotations = pop();
KernelTypeVariableBuilder variable;
Object inScope = scopeLookup(scope, name.name, token);
if (inScope is TypeDeclarationAccessor) {
@@ -3558,6 +3578,12 @@
name.name, library, offsetForToken(name.token), null);
}
variable.parameter.bound = bound;
+ if (annotations != null) {
+ _typeInferrer.inferMetadata(this, annotations);
+ for (Expression annotation in annotations) {
+ variable.parameter.addAnnotation(annotation);
+ }
+ }
push(variable
..finish(library, library.loader.target.objectClassBuilder,
library.loader.target.dynamicType));
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index b4c9192..71372b9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -34,6 +34,7 @@
import 'package:front_end/src/fasta/type_inference/type_schema_elimination.dart';
import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
import 'package:kernel/ast.dart' hide InvalidExpression, InvalidInitializer;
+import 'package:kernel/clone.dart' show CloneVisitor;
import 'package:kernel/frontend/accessors.dart';
import 'package:kernel/type_algebra.dart';
@@ -879,6 +880,7 @@
}
inferrer.inferStatement(body);
if (_declaresVariable) {
+ inferrer.inferMetadataKeepingHelper(variable.annotations);
var tempVar =
new VariableDeclaration(null, type: inferredType, isFinal: true);
var variableGet = new VariableGet(tempVar)
@@ -941,6 +943,7 @@
@override
void _inferStatement(ShadowTypeInferrer inferrer) {
+ inferrer.inferMetadataKeepingHelper(variable.annotations);
inferrer.inferLocalFunction(
function,
null,
@@ -2270,6 +2273,26 @@
@override
void _inferStatement(ShadowTypeInferrer inferrer) {
+ inferrer.inferMetadataKeepingHelper(annotations);
+
+ // After the inference was done on the annotations, we may clone them for
+ // this instance of VariableDeclaration in order to avoid having the same
+ // annotation node for two VariableDeclaration nodes in a situation like
+ // the following:
+ //
+ // class Foo { const Foo(List<String> list); }
+ //
+ // @Foo(const [])
+ // var x, y;
+ CloneVisitor cloner = new CloneVisitor();
+ for (int i = 0; i < annotations.length; ++i) {
+ Expression annotation = annotations[i];
+ if (annotation.parent != this) {
+ annotations[i] = cloner.clone(annotation);
+ annotations[i].parent = this;
+ }
+ }
+
var declaredType = _implicitlyTyped ? const UnknownType() : type;
DartType inferredType;
DartType initializerType;
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 4971952..719ca60 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -337,6 +337,10 @@
/// Performs type inference on the given metadata annotations.
void inferMetadata(BuilderHelper helper, List<Expression> annotations);
+ /// Performs type inference on the given metadata annotations keeping the
+ /// existing helper if possible.
+ void inferMetadataKeepingHelper(List<Expression> annotations);
+
/// Performs type inference on the given function parameter initializer
/// expression.
void inferParameterInitializer(
@@ -374,6 +378,9 @@
void inferMetadata(BuilderHelper helper, List<Expression> annotations) {}
@override
+ void inferMetadataKeepingHelper(List<Expression> annotations) {}
+
+ @override
void inferParameterInitializer(
BuilderHelper helper, Expression initializer, DartType declaredType) {}
}
@@ -1100,6 +1107,7 @@
var positionalParameters = function.positionalParameters;
for (var i = 0; i < positionalParameters.length; i++) {
var parameter = positionalParameters[i];
+ inferMetadataKeepingHelper(parameter.annotations);
if (i >= function.requiredParameterCount &&
parameter.initializer == null) {
parameter.initializer = new ShadowNullLiteral()..parent = parameter;
@@ -1109,6 +1117,7 @@
}
}
for (var parameter in function.namedParameters) {
+ inferMetadataKeepingHelper(parameter.annotations);
if (parameter.initializer == null) {
parameter.initializer = new ShadowNullLiteral()..parent = parameter;
}
@@ -1239,14 +1248,25 @@
void inferMetadata(BuilderHelper helper, List<Expression> annotations) {
if (annotations != null) {
this.helper = helper;
+ inferMetadataKeepingHelper(annotations);
+ this.helper = null;
+ }
+ }
+
+ @override
+ void inferMetadataKeepingHelper(List<Expression> annotations) {
+ if (annotations != null) {
// Place annotations in a temporary list literal so that they will have a
// parent. This is necessary in case any of the annotations need to get
// replaced during type inference.
+ var parents = annotations.map((e) => e.parent).toList();
new ListLiteral(annotations);
for (var annotation in annotations) {
inferExpression(annotation, const UnknownType(), false);
}
- this.helper = null;
+ for (int i = 0; i < annotations.length; ++i) {
+ annotations[i].parent = parents[i];
+ }
}
}
diff --git a/pkg/front_end/testcases/annotation_variable_declaration.dart b/pkg/front_end/testcases/annotation_variable_declaration.dart
new file mode 100644
index 0000000..c64fad7
--- /dev/null
+++ b/pkg/front_end/testcases/annotation_variable_declaration.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2018, 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.
+
+const int foo = 42;
+
+class Bar {
+ const Bar();
+ const Bar.named(x);
+}
+
+class Baz {
+ Baz(@foo constructorFormal);
+
+ factory Baz.bazFactory(@foo factoryFormal) => null;
+
+ fisk(@foo formal1, @Bar() formal2, @Bar.named(foo) formal3,
+ @foo @Bar.named(foo) formal4,
+ [@foo optional]) {
+ @foo
+ var local1;
+
+ @Bar()
+ var local2;
+
+ @Bar.named(foo)
+ var local3;
+
+ @foo
+ @Bar.named(foo)
+ var local4;
+
+ @foo
+ var localWithInitializer = "hello";
+
+ @foo
+ @Bar.named(foo)
+ var localGroupPart1, localGroupPart2;
+
+ naebdyr(@foo nestedFormal) => null;
+
+ var roedmus = (@foo closureFormal) => null;
+ }
+
+ hest({@foo named}) => null;
+}
+
+typedef hest_t({@foo named});
+
+main() {}
diff --git a/pkg/front_end/testcases/annotation_variable_declaration.dart.direct.expect b/pkg/front_end/testcases/annotation_variable_declaration.dart.direct.expect
new file mode 100644
index 0000000..95f1aa8
--- /dev/null
+++ b/pkg/front_end/testcases/annotation_variable_declaration.dart.direct.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef hest_t = ({named: dynamic}) → dynamic;
+class Bar extends core::Object {
+ const constructor •() → void
+ : super core::Object::•()
+ ;
+ const constructor named(dynamic x) → void
+ : super core::Object::•()
+ ;
+}
+class Baz extends core::Object {
+ constructor •(@self::foo dynamic constructorFormal) → void
+ : super core::Object::•()
+ ;
+ static factory bazFactory(@self::foo dynamic factoryFormal) → self::Baz
+ return null;
+ method fisk(@self::foo dynamic formal1, @self::Bar::•() dynamic formal2, @self::Bar::named(self::foo) dynamic formal3, @self::foo @self::Bar::named(self::foo) dynamic formal4, [@self::foo dynamic optional = null]) → dynamic {
+ @self::foo dynamic local1;
+ @self::Bar::•() dynamic local2;
+ @self::Bar::named(self::foo) dynamic local3;
+ @self::foo @self::Bar::named(self::foo) dynamic local4;
+ @self::foo dynamic localWithInitializer = "hello";
+ @self::foo @self::Bar::named(self::foo) dynamic localGroupPart1;
+ @self::foo @self::Bar::named(self::foo) dynamic localGroupPart2;
+ function naebdyr(@self::foo dynamic nestedFormal) → dynamic
+ return null;
+ dynamic roedmus = (@self::foo dynamic closureFormal) → dynamic => null;
+ }
+ method hest({@self::foo dynamic named = null}) → dynamic
+ return null;
+}
+static const field core::int foo = 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/annotation_variable_declaration.dart.direct.transformed.expect b/pkg/front_end/testcases/annotation_variable_declaration.dart.direct.transformed.expect
new file mode 100644
index 0000000..95f1aa8
--- /dev/null
+++ b/pkg/front_end/testcases/annotation_variable_declaration.dart.direct.transformed.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef hest_t = ({named: dynamic}) → dynamic;
+class Bar extends core::Object {
+ const constructor •() → void
+ : super core::Object::•()
+ ;
+ const constructor named(dynamic x) → void
+ : super core::Object::•()
+ ;
+}
+class Baz extends core::Object {
+ constructor •(@self::foo dynamic constructorFormal) → void
+ : super core::Object::•()
+ ;
+ static factory bazFactory(@self::foo dynamic factoryFormal) → self::Baz
+ return null;
+ method fisk(@self::foo dynamic formal1, @self::Bar::•() dynamic formal2, @self::Bar::named(self::foo) dynamic formal3, @self::foo @self::Bar::named(self::foo) dynamic formal4, [@self::foo dynamic optional = null]) → dynamic {
+ @self::foo dynamic local1;
+ @self::Bar::•() dynamic local2;
+ @self::Bar::named(self::foo) dynamic local3;
+ @self::foo @self::Bar::named(self::foo) dynamic local4;
+ @self::foo dynamic localWithInitializer = "hello";
+ @self::foo @self::Bar::named(self::foo) dynamic localGroupPart1;
+ @self::foo @self::Bar::named(self::foo) dynamic localGroupPart2;
+ function naebdyr(@self::foo dynamic nestedFormal) → dynamic
+ return null;
+ dynamic roedmus = (@self::foo dynamic closureFormal) → dynamic => null;
+ }
+ method hest({@self::foo dynamic named = null}) → dynamic
+ return null;
+}
+static const field core::int foo = 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/annotation_variable_declaration.dart.outline.expect b/pkg/front_end/testcases/annotation_variable_declaration.dart.outline.expect
new file mode 100644
index 0000000..6382194
--- /dev/null
+++ b/pkg/front_end/testcases/annotation_variable_declaration.dart.outline.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef hest_t = ({named: dynamic}) → dynamic;
+class Bar extends core::Object {
+ const constructor •() → void
+ ;
+ const constructor named(dynamic x) → void
+ ;
+}
+class Baz extends core::Object {
+ constructor •(dynamic constructorFormal) → void
+ ;
+ static factory bazFactory(dynamic factoryFormal) → self::Baz
+ ;
+ method fisk(dynamic formal1, dynamic formal2, dynamic formal3, dynamic formal4, [dynamic optional]) → dynamic
+ ;
+ method hest({dynamic named}) → dynamic
+ ;
+}
+static const field core::int foo;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/annotation_variable_declaration.dart.strong.expect b/pkg/front_end/testcases/annotation_variable_declaration.dart.strong.expect
new file mode 100644
index 0000000..9ab4cb7
--- /dev/null
+++ b/pkg/front_end/testcases/annotation_variable_declaration.dart.strong.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef hest_t = ({named: dynamic}) → dynamic;
+class Bar extends core::Object {
+ const constructor •() → void
+ : super core::Object::•()
+ ;
+ const constructor named(dynamic x) → void
+ : super core::Object::•()
+ ;
+}
+class Baz extends core::Object {
+ constructor •(@self::foo dynamic constructorFormal) → void
+ : super core::Object::•()
+ ;
+ static factory bazFactory(@self::foo dynamic factoryFormal) → self::Baz
+ return null;
+ method fisk(@self::foo dynamic formal1, @self::Bar::•() dynamic formal2, @self::Bar::named(self::foo) dynamic formal3, @self::foo @self::Bar::named(self::foo) dynamic formal4, [@self::foo dynamic optional = null]) → dynamic {
+ @self::foo dynamic local1;
+ @self::Bar::•() dynamic local2;
+ @self::Bar::named(self::foo) dynamic local3;
+ @self::foo @self::Bar::named(self::foo) dynamic local4;
+ @self::foo core::String localWithInitializer = "hello";
+ @self::foo @self::Bar::named(self::foo) dynamic localGroupPart1;
+ @self::foo @self::Bar::named(self::foo) dynamic localGroupPart2;
+ function naebdyr(@self::foo dynamic nestedFormal) → core::Null
+ return null;
+ (dynamic) → core::Null roedmus = (@self::foo dynamic closureFormal) → core::Null => null;
+ }
+ method hest({@self::foo dynamic named = null}) → dynamic
+ return null;
+}
+static const field core::int foo = 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/annotation_variable_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/annotation_variable_declaration.dart.strong.transformed.expect
new file mode 100644
index 0000000..9ab4cb7
--- /dev/null
+++ b/pkg/front_end/testcases/annotation_variable_declaration.dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef hest_t = ({named: dynamic}) → dynamic;
+class Bar extends core::Object {
+ const constructor •() → void
+ : super core::Object::•()
+ ;
+ const constructor named(dynamic x) → void
+ : super core::Object::•()
+ ;
+}
+class Baz extends core::Object {
+ constructor •(@self::foo dynamic constructorFormal) → void
+ : super core::Object::•()
+ ;
+ static factory bazFactory(@self::foo dynamic factoryFormal) → self::Baz
+ return null;
+ method fisk(@self::foo dynamic formal1, @self::Bar::•() dynamic formal2, @self::Bar::named(self::foo) dynamic formal3, @self::foo @self::Bar::named(self::foo) dynamic formal4, [@self::foo dynamic optional = null]) → dynamic {
+ @self::foo dynamic local1;
+ @self::Bar::•() dynamic local2;
+ @self::Bar::named(self::foo) dynamic local3;
+ @self::foo @self::Bar::named(self::foo) dynamic local4;
+ @self::foo core::String localWithInitializer = "hello";
+ @self::foo @self::Bar::named(self::foo) dynamic localGroupPart1;
+ @self::foo @self::Bar::named(self::foo) dynamic localGroupPart2;
+ function naebdyr(@self::foo dynamic nestedFormal) → core::Null
+ return null;
+ (dynamic) → core::Null roedmus = (@self::foo dynamic closureFormal) → core::Null => null;
+ }
+ method hest({@self::foo dynamic named = null}) → dynamic
+ return null;
+}
+static const field core::int foo = 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/ast_builder.status b/pkg/front_end/testcases/ast_builder.status
index 0007d0b..cbb6e2d 100644
--- a/pkg/front_end/testcases/ast_builder.status
+++ b/pkg/front_end/testcases/ast_builder.status
@@ -11,13 +11,7 @@
inference/abstract_class_instantiation: Fail
inference/constructors_too_many_positional_arguments: Fail
inference/downwards_inference_annotations: Crash
-inference/downwards_inference_annotations_for_loop_variable: Fail
-inference/downwards_inference_annotations_locals: Fail
-inference/downwards_inference_annotations_locals_referring_to_locals: Fail
-inference/downwards_inference_annotations_parameter: Fail
-inference/downwards_inference_annotations_parameter_local: Fail
inference/downwards_inference_annotations_type_variable: Fail
-inference/downwards_inference_annotations_type_variable_local: Fail
inference/downwards_inference_annotations_typedef: Crash
inference/downwards_inference_on_function_of_t_using_the_t: Fail
inference/downwards_inference_yield_yield_star: Fail
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.direct.expect
index 84e4744..c7a86c1 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.direct.expect
@@ -8,9 +8,9 @@
;
}
static method test() → void {
- for (core::int i = 0; i.<(1); i = i.+(1)) {
+ for (@self::Foo::•(const <dynamic>[]) core::int i = 0; i.<(1); i = i.+(1)) {
}
- for (core::int i in <dynamic>[0]) {
+ for (@self::Foo::•(const <dynamic>[]) core::int i in <dynamic>[0]) {
}
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.direct.transformed.expect
index 84e4744..c7a86c1 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.direct.transformed.expect
@@ -8,9 +8,9 @@
;
}
static method test() → void {
- for (core::int i = 0; i.<(1); i = i.+(1)) {
+ for (@self::Foo::•(const <dynamic>[]) core::int i = 0; i.<(1); i = i.+(1)) {
}
- for (core::int i in <dynamic>[0]) {
+ for (@self::Foo::•(const <dynamic>[]) core::int i in <dynamic>[0]) {
}
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.expect
new file mode 100644
index 0000000..e4d43d3
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.expect
@@ -0,0 +1,16 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ const constructor •(core::List<core::String> l) → void
+ : super core::Object::•()
+ ;
+}
+static method test() → void {
+ for (@self::Foo::•(const <core::String>[]) core::int i = 0; i.{core::num::<}(1); i = i.{core::num::+}(1)) {
+ }
+ for (@self::Foo::•(const <core::String>[]) core::int i in <core::int>[0]) {
+ }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.transformed.expect
new file mode 100644
index 0000000..e4d43d3
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.transformed.expect
@@ -0,0 +1,16 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ const constructor •(core::List<core::String> l) → void
+ : super core::Object::•()
+ ;
+}
+static method test() → void {
+ for (@self::Foo::•(const <core::String>[]) core::int i = 0; i.{core::num::<}(1); i = i.{core::num::+}(1)) {
+ }
+ for (@self::Foo::•(const <core::String>[]) core::int i in <core::int>[0]) {
+ }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.expect
new file mode 100644
index 0000000..70f1ea3
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.expect
@@ -0,0 +1,15 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ const constructor •(core::List<core::String> l) → void
+ : super core::Object::•()
+ ;
+}
+static method test() → void {
+ @self::Foo::•(const <core::String>[]) dynamic x;
+ @self::Foo::•(const <core::String>[])
+ function f() → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.transformed.expect
new file mode 100644
index 0000000..70f1ea3
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.transformed.expect
@@ -0,0 +1,15 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ const constructor •(core::List<core::String> l) → void
+ : super core::Object::•()
+ ;
+}
+static method test() → void {
+ @self::Foo::•(const <core::String>[]) dynamic x;
+ @self::Foo::•(const <core::String>[])
+ function f() → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart
index 9d389ca..b28b2ed 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart
@@ -14,6 +14,11 @@
@Foo(/*@typeArgs=int*/ const [x])
var /*@type=dynamic*/ y;
+
+ @Foo(/*@typeArgs=int*/ const [x])
+ void bar() {}
+
+ void baz(@Foo(/*@typeArgs=int*/ const [x]) dynamic formal) {}
}
main() {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.direct.expect
index d3afdb6..a0385be 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.direct.expect
@@ -9,6 +9,9 @@
}
static method test() → void {
const dynamic x = 0;
- dynamic y;
+ @self::Foo::•(const <dynamic>[x]) dynamic y;
+ @self::Foo::•(const <dynamic>[x])
+ function bar() → void {}
+ function baz(@self::Foo::•(const <dynamic>[x]) dynamic formal) → void {}
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.direct.transformed.expect
index d3afdb6..a0385be 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.direct.transformed.expect
@@ -9,6 +9,9 @@
}
static method test() → void {
const dynamic x = 0;
- dynamic y;
+ @self::Foo::•(const <dynamic>[x]) dynamic y;
+ @self::Foo::•(const <dynamic>[x])
+ function bar() → void {}
+ function baz(@self::Foo::•(const <dynamic>[x]) dynamic formal) → void {}
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.expect
new file mode 100644
index 0000000..eac77b2
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.expect
@@ -0,0 +1,17 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ const constructor •(dynamic l) → void
+ : super core::Object::•()
+ ;
+}
+static method test() → void {
+ const core::int x = 0;
+ @self::Foo::•(const <core::int>[x]) dynamic y;
+ @self::Foo::•(const <core::int>[x])
+ function bar() → void {}
+ function baz(@self::Foo::•(const <core::int>[x]) dynamic formal) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.transformed.expect
new file mode 100644
index 0000000..eac77b2
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ const constructor •(dynamic l) → void
+ : super core::Object::•()
+ ;
+}
+static method test() → void {
+ const core::int x = 0;
+ @self::Foo::•(const <core::int>[x]) dynamic y;
+ @self::Foo::•(const <core::int>[x])
+ function bar() → void {}
+ function baz(@self::Foo::•(const <core::int>[x]) dynamic formal) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.direct.expect
index 306b574..9d2c6e3 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.direct.expect
@@ -11,7 +11,7 @@
synthetic constructor •() → void
: super core::Object::•()
;
- method m(dynamic x) → void {}
+ method m(@self::Foo::•(const <dynamic>[]) dynamic x) → void {}
}
-static method f(dynamic x) → void {}
+static method f(@self::Foo::•(const <dynamic>[]) dynamic x) → void {}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.direct.transformed.expect
index 306b574..9d2c6e3 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.direct.transformed.expect
@@ -11,7 +11,7 @@
synthetic constructor •() → void
: super core::Object::•()
;
- method m(dynamic x) → void {}
+ method m(@self::Foo::•(const <dynamic>[]) dynamic x) → void {}
}
-static method f(dynamic x) → void {}
+static method f(@self::Foo::•(const <dynamic>[]) dynamic x) → void {}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.expect
new file mode 100644
index 0000000..7775e23
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.expect
@@ -0,0 +1,17 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ const constructor •(core::List<core::String> l) → void
+ : super core::Object::•()
+ ;
+}
+class C extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method m(@self::Foo::•(const <core::String>[]) dynamic x) → void {}
+}
+static method f(@self::Foo::•(const <core::String>[]) dynamic x) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.transformed.expect
new file mode 100644
index 0000000..7775e23
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ const constructor •(core::List<core::String> l) → void
+ : super core::Object::•()
+ ;
+}
+class C extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method m(@self::Foo::•(const <core::String>[]) dynamic x) → void {}
+}
+static method f(@self::Foo::•(const <core::String>[]) dynamic x) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart
index 6cc32b3..e3198ae 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart
@@ -11,7 +11,7 @@
void test() {
void f(@Foo(/*@typeArgs=String*/ const []) /*@type=dynamic*/ x) {}
- var /*@type=(dynamic) -> Null*/ x = /*@returnType=Null*/ (/*@type=dynamic*/ @Foo(/*@typeArgs=String*/ const [])
+ var /*@type=(dynamic) -> Null*/ x = /*@returnType=Null*/ (@Foo(/*@typeArgs=String*/ const []) /*@type=dynamic*/
x) {};
}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.direct.expect
index d53d84c..9163b9d 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.direct.expect
@@ -8,7 +8,7 @@
;
}
static method test() → void {
- function f(dynamic x) → void {}
- dynamic x = (dynamic x) → dynamic {};
+ function f(@self::Foo::•(const <dynamic>[]) dynamic x) → void {}
+ dynamic x = (@self::Foo::•(const <dynamic>[]) dynamic x) → dynamic {};
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.direct.transformed.expect
index d53d84c..9163b9d 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.direct.transformed.expect
@@ -8,7 +8,7 @@
;
}
static method test() → void {
- function f(dynamic x) → void {}
- dynamic x = (dynamic x) → dynamic {};
+ function f(@self::Foo::•(const <dynamic>[]) dynamic x) → void {}
+ dynamic x = (@self::Foo::•(const <dynamic>[]) dynamic x) → dynamic {};
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect
new file mode 100644
index 0000000..90d59e7
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect
@@ -0,0 +1,14 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ const constructor •(core::List<core::String> l) → void
+ : super core::Object::•()
+ ;
+}
+static method test() → void {
+ function f(@self::Foo::•(const <core::String>[]) dynamic x) → void {}
+ (dynamic) → core::Null x = (@self::Foo::•(const <core::String>[]) dynamic x) → core::Null {};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect
new file mode 100644
index 0000000..90d59e7
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect
@@ -0,0 +1,14 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ const constructor •(core::List<core::String> l) → void
+ : super core::Object::•()
+ ;
+}
+static method test() → void {
+ function f(@self::Foo::•(const <core::String>[]) dynamic x) → void {}
+ (dynamic) → core::Null x = (@self::Foo::•(const <core::String>[]) dynamic x) → core::Null {};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart
index 3ec0b43..b048a1b 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart
@@ -11,7 +11,7 @@
void test() {
void f<@Foo(/*@typeArgs=String*/ const []) T>() {}
- var /*@type=<T extends Object>() -> Null*/ x =
+ var /*@type=<@Foo::•(const <String>[]) T extends Object = dynamic>() -> Null*/ x =
<@Foo(/*@typeArgs=String*/ const []) T> /*@returnType=Null*/ () {};
}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.direct.expect
index 7f49df8..d94bf7a 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.direct.expect
@@ -8,7 +8,7 @@
;
}
static method test() → void {
- function f<T extends core::Object = dynamic>() → void {}
- dynamic x = <T extends core::Object = dynamic>() → dynamic {};
+ function f<@self::Foo::•(const <dynamic>[]) T extends core::Object = dynamic>() → void {}
+ dynamic x = <@self::Foo::•(const <dynamic>[]) T extends core::Object = dynamic>() → dynamic {};
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.direct.transformed.expect
index 7f49df8..d94bf7a 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.direct.transformed.expect
@@ -8,7 +8,7 @@
;
}
static method test() → void {
- function f<T extends core::Object = dynamic>() → void {}
- dynamic x = <T extends core::Object = dynamic>() → dynamic {};
+ function f<@self::Foo::•(const <dynamic>[]) T extends core::Object = dynamic>() → void {}
+ dynamic x = <@self::Foo::•(const <dynamic>[]) T extends core::Object = dynamic>() → dynamic {};
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
new file mode 100644
index 0000000..657f6f6
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
@@ -0,0 +1,14 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ const constructor •(core::List<core::String> l) → void
+ : super core::Object::•()
+ ;
+}
+static method test() → void {
+ function f<@self::Foo::•(const <core::String>[]) T extends core::Object = dynamic>() → void {}
+ <@self::Foo::•(const <core::String>[]) T extends core::Object = dynamic>() → core::Null x = <@self::Foo::•(const <core::String>[]) T extends core::Object = dynamic>() → core::Null {};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
new file mode 100644
index 0000000..657f6f6
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
@@ -0,0 +1,14 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ const constructor •(core::List<core::String> l) → void
+ : super core::Object::•()
+ ;
+}
+static method test() → void {
+ function f<@self::Foo::•(const <core::String>[]) T extends core::Object = dynamic>() → void {}
+ <@self::Foo::•(const <core::String>[]) T extends core::Object = dynamic>() → core::Null x = <@self::Foo::•(const <core::String>[]) T extends core::Object = dynamic>() → core::Null {};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 6f767dc..3ee0f85 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -77,13 +77,7 @@
inference/constructors_infer_from_arguments_argument_not_assignable: TypeCheckError
inference/constructors_too_many_positional_arguments: Fail # Issue #30040
inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer: TypeCheckError
-inference/downwards_inference_annotations_for_loop_variable: Fail # Issue #28434
-inference/downwards_inference_annotations_locals: Fail # Issue #30031 and Issue #28434
-inference/downwards_inference_annotations_locals_referring_to_locals: Fail # Issue #28434
-inference/downwards_inference_annotations_parameter: Fail # Issue #28434
-inference/downwards_inference_annotations_parameter_local: Fail # Issue #28434
-inference/downwards_inference_annotations_type_variable: Fail # Issue #28434
-inference/downwards_inference_annotations_type_variable_local: Fail # Issue #28434
+inference/downwards_inference_annotations_type_variable: Fail # Issue 28981
inference/downwards_inference_on_function_of_t_using_the_t: Fail # Issue #29798
inference/downwards_inference_on_list_literals_infer_downwards: RuntimeError
inference/downwards_inference_yield_yield_star: TypeCheckError
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 2d27d28..cc6aa3c 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -4451,11 +4451,13 @@
accept1(StatementVisitor1 v, arg) => v.visitVariableDeclaration(this, arg);
visitChildren(Visitor v) {
+ visitList(annotations, v);
type?.accept(v);
initializer?.accept(v);
}
transformChildren(Transformer v) {
+ transformList(annotations, v, this);
type = v.visitDartType(type);
if (initializer != null) {
initializer = initializer.accept(v);
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 4ec4cbd..e039b20 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -869,11 +869,17 @@
}
}
- void writeAnnotationList(List<Expression> nodes) {
+ void writeAnnotationList(List<Expression> nodes, {bool separateLines: true}) {
for (Expression node in nodes) {
- writeIndentation();
+ if (separateLines) {
+ writeIndentation();
+ }
writeAnnotation(node);
- endLine();
+ if (separateLines) {
+ endLine();
+ } else {
+ writeSpace();
+ }
}
}
@@ -1671,6 +1677,7 @@
}
visitFunctionDeclaration(FunctionDeclaration node) {
+ writeAnnotationList(node.variable.annotations);
writeIndentation();
writeWord('function');
if (node.function != null) {
@@ -1685,7 +1692,7 @@
{bool useVarKeyword: false}) {
if (showOffsets) writeWord("[${node.fileOffset}]");
if (showMetadata) writeMetadata(node);
- writeAnnotationList(node.annotations);
+ writeAnnotationList(node.annotations, separateLines: false);
writeModifier(node.isCovariant, 'covariant');
writeModifier(node.isGenericCovariantImpl, 'generic-covariant-impl');
writeModifier(
@@ -1836,7 +1843,7 @@
writeModifier(node.isGenericCovariantImpl, 'generic-covariant-impl');
writeModifier(
node.isGenericCovariantInterface, 'generic-covariant-interface');
- writeAnnotationList(node.annotations);
+ writeAnnotationList(node.annotations, separateLines: false);
writeWord(getTypeParameterName(node));
writeSpaced('extends');
writeType(node.bound);