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