Rework type parameters, use correct enclosing element / reference.

R=brianwilkerson@google.com

Change-Id: I7b6300f0eb9e9361155190b08912f6017fe9aaef
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100522
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 150ed5a..56489ad 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -5570,10 +5570,12 @@
     if (linkedNode != null) {
       if (linkedNode is GenericTypeAlias) {
         var context = enclosingUnit.linkedContext;
+        var function = context.getGeneticTypeAliasFunction(linkedNode);
+        var reference = context.getGenericFunctionTypeReference(function);
         return _function = GenericFunctionTypeElementImpl.forLinkedNode(
           this,
-          reference.getChild('@function'),
-          context.getGeneticTypeAliasFunction(linkedNode),
+          reference,
+          function,
         );
       } else {
         return _function = GenericFunctionTypeElementImpl.forLinkedNode(
@@ -9519,11 +9521,14 @@
       if (typeParameters == null) {
         return _typeParameterElements = const [];
       }
+      var containerRef = reference.getChild('@typeParameter');
       return _typeParameterElements =
           typeParameters.typeParameters.map<TypeParameterElement>((node) {
-        TypeParameterElementImpl element = node.declaredElement;
-        element.enclosingElement = this;
-        return element;
+        var reference = containerRef.getChild(node.name.name);
+        if (reference.hasElementFor(node)) {
+          return reference.element as TypeParameterElement;
+        }
+        return TypeParameterElementImpl.forLinkedNode(this, reference, node);
       }).toList();
     }
 
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 4728ec1..7c95330 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -8642,12 +8642,6 @@
   }
 
   @override
-  int get typeParameter_id {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
   int get typeParameterList_rightBracket {
     assert(kind == idl.LinkedNodeKind.typeParameterList);
     return _variantField_16 ??= 0;
@@ -8981,12 +8975,6 @@
     _variantField_16 = value;
   }
 
-  set typeParameter_id(int value) {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
   set typeParameterList_rightBracket(int value) {
     assert(kind == idl.LinkedNodeKind.typeParameterList);
     assert(value == null || value >= 0);
@@ -10898,7 +10886,6 @@
     LinkedNodeBuilder typeParameter_bound,
     int typeParameter_extendsKeyword,
     LinkedNodeBuilder typeParameter_name,
-    int typeParameter_id,
     int codeLength,
     int codeOffset,
   })  : _kind = idl.LinkedNodeKind.typeParameter,
@@ -10907,7 +10894,6 @@
         _variantField_6 = typeParameter_bound,
         _variantField_15 = typeParameter_extendsKeyword,
         _variantField_7 = typeParameter_name,
-        _variantField_16 = typeParameter_id,
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset;
 
@@ -14964,14 +14950,6 @@
   }
 
   @override
-  int get typeParameter_id {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
   int get typeParameterList_rightBracket {
     assert(kind == idl.LinkedNodeKind.typeParameterList);
     _variantField_16 ??=
@@ -16687,7 +16665,6 @@
         _result["typeParameter_extendsKeyword"] = typeParameter_extendsKeyword;
       if (typeParameter_name != null)
         _result["typeParameter_name"] = typeParameter_name.toJson();
-      if (typeParameter_id != 0) _result["typeParameter_id"] = typeParameter_id;
       if (codeLength != 0) _result["codeLength"] = codeLength;
       if (codeOffset != 0) _result["codeOffset"] = codeOffset;
     }
@@ -18144,7 +18121,6 @@
         "typeParameter_bound": typeParameter_bound,
         "typeParameter_extendsKeyword": typeParameter_extendsKeyword,
         "typeParameter_name": typeParameter_name,
-        "typeParameter_id": typeParameter_id,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
         "isSynthetic": isSynthetic,
@@ -19376,6 +19352,7 @@
   int _interfaceClass;
   List<LinkedNodeTypeBuilder> _interfaceTypeArguments;
   idl.LinkedNodeTypeKind _kind;
+  int _typeParameterElement;
   int _typeParameterId;
 
   @override
@@ -19443,6 +19420,14 @@
   }
 
   @override
+  int get typeParameterElement => _typeParameterElement ??= 0;
+
+  set typeParameterElement(int value) {
+    assert(value == null || value >= 0);
+    this._typeParameterElement = value;
+  }
+
+  @override
   int get typeParameterId => _typeParameterId ??= 0;
 
   set typeParameterId(int value) {
@@ -19459,6 +19444,7 @@
       int interfaceClass,
       List<LinkedNodeTypeBuilder> interfaceTypeArguments,
       idl.LinkedNodeTypeKind kind,
+      int typeParameterElement,
       int typeParameterId})
       : _functionFormalParameters = functionFormalParameters,
         _functionReturnType = functionReturnType,
@@ -19468,6 +19454,7 @@
         _interfaceClass = interfaceClass,
         _interfaceTypeArguments = interfaceTypeArguments,
         _kind = kind,
+        _typeParameterElement = typeParameterElement,
         _typeParameterId = typeParameterId;
 
   /// Flush [informative] data recursively.
@@ -19509,6 +19496,7 @@
       }
     }
     signature.addInt(this._kind == null ? 0 : this._kind.index);
+    signature.addInt(this._typeParameterElement ?? 0);
     signature.addInt(this._typeParameterId ?? 0);
     signature.addInt(this._genericTypeAliasReference ?? 0);
     if (this._genericTypeAliasTypeArguments == null) {
@@ -19561,10 +19549,10 @@
       fbBuilder.addOffset(2, offset_functionTypeParameters);
     }
     if (_genericTypeAliasReference != null && _genericTypeAliasReference != 0) {
-      fbBuilder.addUint32(7, _genericTypeAliasReference);
+      fbBuilder.addUint32(8, _genericTypeAliasReference);
     }
     if (offset_genericTypeAliasTypeArguments != null) {
-      fbBuilder.addOffset(8, offset_genericTypeAliasTypeArguments);
+      fbBuilder.addOffset(9, offset_genericTypeAliasTypeArguments);
     }
     if (_interfaceClass != null && _interfaceClass != 0) {
       fbBuilder.addUint32(3, _interfaceClass);
@@ -19575,8 +19563,11 @@
     if (_kind != null && _kind != idl.LinkedNodeTypeKind.bottom) {
       fbBuilder.addUint8(5, _kind.index);
     }
+    if (_typeParameterElement != null && _typeParameterElement != 0) {
+      fbBuilder.addUint32(6, _typeParameterElement);
+    }
     if (_typeParameterId != null && _typeParameterId != 0) {
-      fbBuilder.addUint32(6, _typeParameterId);
+      fbBuilder.addUint32(7, _typeParameterId);
     }
     return fbBuilder.endTable();
   }
@@ -19606,6 +19597,7 @@
   int _interfaceClass;
   List<idl.LinkedNodeType> _interfaceTypeArguments;
   idl.LinkedNodeTypeKind _kind;
+  int _typeParameterElement;
   int _typeParameterId;
 
   @override
@@ -19638,7 +19630,7 @@
   @override
   int get genericTypeAliasReference {
     _genericTypeAliasReference ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 7, 0);
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 8, 0);
     return _genericTypeAliasReference;
   }
 
@@ -19646,7 +19638,7 @@
   List<idl.LinkedNodeType> get genericTypeAliasTypeArguments {
     _genericTypeAliasTypeArguments ??=
         const fb.ListReader<idl.LinkedNodeType>(const _LinkedNodeTypeReader())
-            .vTableGet(_bc, _bcOffset, 8, const <idl.LinkedNodeType>[]);
+            .vTableGet(_bc, _bcOffset, 9, const <idl.LinkedNodeType>[]);
     return _genericTypeAliasTypeArguments;
   }
 
@@ -19672,9 +19664,16 @@
   }
 
   @override
+  int get typeParameterElement {
+    _typeParameterElement ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 6, 0);
+    return _typeParameterElement;
+  }
+
+  @override
   int get typeParameterId {
     _typeParameterId ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 6, 0);
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 7, 0);
     return _typeParameterId;
   }
 }
@@ -19703,6 +19702,8 @@
           interfaceTypeArguments.map((_value) => _value.toJson()).toList();
     if (kind != idl.LinkedNodeTypeKind.bottom)
       _result["kind"] = kind.toString().split('.')[1];
+    if (typeParameterElement != 0)
+      _result["typeParameterElement"] = typeParameterElement;
     if (typeParameterId != 0) _result["typeParameterId"] = typeParameterId;
     return _result;
   }
@@ -19717,6 +19718,7 @@
         "interfaceClass": interfaceClass,
         "interfaceTypeArguments": interfaceTypeArguments,
         "kind": kind,
+        "typeParameterElement": typeParameterElement,
         "typeParameterId": typeParameterId,
       };
 
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index f0c47f5..79b5645 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1990,9 +1990,9 @@
 
   functionTypeParameters:[LinkedNodeTypeTypeParameter] (id: 2);
 
-  genericTypeAliasReference:uint (id: 7);
+  genericTypeAliasReference:uint (id: 8);
 
-  genericTypeAliasTypeArguments:[LinkedNodeType] (id: 8);
+  genericTypeAliasTypeArguments:[LinkedNodeType] (id: 9);
 
   /// Reference to a [LinkedNodeReferences].
   interfaceClass:uint (id: 3);
@@ -2001,7 +2001,9 @@
 
   kind:LinkedNodeTypeKind (id: 5);
 
-  typeParameterId:uint (id: 6);
+  typeParameterElement:uint (id: 6);
+
+  typeParameterId:uint (id: 7);
 }
 
 /// Information about a formal parameter in a function type.
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 9e4e165..94d4562 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -2300,9 +2300,6 @@
   @VariantId(15, variant: LinkedNodeKind.typeParameter)
   int get typeParameter_extendsKeyword;
 
-  @VariantId(16, variant: LinkedNodeKind.typeParameter)
-  int get typeParameter_id;
-
   @VariantId(7, variant: LinkedNodeKind.typeParameter)
   LinkedNode get typeParameter_name;
 
@@ -2586,10 +2583,10 @@
   @Id(2)
   List<LinkedNodeTypeTypeParameter> get functionTypeParameters;
 
-  @Id(7)
+  @Id(8)
   int get genericTypeAliasReference;
 
-  @Id(8)
+  @Id(9)
   List<LinkedNodeType> get genericTypeAliasTypeArguments;
 
   /// Reference to a [LinkedNodeReferences].
@@ -2603,6 +2600,9 @@
   LinkedNodeTypeKind get kind;
 
   @Id(6)
+  int get typeParameterElement;
+
+  @Id(7)
   int get typeParameterId;
 }
 
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 7d90ebf..d1b63be 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -1211,7 +1211,6 @@
       _readNodeLazy(data.typeParameter_bound),
     );
     LazyTypeParameter.setData(node, data);
-    _unitContext.addTypeParameter(data.typeParameter_id, node);
     return node;
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index c58457b..b76fe42 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -640,8 +640,7 @@
     );
     _writeActualReturnType(builder, node);
 
-    var element = (node as GenericFunctionTypeImpl).declaredElement;
-    var id = _linkingContext.idOfGenericFunctionType(element);
+    var id = LazyAst.getGenericFunctionTypeId(node);
     builder.genericFunctionType_id = id;
 
     return builder;
@@ -1256,10 +1255,6 @@
         typeParameter_name: node.name.accept(this));
     _storeDeclaration(builder, node);
     _storeCodeOffsetLength(builder, node);
-
-    var id = _linkingContext.idOfTypeParameter(node.declaredElement);
-    builder.typeParameter_id = id;
-
     return builder;
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/declaration_splicer.dart b/pkg/analyzer/lib/src/summary2/declaration_splicer.dart
index 14a9370..468fb19 100644
--- a/pkg/analyzer/lib/src/summary2/declaration_splicer.dart
+++ b/pkg/analyzer/lib/src/summary2/declaration_splicer.dart
@@ -182,6 +182,7 @@
     (partial.functionExpression as FunctionExpressionImpl).declaredElement =
         element;
     _metadata(partial.metadata, element);
+    _node(full.returnType, partial.returnType);
   }
 
   void _functionExpression(
@@ -264,6 +265,7 @@
       partial.body = _body(full.body);
     });
     _metadata(partial.metadata, element);
+    _node(full.returnType, partial.returnType);
   }
 
   void _mixinDeclaration(MixinDeclaration full, MixinDeclaration partial) {
@@ -378,6 +380,7 @@
     _match(partial.identifier, element);
     (partial as SimpleFormalParameterImpl).declaredElement = element;
     _metadata(partial.metadata, element);
+    _node(full.type, partial.type);
   }
 
   void _topLevelVariableDeclaration(
@@ -432,6 +435,8 @@
     VariableDeclarationList full,
     VariableDeclarationList partial,
   ) {
+    _node(full.type, partial.type);
+
     var fullList = full.variables;
     var partialList = partial.variables;
     for (var i = 0; i < fullList.length; ++i) {
diff --git a/pkg/analyzer/lib/src/summary2/lazy_ast.dart b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
index 2eaaddd..f7153cb 100644
--- a/pkg/analyzer/lib/src/summary2/lazy_ast.dart
+++ b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
@@ -11,6 +11,7 @@
 /// Accessor for reading AST lazily, or read data that is stored in IDL, but
 /// cannot be stored in AST, like inferred types.
 class LazyAst {
+  static const _genericFunctionTypeIdKey = 'lazyAst_genericFunctionTypeId';
   static const _hasOverrideInferenceKey = 'lazyAst_hasOverrideInference';
   static const _inheritsCovariantKey = 'lazyAst_isCovariant';
   static const _isSimplyBoundedKey = 'lazyAst_simplyBounded';
@@ -22,6 +23,10 @@
 
   LazyAst(this.data);
 
+  static int getGenericFunctionTypeId(GenericFunctionType node) {
+    return node.getProperty(_genericFunctionTypeIdKey);
+  }
+
   static bool getInheritsCovariant(AstNode node) {
     return node.getProperty(_inheritsCovariantKey) ?? false;
   }
@@ -46,6 +51,10 @@
     return node.getProperty(_isSimplyBoundedKey);
   }
 
+  static void setGenericFunctionTypeId(GenericFunctionType node, int id) {
+    node.setProperty(_genericFunctionTypeIdKey, id);
+  }
+
   static void setInheritsCovariant(AstNode node, bool value) {
     node.setProperty(_inheritsCovariantKey, value);
   }
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index e6dab46..0dffc38 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -179,6 +179,13 @@
       return _typeAlias(unit, reference);
     }
 
+    if (parentName == '@typeParameter') {
+      var enclosing = elementOfReference(parent2);
+      (enclosing as TypeParameterizedElement).typeParameters;
+      assert(reference.element != null);
+      return reference.element;
+    }
+
     if (parentName == '@unit') {
       elementOfReference(parent2);
       // Creating a library fills all its units.
@@ -204,6 +211,12 @@
       assert(reference.element != null);
       return reference.element;
     }
+    if (enclosing is EnumElementImpl) {
+      enclosing.accessors;
+      // Requesting accessors sets elements for accessors and variables.
+      assert(reference.element != null);
+      return reference.element;
+    }
     // Only classes and units have accessors.
     throw StateError('${enclosing.runtimeType}');
   }
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index b403308..2d39d37 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -35,10 +35,7 @@
   /// Mapping from identifiers to elements for generic function types.
   final Map<int, GenericFunctionTypeElementImpl> _genericFunctionTypes = {};
 
-  /// Mapping from identifiers to real or synthetic type parameters.
-  ///
-  /// Real type parameters have corresponding [TypeParameter] nodes, and are
-  /// referenced from other AST nodes.
+  /// Mapping from identifiers to synthetic type parameters.
   ///
   /// Synthetic type parameters are added when [readType] begins reading a
   /// [FunctionType], and removed when reading is done.
@@ -92,6 +89,8 @@
   void addGenericFunctionType(int id, GenericFunctionTypeImpl node) {
     if (this.reference == null) return;
 
+    LazyAst.setGenericFunctionTypeId(node, id);
+
     var element = _genericFunctionTypes[id];
     if (element == null) {
       element = GenericFunctionTypeElementImpl.forLinkedNode(
@@ -110,26 +109,6 @@
     element.reference = reference;
   }
 
-  /// Every [TypeParameter] node has [TypeParameterElement], which is created
-  /// during reading of this node. All type parameter nodes are read before
-  /// any nodes that reference them (bounds are read lazily later).
-  void addTypeParameter(int id, TypeParameter node) {
-    if (this.reference == null) return;
-
-    var element = _typeParameters[id];
-    if (element == null) {
-      element = TypeParameterElementImpl.forLinkedNode(null, null, node);
-      _typeParameters[id] = element;
-    }
-
-    node.name.staticElement = element;
-
-    var containerRef = this.reference.getChild('@typeParameter');
-    var reference = containerRef.getChild('$id');
-    reference.element = element;
-    element.reference = reference;
-  }
-
   /// Return the [LibraryElement] referenced in the [node].
   LibraryElement directiveLibrary(UriBasedDirective node) {
     var uriStr = LazyDirective.getSelectedUri(node);
@@ -358,6 +337,11 @@
 //    }
   }
 
+  Reference getGenericFunctionTypeReference(GenericFunctionType node) {
+    var id = LazyAst.getGenericFunctionTypeId(node);
+    return reference.getChild('@genericFunctionType').getChild('$id');
+  }
+
   GenericFunctionType getGeneticTypeAliasFunction(GenericTypeAlias node) {
     LazyGenericTypeAlias.readFunctionType(_astReader, node);
     return node.functionType;
@@ -943,9 +927,15 @@
       );
     } else if (kind == LinkedNodeTypeKind.typeParameter) {
       var id = linkedType.typeParameterId;
-      var element = _typeParameters[id];
-      assert(element != null);
-      return TypeParameterTypeImpl(element);
+      if (id != 0) {
+        var element = _typeParameters[id];
+        assert(element != null);
+        return TypeParameterTypeImpl(element);
+      } else {
+        var index = linkedType.typeParameterElement;
+        var element = bundleContext.elementOfIndex(index);
+        return TypeParameterTypeImpl(element);
+      }
     } else if (kind == LinkedNodeTypeKind.void_) {
       return VoidTypeImpl.instance;
     } else {
@@ -970,7 +960,6 @@
     var context = LinkedUnitContext._(bundleContext, libraryContext,
         indexInLibrary, uriStr, reference, data, TokensContext(data.tokens));
     context._genericFunctionTypes.addAll(_genericFunctionTypes);
-    context._typeParameters.addAll(_typeParameters);
     var astReader = AstBinaryReader(context);
     return astReader.readNode(data.node);
   }
@@ -1198,9 +1187,6 @@
     for (var typeParameter in typeParameters.typeParameters) {
       var bound = context.getTypeParameterBound(typeParameter);
       read(bound);
-
-      TypeParameterElementImpl element = typeParameter.declaredElement;
-      element.enclosingElement = context.reference.element;
     }
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
index 321ab6b..90ea6df 100644
--- a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
@@ -31,7 +31,6 @@
   );
 
   final Map<TypeParameterElement, int> _typeParameters = Map.identity();
-  int _nextTypeParameterId = 1;
   int _nextSyntheticTypeParameterId = 0x10000;
 
   final Map<GenericFunctionTypeElement, int> _genericFunctionTypes =
@@ -40,18 +39,6 @@
 
   LinkingBundleContext(this.dynamicReference);
 
-  int addGenericFunctionType(GenericFunctionTypeElement element) {
-    var id = _nextGenericFunctionTypeId++;
-    _genericFunctionTypes[element] = id;
-    return id;
-  }
-
-  int addTypeParameter(TypeParameterElement element) {
-    var id = _nextTypeParameterId++;
-    _typeParameters[element] = id;
-    return id;
-  }
-
   int idOfGenericFunctionType(GenericFunctionTypeElement element) {
     return _genericFunctionTypes[element];
   }
@@ -86,6 +73,10 @@
     return reference.index;
   }
 
+  int nextGenericFunctionTypeId() {
+    return _nextGenericFunctionTypeId++;
+  }
+
   LinkedNodeTypeBuilder writeType(DartType type) {
     if (type == null) return null;
 
@@ -107,10 +98,19 @@
       );
     } else if (type is TypeParameterType) {
       TypeParameterElementImpl element = type.element;
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.typeParameter,
-        typeParameterId: _typeParameters[element],
-      );
+      var id = _typeParameters[element];
+      if (id != null) {
+        return LinkedNodeTypeBuilder(
+          kind: LinkedNodeTypeKind.typeParameter,
+          typeParameterId: id,
+        );
+      } else {
+        var index = indexOfElement(element);
+        return LinkedNodeTypeBuilder(
+          kind: LinkedNodeTypeKind.typeParameter,
+          typeParameterElement: index,
+        );
+      }
     } else if (type is VoidType) {
       return LinkedNodeTypeBuilder(
         kind: LinkedNodeTypeKind.void_,
diff --git a/pkg/analyzer/lib/src/summary2/reference.dart b/pkg/analyzer/lib/src/summary2/reference.dart
index 099c8b8..95c0ae7 100644
--- a/pkg/analyzer/lib/src/summary2/reference.dart
+++ b/pkg/analyzer/lib/src/summary2/reference.dart
@@ -71,8 +71,6 @@
 
   bool get isTypeAlias => parent != null && parent.name == '@typeAlias';
 
-  int get numOfChildren => _children != null ? _children.length : 0;
-
   /// Return the child with the given name, or `null` if does not exist.
   Reference operator [](String name) {
     return _children != null ? _children[name] : null;
@@ -92,7 +90,7 @@
     if (element != null && node2 == node) {
       return true;
     } else {
-      if (node == null) {
+      if (node2 == null) {
         node2 = node;
       }
       return false;
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index b652053..13d0e39 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/lazy_ast.dart';
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/linking_bundle_context.dart';
 import 'package:analyzer/src/summary2/linking_node_scope.dart';
@@ -540,13 +541,13 @@
     var name = node.name.name;
     reference = reference.getChild('@class').getChild(name);
 
-    _createTypeParameterElements(node.typeParameters);
     var element = ClassElementImpl.forLinkedNode(
       outerReference.element,
       reference,
       node,
     );
     node.name.staticElement = element;
+    _createTypeParameterElements(node.typeParameters);
     scope = new TypeParameterScope(scope, element);
     scope = new ClassScope(scope, element);
     LinkingNodeContext(node, scope);
@@ -570,13 +571,13 @@
     var name = node.name.name;
     reference = reference.getChild('@class').getChild(name);
 
-    _createTypeParameterElements(node.typeParameters);
     var element = ClassElementImpl.forLinkedNode(
       outerReference.element,
       reference,
       node,
     );
     node.name.staticElement = element;
+    _createTypeParameterElements(node.typeParameters);
     scope = new TypeParameterScope(scope, element);
     scope = new ClassScope(scope, element);
     LinkingNodeContext(node, scope);
@@ -661,13 +662,13 @@
     var name = node.name.name;
     reference = reference.getChild('@function').getChild(name);
 
-    _createTypeParameterElements(node.functionExpression.typeParameters);
     var element = FunctionElementImpl.forLinkedNode(
       outerReference.element,
       reference,
       node,
     );
     node.name.staticElement = element;
+    _createTypeParameterElements(node.functionExpression.typeParameters);
     scope = new FunctionScope(scope, element);
     LinkingNodeContext(node, scope);
 
@@ -693,13 +694,13 @@
     var name = node.name.name;
     reference = reference.getChild('@typeAlias').getChild(name);
 
-    _createTypeParameterElements(node.typeParameters);
     var element = GenericTypeAliasElementImpl.forLinkedNode(
       outerReference.element,
       reference,
       node,
     );
     node.name.staticElement = element;
+    _createTypeParameterElements(node.typeParameters);
     scope = FunctionTypeScope(outerScope, element);
 
     node.returnType?.accept(this);
@@ -725,23 +726,25 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = '${outerReference.numOfChildren}';
-    reference = reference.getChild(name);
+    var id = linkingContext.nextGenericFunctionTypeId();
+    LazyAst.setGenericFunctionTypeId(node, id);
 
-    _createGenericFunctionTypeElement(node);
-    _createTypeParameterElements(node.typeParameters);
+    var containerRef = unitReference.getChild('@genericFunctionType');
+    reference = containerRef.getChild('$id');
+
     var element = GenericFunctionTypeElementImpl.forLinkedNode(
-      outerReference.element,
+      unitReference.element,
       reference,
       node,
     );
+    (node as GenericFunctionTypeImpl).declaredElement = element;
+    _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(outerScope, element);
 
     node.returnType?.accept(this);
     node.typeParameters?.accept(this);
     node.parameters.accept(this);
     nodesToBuildType.add(node);
-    nodesToBuildType.add(node);
 
     scope = outerScope;
     reference = outerReference;
@@ -755,13 +758,13 @@
     var name = node.name.name;
     reference = reference.getChild('@typeAlias').getChild(name);
 
-    _createTypeParameterElements(node.typeParameters);
     var element = GenericTypeAliasElementImpl.forLinkedNode(
       outerReference.element,
       reference,
       node,
     );
     node.name.staticElement = element;
+    _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(outerScope, element);
 
     node.typeParameters?.accept(this);
@@ -785,13 +788,13 @@
     var name = node.name.name;
     reference = reference.getChild('@method').getChild(name);
 
-    _createTypeParameterElements(node.typeParameters);
     var element = MethodElementImpl.forLinkedNode(
       outerReference.element,
       reference,
       node,
     );
     node.name.staticElement = element;
+    _createTypeParameterElements(node.typeParameters);
     scope = new FunctionScope(scope, element);
     LinkingNodeContext(node, scope);
 
@@ -810,15 +813,15 @@
     var outerReference = reference;
 
     var name = node.name.name;
-    reference = reference.getChild('@class').getChild(name);
+    reference = reference.getChild('@mixin').getChild(name);
 
-    _createTypeParameterElements(node.typeParameters);
     var element = ClassElementImpl.forLinkedNode(
       outerReference.element,
       reference,
       node,
     );
     node.name.staticElement = element;
+    _createTypeParameterElements(node.typeParameters);
     scope = new TypeParameterScope(scope, element);
     scope = new ClassScope(scope, element);
     LinkingNodeContext(node, scope);
@@ -896,33 +899,17 @@
     node.mixinTypes.accept(this);
   }
 
-  void _createGenericFunctionTypeElement(GenericFunctionTypeImpl node) {
-    var element =
-        GenericFunctionTypeElementImpl.forLinkedNode(null, null, node);
-    var id = linkingContext.addGenericFunctionType(element);
-
-    // Each element that might be referenced should have a Reference.
-    // While GenericFunctionType itself does not have a name, so cannot be
-    // referenced itself, it hosts other elements, such as formal parameters,
-    // that can be referenced.
-    var containerRef = unitReference.getChild('@genericFunctionType');
-    var reference = containerRef.getChild('$id');
-    reference.element = element;
-    element.reference = reference;
-
-    node.declaredElement = element;
-  }
-
   void _createTypeParameterElement(TypeParameter node) {
-    var element = TypeParameterElementImpl.forLinkedNode(null, null, node);
-    var id = linkingContext.addTypeParameter(element);
+    var outerReference = this.reference;
+    var containerRef = outerReference.getChild('@typeParameter');
+    var reference = containerRef.getChild(node.name.name);
+    reference.node2 = node;
 
-    // Each element that might be referenced should have a Reference.
-    var containerRef = unitReference.getChild('@typeParameter');
-    var reference = containerRef.getChild('$id');
-    reference.element = element;
-    element.reference = reference;
-
+    var element = TypeParameterElementImpl.forLinkedNode(
+      outerReference.element,
+      reference,
+      node,
+    );
     node.name.staticElement = element;
   }