Resolve typed constant initializers separately.
R=brianwilkerson@google.com
Change-Id: Id54b57a40004de0c9adc345e1f944fc89b568e68
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100929
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index b2958f6..82fe2ca 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -130,6 +130,7 @@
_createLoadLibraryFunctions();
_performTopLevelInference();
_resolveConstructors();
+ _resolveConstantInitializers();
_resolveDefaultValues();
_resolveMetadata();
_collectMixinSuperInvokedNames();
@@ -251,6 +252,10 @@
TopLevelInference(this).infer();
}
+ void _resolveConstantInitializers() {
+ ConstantInitializersResolver(this).perform();
+ }
+
void _resolveConstructors() {
for (var library in builders.values) {
library.resolveConstructors();
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 35cdd00..09a4027 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -711,6 +711,10 @@
}
bool hasImplicitReturnType(AstNode node) {
+ if (node is FunctionDeclaration) {
+ LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
+ return node.returnType == null;
+ }
if (node is MethodDeclaration) {
LazyMethodDeclaration.readReturnTypeNode(_astReader, node);
return node.returnType == null;
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index 4b7cd9f..4b6dae9 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
@@ -546,11 +547,7 @@
var name = node.name.name;
reference = reference.getChild('@class').getChild(name);
- var element = ClassElementImpl.forLinkedNode(
- outerReference.element,
- reference,
- node,
- );
+ ClassElementImpl element = reference.element;
node.name.staticElement = element;
_createTypeParameterElements(node.typeParameters);
scope = new TypeParameterScope(scope, element);
@@ -576,11 +573,7 @@
var name = node.name.name;
reference = reference.getChild('@class').getChild(name);
- var element = ClassElementImpl.forLinkedNode(
- outerReference.element,
- reference,
- node,
- );
+ ClassElementImpl element = reference.element;
node.name.staticElement = element;
_createTypeParameterElements(node.typeParameters);
scope = new TypeParameterScope(scope, element);
@@ -665,14 +658,18 @@
var outerScope = scope;
var outerReference = reference;
- var name = node.name.name;
- reference = reference.getChild('@function').getChild(name);
+ var container = '@function';
+ var propertyKeyword = node.propertyKeyword?.keyword;
+ if (propertyKeyword == Keyword.GET) {
+ container = '@getter';
+ } else if (propertyKeyword == Keyword.SET) {
+ container = '@setter';
+ }
- var element = FunctionElementImpl.forLinkedNode(
- outerReference.element,
- reference,
- node,
- );
+ var name = node.name.name;
+ reference = reference.getChild(container).getChild(name);
+
+ ExecutableElementImpl element = reference.element;
node.name.staticElement = element;
_createTypeParameterElements(node.functionExpression.typeParameters);
scope = new FunctionScope(scope, element);
@@ -700,11 +697,7 @@
var name = node.name.name;
reference = reference.getChild('@typeAlias').getChild(name);
- var element = GenericTypeAliasElementImpl.forLinkedNode(
- outerReference.element,
- reference,
- node,
- );
+ GenericTypeAliasElementImpl element = reference.element;
node.name.staticElement = element;
_createTypeParameterElements(node.typeParameters);
scope = FunctionTypeScope(outerScope, element);
@@ -790,11 +783,7 @@
var name = node.name.name;
reference = reference.getChild('@typeAlias').getChild(name);
- var element = GenericTypeAliasElementImpl.forLinkedNode(
- outerReference.element,
- reference,
- node,
- );
+ GenericTypeAliasElementImpl element = reference.element;
node.name.staticElement = element;
_createTypeParameterElements(node.typeParameters);
scope = TypeParameterScope(outerScope, element);
@@ -817,8 +806,16 @@
var outerScope = scope;
var outerReference = reference;
+ var container = '@method';
+ var propertyKeyword = node.propertyKeyword?.keyword;
+ if (propertyKeyword == Keyword.GET) {
+ container = '@getter';
+ } else if (propertyKeyword == Keyword.SET) {
+ container = '@setter';
+ }
+
var name = node.name.name;
- reference = reference.getChild('@method').getChild(name);
+ reference = reference.getChild(container).getChild(name);
var element = MethodElementImpl.forLinkedNode(
outerReference.element,
@@ -847,11 +844,7 @@
var name = node.name.name;
reference = reference.getChild('@mixin').getChild(name);
- var element = ClassElementImpl.forLinkedNode(
- outerReference.element,
- reference,
- node,
- );
+ MixinElementImpl element = reference.element;
node.name.staticElement = element;
_createTypeParameterElements(node.typeParameters);
scope = new TypeParameterScope(scope, element);
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index 7e588a4..0916c0d 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -32,6 +32,53 @@
return (element as ElementImpl).linkedNode;
}
+/// Resolver for typed constant top-level variables and fields initializers.
+///
+/// Initializers of untyped variables are resolved during [TopLevelInference].
+class ConstantInitializersResolver {
+ final Linker linker;
+
+ LibraryElement _library;
+ Scope _scope;
+
+ ConstantInitializersResolver(this.linker);
+
+ DynamicTypeImpl get _dynamicType => DynamicTypeImpl.instance;
+
+ void perform() {
+ for (var builder in linker.builders.values) {
+ _library = builder.element;
+ for (var unitContext in builder.context.units) {
+ for (var unitMember in unitContext.unit.declarations) {
+ _scope = builder.libraryScope;
+ if (unitMember is TopLevelVariableDeclaration) {
+ _variableDeclarationList(unitMember.variables);
+ } else if (unitMember is ClassOrMixinDeclaration) {
+ _scope = LinkingNodeContext.get(unitMember).scope;
+ for (var classMember in unitMember.members) {
+ if (classMember is FieldDeclaration) {
+ _variableDeclarationList(classMember.fields);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void _variableDeclarationList(VariableDeclarationList node) {
+ if (node.isConst && node.type != null) {
+ for (var variable in node.variables) {
+ var initializer = variable.initializer;
+ if (initializer != null) {
+ var astResolver = AstResolver(linker, _library, _scope);
+ astResolver.resolve(initializer, doAstRewrite: true);
+ }
+ }
+ }
+ }
+}
+
class TopLevelInference {
final Linker linker;
@@ -143,6 +190,15 @@
_InferenceNode(this._walker, this._library, this._scope, this._node);
+ bool get isImplicitlyTypedInstanceField {
+ VariableDeclarationList variables = _node.parent;
+ if (variables.type == null) {
+ var parent = variables.parent;
+ return parent is FieldDeclaration && !parent.isStatic;
+ }
+ return false;
+ }
+
@override
List<_InferenceNode> computeDependencies() {
_node.initializer.accept(LocalElementBuilder(ElementHolder(), null));
@@ -156,10 +212,20 @@
return const <_InferenceNode>[];
}
- return collector._set
+ var dependencies = collector._set
.map(_walker.getNode)
.where((node) => node != null)
.toList();
+
+ for (var node in dependencies) {
+ if (node.isImplicitlyTypedInstanceField) {
+ LazyAst.setType(_node, DynamicTypeImpl.instance);
+ isEvaluated = true;
+ return const <_InferenceNode>[];
+ }
+ }
+
+ return dependencies;
}
void evaluate() {
@@ -260,7 +326,6 @@
}
void perform() {
- createNodes();
_walker.walkNodes();
}
@@ -276,17 +341,15 @@
if (element.isSynthetic) return;
VariableDeclaration node = _getLinkedNode(element);
- if (LazyAst.getType(node) == null || element.isConst) {
- if (node.initializer != null) {
- var inferenceNode = _InferenceNode(_walker, _library, _scope, node);
- _walker._nodes[element] = inferenceNode;
- (element as PropertyInducingElementImpl).initializer =
- _FunctionElementForLink_Initializer(inferenceNode);
- } else {
- if (LazyAst.getType(node) == null) {
- LazyAst.setType(node, DynamicTypeImpl.instance);
- }
- }
+ if (LazyAst.getType(node) != null) return;
+
+ if (node.initializer != null) {
+ var inferenceNode = _InferenceNode(_walker, _library, _scope, node);
+ _walker._nodes[element] = inferenceNode;
+ (element as PropertyInducingElementImpl).initializer =
+ _FunctionElementForLink_Initializer(inferenceNode);
+ } else {
+ LazyAst.setType(node, DynamicTypeImpl.instance);
}
}
}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index 56f71d34..da49022b 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -112,12 +112,6 @@
@override
@failingTest
- test_const_constructor_inferred_args() async {
- await super.test_const_constructor_inferred_args();
- }
-
- @override
- @failingTest
test_syntheticFunctionType_genericClosure() async {
// TODO(scheglov) Bug in TypeSystem.getLeastUpperBound().
// LUB(<T>(T) → int, <T>(T) → int) gives `(T) → int`, note absence of `<T>`.
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 7ae6c74..9d7839b 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -2280,6 +2280,26 @@
withConstElements: false);
}
+ test_const_classField() async {
+ var library = await checkLibrary(r'''
+class C {
+ static const int f1 = 1;
+ static const int f2 = C.f1, f3 = C.f2;
+}
+''');
+ checkElementText(library, r'''
+class C {
+ static const int f1 = 1;
+ static const int f2 =
+ C/*location: test.dart;C*/.
+ f1/*location: test.dart;C;f1?*/;
+ static const int f3 =
+ C/*location: test.dart;C*/.
+ f2/*location: test.dart;C;f2?*/;
+}
+''');
+ }
+
test_const_constructor_inferred_args() async {
var library = await checkLibrary('''
class C<T> {