Record TopLevelInferenceErrorKind.dependencyCycle in summary2.

R=brianwilkerson@google.com

Change-Id: I1869f31dd6163827026e8e9d54e8682cb9ab2405
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99820
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index c188876..945fd82 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -7935,6 +7935,10 @@
 
   @override
   TopLevelInferenceError get typeInferenceError {
+    if (linkedNode != null) {
+      return linkedContext.getTypeInferenceError(linkedNode);
+    }
+
     if (_unlinkedVariable != null) {
       return enclosingUnit.resynthesizerContext
           .getTypeInferenceError(_unlinkedVariable.inferredTypeSlot);
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index d23f079..7f60c19 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -4754,6 +4754,7 @@
   idl.LinkedNodeKind _kind;
   String _variantField_20;
   bool _variantField_31;
+  TopLevelInferenceErrorBuilder _variantField_35;
   String _variantField_22;
   LinkedNodeVariablesDeclarationBuilder _variantField_32;
 
@@ -10009,6 +10010,17 @@
   }
 
   @override
+  TopLevelInferenceErrorBuilder get topLevelTypeInferenceError {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_35;
+  }
+
+  set topLevelTypeInferenceError(TopLevelInferenceErrorBuilder value) {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_35 = value;
+  }
+
+  @override
   String get uriBasedDirective_uriContent {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective ||
@@ -10240,6 +10252,7 @@
     LinkedNodeBuilder variableDeclaration_name,
     int codeLength,
     int codeOffset,
+    TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
     LinkedNodeVariablesDeclarationBuilder variableDeclaration_declaration,
   })  : _kind = idl.LinkedNodeKind.variableDeclaration,
         _variantField_24 = actualType,
@@ -10250,6 +10263,7 @@
         _variantField_7 = variableDeclaration_name,
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset,
+        _variantField_35 = topLevelTypeInferenceError,
         _variantField_32 = variableDeclaration_declaration;
 
   LinkedNodeBuilder.binaryExpression({
@@ -11621,6 +11635,7 @@
     _variantField_10?.flushInformative();
     _variantField_25?.flushInformative();
     _variantField_14?.flushInformative();
+    _variantField_35?.flushInformative();
     _variantField_32?.flushInformative();
   }
 
@@ -11711,6 +11726,8 @@
     this._variantField_32?.collectApiSignature(signature);
     signature.addInt(this._variantField_33 ?? 0);
     signature.addInt(this._variantField_34 ?? 0);
+    signature.addBool(this._variantField_35 != null);
+    this._variantField_35?.collectApiSignature(signature);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -11733,6 +11750,7 @@
     fb.Offset offset_variantField_30;
     fb.Offset offset_variantField_14;
     fb.Offset offset_variantField_20;
+    fb.Offset offset_variantField_35;
     fb.Offset offset_variantField_22;
     fb.Offset offset_variantField_32;
     if (_variantField_24 != null) {
@@ -11796,6 +11814,9 @@
     if (_variantField_20 != null) {
       offset_variantField_20 = fbBuilder.writeString(_variantField_20);
     }
+    if (_variantField_35 != null) {
+      offset_variantField_35 = _variantField_35.finish(fbBuilder);
+    }
     if (_variantField_22 != null) {
       offset_variantField_22 = fbBuilder.writeString(_variantField_22);
     }
@@ -11904,6 +11925,9 @@
     if (_variantField_31 == true) {
       fbBuilder.addBool(31, true);
     }
+    if (offset_variantField_35 != null) {
+      fbBuilder.addOffset(35, offset_variantField_35);
+    }
     if (offset_variantField_22 != null) {
       fbBuilder.addOffset(22, offset_variantField_22);
     }
@@ -11963,6 +11987,7 @@
   idl.LinkedNodeKind _kind;
   String _variantField_20;
   bool _variantField_31;
+  idl.TopLevelInferenceError _variantField_35;
   String _variantField_22;
   idl.LinkedNodeVariablesDeclaration _variantField_32;
 
@@ -15591,6 +15616,14 @@
   }
 
   @override
+  idl.TopLevelInferenceError get topLevelTypeInferenceError {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_35 ??= const _TopLevelInferenceErrorReader()
+        .vTableGet(_bc, _bcOffset, 35, null);
+    return _variantField_35;
+  }
+
+  @override
   String get uriBasedDirective_uriContent {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective ||
@@ -15865,6 +15898,9 @@
         _result["variableDeclaration_name"] = variableDeclaration_name.toJson();
       if (codeLength != 0) _result["codeLength"] = codeLength;
       if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (topLevelTypeInferenceError != null)
+        _result["topLevelTypeInferenceError"] =
+            topLevelTypeInferenceError.toJson();
       if (variableDeclaration_declaration != null)
         _result["variableDeclaration_declaration"] =
             variableDeclaration_declaration.toJson();
@@ -17518,6 +17554,7 @@
         "codeOffset": codeOffset,
         "isSynthetic": isSynthetic,
         "kind": kind,
+        "topLevelTypeInferenceError": topLevelTypeInferenceError,
         "variableDeclaration_declaration": variableDeclaration_declaration,
       };
     }
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index d318669..a3cb2fc 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1935,6 +1935,8 @@
 
   variantField_31:bool (id: 31);
 
+  variantField_35:TopLevelInferenceError (id: 35);
+
   variantField_22:string (id: 22);
 
   variantField_32:LinkedNodeVariablesDeclaration (id: 32);
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index f1468b1..805f155 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -2211,6 +2211,11 @@
   @VariantId(15, variant: LinkedNodeKind.throwExpression)
   int get throwExpression_throwKeyword;
 
+  @VariantId(35, variantList: [
+    LinkedNodeKind.variableDeclaration,
+  ])
+  TopLevelInferenceError get topLevelTypeInferenceError;
+
   @VariantId(15, variant: LinkedNodeKind.topLevelVariableDeclaration)
   int get topLevelVariableDeclaration_semicolon;
 
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index ef1534c..df53896 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -1267,6 +1267,7 @@
       variableDeclaration_name: node.name.accept(this),
       variableDeclaration_declaration: _variablesDeclaration,
     );
+    builder.topLevelTypeInferenceError = LazyAst.getTypeInferenceError(node);
     _writeActualType(builder, node);
     return builder;
   }
diff --git a/pkg/analyzer/lib/src/summary2/lazy_ast.dart b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
index 773b59f..1f7ab615 100644
--- a/pkg/analyzer/lib/src/summary2/lazy_ast.dart
+++ b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
@@ -14,6 +14,7 @@
   static const _hasOverrideInferenceKey = 'lazyAst_hasOverrideInference';
   static const _isSimplyBoundedKey = 'lazyAst_simplyBounded';
   static const _returnTypeKey = 'lazyAst_returnType';
+  static const _typeInferenceErrorKey = 'lazyAst_typeInferenceError';
   static const _typeKey = 'lazyAst_type';
 
   final LinkedNode data;
@@ -28,6 +29,10 @@
     return node.getProperty(_typeKey);
   }
 
+  static TopLevelInferenceError getTypeInferenceError(AstNode node) {
+    return node.getProperty(_typeInferenceErrorKey);
+  }
+
   static bool hasOverrideInferenceDone(AstNode node) {
     return node.getProperty(_hasOverrideInferenceKey) ?? false;
   }
@@ -51,6 +56,11 @@
   static void setType(AstNode node, DartType type) {
     node.setProperty(_typeKey, type);
   }
+
+  static void setTypeInferenceError(
+      AstNode node, TopLevelInferenceError error) {
+    node.setProperty(_typeInferenceErrorKey, error);
+  }
 }
 
 class LazyClassDeclaration {
@@ -1241,6 +1251,7 @@
 
   bool _hasInitializer = false;
   bool _hasType = false;
+  bool _hasTypeInferenceError = false;
 
   LazyVariableDeclaration(this.data);
 
@@ -1263,6 +1274,17 @@
     return LazyAst.getType(node);
   }
 
+  static TopLevelInferenceError getTypeInferenceError(
+      VariableDeclaration node) {
+    var lazy = get(node);
+    if (!lazy._hasTypeInferenceError) {
+      var error = lazy.data.topLevelTypeInferenceError;
+      LazyAst.setTypeInferenceError(node, error);
+      lazy._hasTypeInferenceError = true;
+    }
+    return LazyAst.getTypeInferenceError(node);
+  }
+
   static void readInitializer(
     AstBinaryReader reader,
     VariableDeclaration node,
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 86bc82a..ce18580 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -531,6 +531,14 @@
     }
   }
 
+  TopLevelInferenceError getTypeInferenceError(AstNode node) {
+    if (node is VariableDeclaration) {
+      return LazyVariableDeclaration.getTypeInferenceError(node);
+    } else {
+      return null;
+    }
+  }
+
   TypeAnnotation getTypeParameterBound(TypeParameter node) {
     LazyTypeParameter.readBound(_astReader, node);
     return node.bound;
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index d34a336..cb49b53 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -11,6 +11,8 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/link.dart' as graph
     show DependencyWalker, Node;
 import 'package:analyzer/src/summary2/ast_resolver.dart';
@@ -150,8 +152,27 @@
     isEvaluated = true;
   }
 
-  void markCircular() {
+  void markCircular(List<_InferenceNode> cycle) {
     LazyAst.setType(_node, DynamicTypeImpl.instance);
+
+    var cycleNames = Set<String>();
+    for (var inferenceNode in cycle) {
+      var node = inferenceNode._node;
+      if (node is VariableDeclaration) {
+        cycleNames.add(node.name.name);
+      } else {
+        cycleNames.add('<unknown>');
+      }
+    }
+
+    LazyAst.setTypeInferenceError(
+      _node,
+      TopLevelInferenceErrorBuilder(
+        kind: TopLevelInferenceErrorKind.dependencyCycle,
+        arguments: cycleNames.toList(),
+      ),
+    );
+
     isEvaluated = true;
   }
 
@@ -180,7 +201,7 @@
   @override
   void evaluateScc(List<_InferenceNode> scc) {
     for (var node in scc) {
-      node.markCircular();
+      node.markCircular(scc);
     }
   }
 
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 666393d..b7fff02 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -6535,21 +6535,12 @@
 var c = a + 3;
 var d = 4;
 ''');
-    if (isAstBasedSummary) {
-      checkElementText(library, r'''
-dynamic a;
-dynamic b;
-dynamic c;
-int d;
-''');
-    } else {
-      checkElementText(library, r'''
+    checkElementText(library, r'''
 dynamic a/*error: dependencyCycle*/;
 dynamic b/*error: dependencyCycle*/;
 dynamic c/*error: dependencyCycle*/;
 int d;
 ''');
-    }
   }
 
   test_inferred_type_is_typedef() async {