Record GenericFunctionType nodes separately in the unit.

This fixes most failures related to them.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: Icbd9eac52159064d5ffc43a4b30b75589a089a94
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/102480
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index f317b8f..aa4e55d 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -5585,11 +5585,7 @@
         var function = context.getGeneticTypeAliasFunction(linkedNode);
         if (function != null) {
           var reference = context.getGenericFunctionTypeReference(function);
-          return _function = GenericFunctionTypeElementImpl.forLinkedNode(
-            this,
-            reference,
-            function,
-          );
+          return _function = reference.element;
         } else {
           return null;
         }
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index dd07cce..ac587ca 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/exception/exception.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -31,6 +32,10 @@
   /// element model.
   ElementWalker _walker;
 
+  /// The number of [GenericFunctionType] nodes that we encountered so far.
+  /// We use it to request the corresponding resolved node.
+  int _nextGenericFunctionTypeId = 0;
+
   DeclarationResolver();
 
   /// Resolve the declarations within the given compilation [unit] to the
@@ -269,15 +274,21 @@
     if (_walker.elementBuilder != null) {
       _walker.elementBuilder.visitGenericFunctionType(node);
     } else {
-      DartType type = node.type;
-      if (type != null) {
-        Element element = type.element;
-        if (element is GenericFunctionTypeElement) {
-          _setGenericFunctionType(node.returnType, element.returnType);
-          _walk(new ElementWalker.forGenericFunctionType(element), () {
-            super.visitGenericFunctionType(node);
-          });
-        }
+      Element element;
+      if (AnalysisDriver.useSummary2) {
+        var id = _nextGenericFunctionTypeId++;
+        var context = _enclosingUnit.linkedContext;
+        var linkedNode = context.getGenericFunctionType(id);
+        element = linkedNode.declaredElement;
+        (node as GenericFunctionTypeImpl).declaredElement = element;
+      } else {
+        element = node.type?.element;
+      }
+      if (element is GenericFunctionTypeElement) {
+        _setGenericFunctionType(node.returnType, element.returnType);
+        _walk(new ElementWalker.forGenericFunctionType(element), () {
+          super.visitGenericFunctionType(node);
+        });
       }
     }
   }
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index f68e202..6792bc6 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -5313,7 +5313,7 @@
       return;
     }
     if (type is ParameterizedType) {
-      var element = type.element;
+      var element = typeName.name.staticElement;
       // prepare type parameters
       List<TypeParameterElement> parameterElements;
       if (element is ClassElement) {
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 0f0f93e..68e2d88 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -15257,6 +15257,7 @@
 class LinkedNodeUnitBuilder extends Object
     with _LinkedNodeUnitMixin
     implements idl.LinkedNodeUnit {
+  List<LinkedNodeBuilder> _genericFunctionTypes;
   bool _isSynthetic;
   List<int> _lineStarts;
   LinkedNodeBuilder _node;
@@ -15264,6 +15265,20 @@
   String _uriStr;
 
   @override
+  List<LinkedNodeBuilder> get genericFunctionTypes =>
+      _genericFunctionTypes ??= <LinkedNodeBuilder>[];
+
+  /// All generic function types in the unit - in generic type aliases, or used
+  /// directly as type annotations.
+  ///
+  /// They are requested in two cases: when we are reading a node that contains
+  /// them (e.g. a return type of a method), or when we run over unresolved
+  /// AST in declaration resolver.
+  set genericFunctionTypes(List<LinkedNodeBuilder> value) {
+    this._genericFunctionTypes = value;
+  }
+
+  @override
   bool get isSynthetic => _isSynthetic ??= false;
 
   set isSynthetic(bool value) {
@@ -15301,12 +15316,14 @@
   }
 
   LinkedNodeUnitBuilder(
-      {bool isSynthetic,
+      {List<LinkedNodeBuilder> genericFunctionTypes,
+      bool isSynthetic,
       List<int> lineStarts,
       LinkedNodeBuilder node,
       UnlinkedTokensBuilder tokens,
       String uriStr})
-      : _isSynthetic = isSynthetic,
+      : _genericFunctionTypes = genericFunctionTypes,
+        _isSynthetic = isSynthetic,
         _lineStarts = lineStarts,
         _node = node,
         _tokens = tokens,
@@ -15314,6 +15331,7 @@
 
   /// Flush [informative] data recursively.
   void flushInformative() {
+    _genericFunctionTypes?.forEach((b) => b.flushInformative());
     _lineStarts = null;
     _node?.flushInformative();
     _tokens?.flushInformative();
@@ -15327,13 +15345,26 @@
     signature.addBool(this._node != null);
     this._node?.collectApiSignature(signature);
     signature.addBool(this._isSynthetic == true);
+    if (this._genericFunctionTypes == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._genericFunctionTypes.length);
+      for (var x in this._genericFunctionTypes) {
+        x?.collectApiSignature(signature);
+      }
+    }
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_genericFunctionTypes;
     fb.Offset offset_lineStarts;
     fb.Offset offset_node;
     fb.Offset offset_tokens;
     fb.Offset offset_uriStr;
+    if (!(_genericFunctionTypes == null || _genericFunctionTypes.isEmpty)) {
+      offset_genericFunctionTypes = fbBuilder.writeList(
+          _genericFunctionTypes.map((b) => b.finish(fbBuilder)).toList());
+    }
     if (!(_lineStarts == null || _lineStarts.isEmpty)) {
       offset_lineStarts = fbBuilder.writeListUint32(_lineStarts);
     }
@@ -15347,6 +15378,9 @@
       offset_uriStr = fbBuilder.writeString(_uriStr);
     }
     fbBuilder.startTable();
+    if (offset_genericFunctionTypes != null) {
+      fbBuilder.addOffset(5, offset_genericFunctionTypes);
+    }
     if (_isSynthetic == true) {
       fbBuilder.addBool(3, true);
     }
@@ -15382,6 +15416,7 @@
 
   _LinkedNodeUnitImpl(this._bc, this._bcOffset);
 
+  List<idl.LinkedNode> _genericFunctionTypes;
   bool _isSynthetic;
   List<int> _lineStarts;
   idl.LinkedNode _node;
@@ -15389,6 +15424,14 @@
   String _uriStr;
 
   @override
+  List<idl.LinkedNode> get genericFunctionTypes {
+    _genericFunctionTypes ??=
+        const fb.ListReader<idl.LinkedNode>(const _LinkedNodeReader())
+            .vTableGet(_bc, _bcOffset, 5, const <idl.LinkedNode>[]);
+    return _genericFunctionTypes;
+  }
+
+  @override
   bool get isSynthetic {
     _isSynthetic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
     return _isSynthetic;
@@ -15425,6 +15468,9 @@
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
+    if (genericFunctionTypes.isNotEmpty)
+      _result["genericFunctionTypes"] =
+          genericFunctionTypes.map((_value) => _value.toJson()).toList();
     if (isSynthetic != false) _result["isSynthetic"] = isSynthetic;
     if (lineStarts.isNotEmpty) _result["lineStarts"] = lineStarts;
     if (node != null) _result["node"] = node.toJson();
@@ -15435,6 +15481,7 @@
 
   @override
   Map<String, Object> toMap() => {
+        "genericFunctionTypes": genericFunctionTypes,
         "isSynthetic": isSynthetic,
         "lineStarts": lineStarts,
         "node": node,
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 6c25f34..ba6a1ed 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -2036,6 +2036,14 @@
 
 /// Information about a single library in a [LinkedNodeLibrary].
 table LinkedNodeUnit {
+  /// All generic function types in the unit - in generic type aliases, or used
+  /// directly as type annotations.
+  ///
+  /// They are requested in two cases: when we are reading a node that contains
+  /// them (e.g. a return type of a method), or when we run over unresolved
+  /// AST in declaration resolver.
+  genericFunctionTypes:[LinkedNode] (id: 5);
+
   isSynthetic:bool (id: 3);
 
   /// Offsets of the first character of each line in the source code.
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 2ed52fc..182acf6 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -1345,12 +1345,12 @@
   @VariantId(2, variant: LinkedNodeKind.implementsClause)
   List<LinkedNode> get implementsClause_interfaces;
 
-  @VariantId(15, variant: LinkedNodeKind.importDirective)
-  int get importDirective_prefixOffset;
-
   @VariantId(1, variant: LinkedNodeKind.importDirective)
   String get importDirective_prefix;
 
+  @VariantId(15, variant: LinkedNodeKind.importDirective)
+  int get importDirective_prefixOffset;
+
   @VariantId(15, variant: LinkedNodeKind.indexExpression)
   int get indexExpression_element;
 
@@ -1467,6 +1467,12 @@
   @Id(37)
   String get name;
 
+  @VariantId(6, variant: LinkedNodeKind.namedExpression)
+  LinkedNode get namedExpression_expression;
+
+  @VariantId(7, variant: LinkedNodeKind.namedExpression)
+  LinkedNode get namedExpression_name;
+
   @VariantId(16, variantList: [
     LinkedNodeKind.classDeclaration,
     LinkedNodeKind.classTypeAlias,
@@ -1489,12 +1495,6 @@
   ])
   int get nameOffset;
 
-  @VariantId(6, variant: LinkedNodeKind.namedExpression)
-  LinkedNode get namedExpression_expression;
-
-  @VariantId(7, variant: LinkedNodeKind.namedExpression)
-  LinkedNode get namedExpression_name;
-
   @VariantId(36, variantList: [
     LinkedNodeKind.hideCombinator,
     LinkedNodeKind.showCombinator,
@@ -2026,6 +2026,15 @@
 
 /// Information about a single library in a [LinkedNodeLibrary].
 abstract class LinkedNodeUnit extends base.SummaryClass {
+  /// All generic function types in the unit - in generic type aliases, or used
+  /// directly as type annotations.
+  ///
+  /// They are requested in two cases: when we are reading a node that contains
+  /// them (e.g. a return type of a method), or when we run over unresolved
+  /// AST in declaration resolver.
+  @Id(5)
+  List<LinkedNode> get genericFunctionTypes;
+
   @Id(3)
   bool get isSynthetic;
 
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 0725e93..266f80b 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -45,6 +45,21 @@
 
   InterfaceType get _stringType => _unitContext.typeProvider.stringType;
 
+  /// This method is invoked by [LinkedUnitContext] to perform actual reading.
+  GenericFunctionType readGenericFunctionType(LinkedNode data) {
+    GenericFunctionTypeImpl node = astFactory.genericFunctionType(
+      _readNodeLazy(data.genericFunctionType_returnType),
+      _Tokens.FUNCTION,
+      _readNode(data.genericFunctionType_typeParameters),
+      _readNodeLazy(data.genericFunctionType_formalParameters),
+      question:
+          AstBinaryFlags.hasQuestion(data.flags) ? _Tokens.QUESTION : null,
+    );
+    node.type = _readType(data.genericFunctionType_type);
+    LazyGenericFunctionType.setData(node, data);
+    return node;
+  }
+
   AstNode readNode(LinkedNode data) {
     timerAstBinaryReader.start();
     try {
@@ -761,18 +776,8 @@
   }
 
   GenericFunctionType _read_genericFunctionType(LinkedNode data) {
-    GenericFunctionTypeImpl node = astFactory.genericFunctionType(
-      _readNodeLazy(data.genericFunctionType_returnType),
-      _Tokens.FUNCTION,
-      _readNode(data.genericFunctionType_typeParameters),
-      _readNodeLazy(data.genericFunctionType_formalParameters),
-      question:
-          AstBinaryFlags.hasQuestion(data.flags) ? _Tokens.QUESTION : null,
-    );
-    node.type = _readType(data.genericFunctionType_type);
-    LazyGenericFunctionType.setData(node, data);
-    _unitContext.addGenericFunctionType(data.genericFunctionType_id, node);
-    return node;
+    var id = data.genericFunctionType_id;
+    return _unitContext.getGenericFunctionType(id);
   }
 
   GenericTypeAlias _read_genericTypeAlias(LinkedNode data) {
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index abc1356..dbbda96 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -28,6 +28,9 @@
 class AstBinaryWriter extends ThrowingAstVisitor<LinkedNodeBuilder> {
   final LinkingBundleContext _linkingContext;
 
+  /// The list stored [GenericFunctionType]s, as visited in depth-first order.
+  final List<LinkedNodeBuilder> genericFunctionTypes = [];
+
   /// This field is set temporary while visiting [FieldDeclaration] or
   /// [TopLevelVariableDeclaration] to store data shared among all variables
   /// in these declarations.
@@ -677,6 +680,10 @@
 
   @override
   LinkedNodeBuilder visitGenericFunctionType(GenericFunctionType node) {
+    var id = LazyAst.getGenericFunctionTypeId(node);
+    assert(genericFunctionTypes.length == id);
+    genericFunctionTypes.add(null);
+
     var builder = LinkedNodeBuilder.genericFunctionType(
       genericFunctionType_formalParameters: node.parameters.accept(this),
       genericFunctionType_returnType: node.returnType?.accept(this),
@@ -688,10 +695,12 @@
     );
     _writeActualReturnType(builder, node);
 
-    var id = LazyAst.getGenericFunctionTypeId(node);
     builder.genericFunctionType_id = id;
+    genericFunctionTypes[id] = builder;
 
-    return builder;
+    return LinkedNodeBuilder.genericFunctionType(
+      genericFunctionType_id: id,
+    );
   }
 
   @override
@@ -699,8 +708,8 @@
     timerAstBinaryWriterTypedef.start();
     try {
       var builder = LinkedNodeBuilder.genericTypeAlias(
-        genericTypeAlias_functionType: node.functionType?.accept(this),
         genericTypeAlias_typeParameters: node.typeParameters?.accept(this),
+        genericTypeAlias_functionType: node.functionType?.accept(this),
         typeAlias_hasSelfReference:
             LazyGenericTypeAlias.getHasSelfReference(node),
       );
@@ -1407,10 +1416,10 @@
     return builder;
   }
 
-  LinkedNodeBuilder writeNode(AstNode node) {
+  LinkedNodeBuilder writeUnit(CompilationUnit unit) {
     timerAstBinaryWriter.start();
     try {
-      return node.accept(this);
+      return unit.accept(this);
     } finally {
       timerAstBinaryWriter.stop();
     }
diff --git a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
index fb84bac..cb279c6 100644
--- a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
@@ -237,7 +237,6 @@
       var unitRef = reference.getChild('@unit');
       var unitReference = unitRef.getChild(unitContext.uriStr);
       var resolver = ReferenceResolver(
-        linker.linkingBundleContext,
         nodesToBuildType,
         linker.elementFactory,
         element,
diff --git a/pkg/analyzer/lib/src/summary2/declaration_splicer.dart b/pkg/analyzer/lib/src/summary2/declaration_splicer.dart
deleted file mode 100644
index f562b51..0000000
--- a/pkg/analyzer/lib/src/summary2/declaration_splicer.dart
+++ /dev/null
@@ -1,593 +0,0 @@
-// Copyright (c) 2019, 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.
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/element/builder.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-
-/// This class takes a [CompilationUnitElement] lazily resynthesized from a
-/// fully resolved, but partial AST (contains only APIs), and full unresolved
-/// AST - and splices them into a single AST with all declaration nodes
-/// fully resolved, and function bodies and variable initializers unresolved.
-///
-class DeclarationSplicer {
-  final CompilationUnitElementImpl _unitElement;
-
-  _ElementWalker _walker;
-
-  DeclarationSplicer(this._unitElement);
-
-  void splice(CompilationUnit full) {
-    var partialNode = _unitElement.linkedContext.readUnitEagerly();
-    _walk(_ElementWalker.forCompilationUnit(_unitElement), () {
-      _directives(full, partialNode);
-      _declarations(full, partialNode);
-    });
-  }
-
-  FunctionBody _body(FunctionBody full) {
-    _buildLocalElements(full);
-    return full;
-  }
-
-  void _buildLocalElements(AstNode node) {
-    if (node == null) return;
-
-    var holder = ElementHolder();
-    var elementBuilder = LocalElementBuilder(holder, _unitElement);
-    node.accept(elementBuilder);
-
-    ElementImpl element = _walker.element;
-    element.encloseElements(holder.functions);
-    element.encloseElements(holder.labels);
-    element.encloseElements(holder.localVariables);
-  }
-
-  void _classDeclaration(ClassDeclaration full, ClassDeclaration partial) {
-    var element = _walker.getClass();
-    _match(partial.name, element);
-    _walk(_ElementWalker.forClass(element), () {
-      _node(full.typeParameters, partial.typeParameters);
-      var fullList = full.members;
-      var partialList = partial.members;
-      for (var i = 0; i < fullList.length; ++i) {
-        _node(fullList[i], partialList[i]);
-      }
-    });
-    _metadata(partial.metadata, element);
-  }
-
-  void _classTypeAlias(ClassTypeAlias full, ClassTypeAlias partial) {
-    var element = _walker.getClass();
-    _match(partial.name, element);
-    _walk(_ElementWalker.forClass(element), () {
-      _node(full.typeParameters, partial.typeParameters);
-    });
-    _metadata(partial.metadata, element);
-  }
-
-  void _constructorDeclaration(
-    ConstructorDeclaration full,
-    ConstructorDeclaration partial,
-  ) {
-    var element = _walker.getConstructor();
-    _match(partial.name, element);
-    (partial as ConstructorDeclarationImpl).declaredElement = element;
-    _walk(_ElementWalker.forExecutable(element), () {
-      _formalParameterList(full.parameters, partial.parameters);
-      _constructorInitializers(full.initializers, partial.initializers);
-      partial.body = _body(full.body);
-    });
-    _metadata(partial.metadata, element);
-  }
-
-  void _constructorInitializers(
-    List<ConstructorInitializer> full,
-    List<ConstructorInitializer> partial,
-  ) {
-    if (full.isNotEmpty && partial.isEmpty) {
-      partial.addAll(full);
-    }
-    partial.forEach(_buildLocalElements);
-  }
-
-  void _declarations(CompilationUnit full, CompilationUnit partial) {
-    var fullList = full.declarations;
-    var partialList = partial.declarations;
-    for (var i = 0; i < fullList.length; ++i) {
-      var partialNode = _node(fullList[i], partialList[i]);
-      fullList[i] = partialNode;
-    }
-  }
-
-  void _directives(CompilationUnit full, CompilationUnit partial) {
-    var libraryElement = _unitElement.library;
-    var exportIndex = 0;
-    var importIndex = 0;
-    var partIndex = 0;
-    for (var directive in full.directives) {
-      if (directive is ExportDirective) {
-        var element = libraryElement.exports[exportIndex++];
-        _metadata(directive.metadata, element);
-      } else if (directive is ImportDirective) {
-        var element = libraryElement.imports[importIndex++];
-        _metadata(directive.metadata, element);
-      } else if (directive is LibraryDirective) {
-        var element = libraryElement;
-        _metadata(directive.metadata, element);
-      } else if (directive is PartDirective) {
-        var element = libraryElement.parts[partIndex++];
-        _metadata(directive.metadata, element);
-      }
-    }
-  }
-
-  void _enumConstantDeclaration(
-      EnumConstantDeclaration full, EnumConstantDeclaration partial) {
-    var element = _walker.getVariable();
-    _match(partial.name, element);
-    _metadata(partial.metadata, element);
-  }
-
-  void _enumDeclaration(EnumDeclaration full, EnumDeclaration partial) {
-    var element = _walker.getEnum();
-    _match(partial.name, element);
-    _walk(_ElementWalker.forClass(element), () {
-      var fullList = full.constants;
-      var partialList = partial.constants;
-      for (var i = 0; i < fullList.length; ++i) {
-        _node(fullList[i], partialList[i]);
-      }
-    });
-    _metadata(partial.metadata, element);
-  }
-
-  void _fieldDeclaration(FieldDeclaration full, FieldDeclaration partial) {
-    _node(full.fields, partial.fields);
-
-    var first = partial.fields.variables[0];
-    _metadata(partial.metadata, first.declaredElement);
-  }
-
-  void _fieldFormalParameter(
-    FieldFormalParameter full,
-    FieldFormalParameter partial,
-  ) {
-    var element = _walker.getParameter();
-    _match(partial.identifier, element);
-    _walk(_ElementWalker.forParameter(element), () {
-      _node(full.typeParameters, partial.typeParameters);
-      _node(full.parameters, partial.parameters);
-    });
-    _metadata(partial.metadata, element);
-  }
-
-  void _formalParameterList(
-    FormalParameterList full,
-    FormalParameterList partial,
-  ) {
-    var fullList = full.parameters;
-    var partialList = partial.parameters;
-    for (var i = 0; i < fullList.length; ++i) {
-      _node(fullList[i], partialList[i]);
-    }
-  }
-
-  void _functionDeclaration(
-    FunctionDeclaration full,
-    FunctionDeclaration partial,
-  ) {
-    var element = partial.propertyKeyword == null
-        ? _walker.getFunction()
-        : _walker.getAccessor();
-    _match(partial.name, element);
-    _walk(_ElementWalker.forExecutable(element), () {
-      _node(full.functionExpression, partial.functionExpression);
-    });
-    (partial.functionExpression as FunctionExpressionImpl).declaredElement =
-        element;
-    _metadata(partial.metadata, element);
-    _node(full.returnType, partial.returnType);
-  }
-
-  void _functionExpression(
-    FunctionExpression full,
-    FunctionExpression partial,
-  ) {
-    _node(full.typeParameters, partial.typeParameters);
-    _node(full.parameters, partial.parameters);
-    partial.body = _body(full.body);
-  }
-
-  void _functionTypeAlias(FunctionTypeAlias full, FunctionTypeAlias partial) {
-    var element = _walker.getTypedef();
-    _match(partial.name, element);
-    _walk(_ElementWalker.forGenericTypeAlias(element), () {
-      _node(full.typeParameters, partial.typeParameters);
-      _node(full.parameters, partial.parameters);
-    });
-    _metadata(partial.metadata, element);
-  }
-
-  void _functionTypedFormalParameter(
-    FunctionTypedFormalParameter full,
-    FunctionTypedFormalParameter partial,
-  ) {
-    var element = _walker.getParameter();
-    _match(partial.identifier, element);
-    _walk(_ElementWalker.forParameter(element), () {
-      _node(full.typeParameters, partial.typeParameters);
-      _node(full.parameters, partial.parameters);
-    });
-    _metadata(partial.metadata, element);
-  }
-
-  void _genericFunctionType(
-    GenericFunctionType full,
-    GenericFunctionType partial,
-  ) {
-    var element = (partial as GenericFunctionTypeImpl).declaredElement;
-    _walk(_ElementWalker.forGenericFunctionType(element), () {
-      _node(full.returnType, partial.returnType);
-      _node(full.typeParameters, partial.typeParameters);
-      _node(full.parameters, partial.parameters);
-    });
-  }
-
-  void _genericTypeAlias(GenericTypeAlias full, GenericTypeAlias partial) {
-    var element = _walker.getTypedef();
-    _match(partial.name, element);
-    _walk(_ElementWalker.forGenericTypeAlias(element), () {
-      _node(full.typeParameters, partial.typeParameters);
-      _node(full.functionType, partial.functionType);
-    });
-    _metadata(partial.metadata, element);
-  }
-
-  /// Updates [node] to point to [element], after ensuring that the
-  /// element has the expected name.
-  E _match<E extends Element>(SimpleIdentifier node, E element) {
-    // TODO(scheglov) has troubles with getter/setter.
-//    if (element.name != node.name) {
-//      throw new StateError(
-//        'Expected an element matching `${node.name}`, got `${element.name}`',
-//      );
-//    }
-    if (node != null) {
-      node.staticElement = element;
-    }
-    return element;
-  }
-
-  /// Associate [nodes] with the corresponding [ElementAnnotation]s.
-  void _metadata(List<Annotation> nodes, Element element) {
-    var elements = element.metadata;
-    if (nodes.length != elements.length) {
-      throw StateError('Found ${nodes.length} annotation nodes and '
-          '${elements.length} element annotations');
-    }
-    for (var i = 0; i < nodes.length; i++) {
-      var node = nodes[i];
-      node.elementAnnotation = elements[i];
-      _buildLocalElements(node);
-    }
-  }
-
-  void _methodDeclaration(MethodDeclaration full, MethodDeclaration partial) {
-    var element = partial.propertyKeyword == null
-        ? _walker.getFunction()
-        : _walker.getAccessor();
-    _match(partial.name, element);
-    _walk(_ElementWalker.forExecutable(element), () {
-      _node(full.typeParameters, partial.typeParameters);
-      _node(full.parameters, partial.parameters);
-      partial.body = _body(full.body);
-    });
-    _metadata(partial.metadata, element);
-    _node(full.returnType, partial.returnType);
-  }
-
-  void _mixinDeclaration(MixinDeclaration full, MixinDeclaration partial) {
-    var element = _walker.getMixin();
-    _match(partial.name, element);
-    _walk(_ElementWalker.forClass(element), () {
-      _node(full.typeParameters, partial.typeParameters);
-      var fullList = full.members;
-      var partialList = partial.members;
-      for (var i = 0; i < fullList.length; ++i) {
-        _node(fullList[i], partialList[i]);
-      }
-    });
-    _metadata(partial.metadata, element);
-  }
-
-  AstNode _node(AstNode full, AstNode partial) {
-    if (full == null && partial == null) {
-      return partial;
-    } else if (full is ClassDeclaration && partial is ClassDeclaration) {
-      _classDeclaration(full, partial);
-      return partial;
-    } else if (full is ClassTypeAlias && partial is ClassTypeAlias) {
-      _classTypeAlias(full, partial);
-      return partial;
-    } else if (full is ConstructorDeclaration &&
-        partial is ConstructorDeclaration) {
-      _constructorDeclaration(full, partial);
-      return partial;
-    } else if (full is DefaultFormalParameter &&
-        partial is DefaultFormalParameter) {
-      _node(full.parameter, partial.parameter);
-      return partial;
-    } else if (full is EnumConstantDeclaration &&
-        partial is EnumConstantDeclaration) {
-      _enumConstantDeclaration(full, partial);
-      return partial;
-    } else if (full is EnumDeclaration && partial is EnumDeclaration) {
-      _enumDeclaration(full, partial);
-      return partial;
-    } else if (full is FieldDeclaration && partial is FieldDeclaration) {
-      _fieldDeclaration(full, partial);
-      return partial;
-    } else if (full is FieldFormalParameter &&
-        partial is FieldFormalParameter) {
-      _fieldFormalParameter(full, partial);
-      return partial;
-    } else if (full is FormalParameterList && partial is FormalParameterList) {
-      _formalParameterList(full, partial);
-      return partial;
-    } else if (full is FunctionDeclaration && partial is FunctionDeclaration) {
-      _functionDeclaration(full, partial);
-      return partial;
-    } else if (full is FunctionExpression && partial is FunctionExpression) {
-      _functionExpression(full, partial);
-      return partial;
-    } else if (full is FunctionTypedFormalParameter &&
-        partial is FunctionTypedFormalParameter) {
-      _functionTypedFormalParameter(full, partial);
-      return partial;
-    } else if (full is FunctionTypeAlias && partial is FunctionTypeAlias) {
-      _functionTypeAlias(full, partial);
-      return partial;
-    } else if (full is GenericFunctionType && partial is GenericFunctionType) {
-      _genericFunctionType(full, partial);
-      return partial;
-    } else if (full is GenericTypeAlias && partial is GenericTypeAlias) {
-      _genericTypeAlias(full, partial);
-      return partial;
-    } else if (full is MethodDeclaration && partial is MethodDeclaration) {
-      _methodDeclaration(full, partial);
-      return partial;
-    } else if (full is MixinDeclaration && partial is MixinDeclaration) {
-      _mixinDeclaration(full, partial);
-      return partial;
-    } else if (full is SimpleFormalParameter &&
-        partial is SimpleFormalParameter) {
-      _simpleFormalParameter(full, partial);
-      return partial;
-    } else if (full is TopLevelVariableDeclaration &&
-        partial is TopLevelVariableDeclaration) {
-      _topLevelVariableDeclaration(full, partial);
-      return partial;
-    } else if (full is TypeName && partial is TypeName) {
-      _typeName(full, partial);
-      return partial;
-    } else if (full is TypeParameter && partial is TypeParameter) {
-      _typeParameter(full, partial);
-      return partial;
-    } else if (full is TypeParameterList && partial is TypeParameterList) {
-      _typeParameterList(full, partial);
-      return partial;
-    } else if (full is VariableDeclaration && partial is VariableDeclaration) {
-      _variableDeclaration(full, partial);
-      return partial;
-    } else if (full is VariableDeclarationList &&
-        partial is VariableDeclarationList) {
-      _variableDeclarationList(full, partial);
-      return partial;
-    } else {
-      throw UnimplementedError(
-        '${full.runtimeType} and ${partial.runtimeType}',
-      );
-    }
-  }
-
-  void _simpleFormalParameter(
-    SimpleFormalParameter full,
-    SimpleFormalParameter partial,
-  ) {
-    var element = _walker.getParameter();
-    _match(partial.identifier, element);
-    (partial as SimpleFormalParameterImpl).declaredElement = element;
-    _metadata(partial.metadata, element);
-    _node(full.type, partial.type);
-  }
-
-  void _topLevelVariableDeclaration(
-    TopLevelVariableDeclaration full,
-    TopLevelVariableDeclaration partial,
-  ) {
-    _node(full.variables, partial.variables);
-
-    var first = partial.variables.variables[0];
-    _metadata(partial.metadata, first.declaredElement);
-  }
-
-  void _typeName(TypeName full, TypeName partial) {
-    var fullList = full.typeArguments?.arguments;
-    var partialList = partial.typeArguments?.arguments;
-    if (fullList != null && partialList != null) {
-      for (var i = 0; i < fullList.length; ++i) {
-        _node(fullList[i], partialList[i]);
-      }
-    }
-  }
-
-  void _typeParameter(TypeParameter full, TypeParameter partial) {
-    var element = _walker.getTypeParameter();
-    _match(partial.name, element);
-    _node(full.bound, partial.bound);
-    _metadata(partial.metadata, element);
-  }
-
-  void _typeParameterList(TypeParameterList full, TypeParameterList partial) {
-    var fullList = full.typeParameters;
-    var partialList = partial.typeParameters;
-    for (var i = 0; i < fullList.length; ++i) {
-      _node(fullList[i], partialList[i]);
-    }
-  }
-
-  void _variableDeclaration(
-    VariableDeclaration full,
-    VariableDeclaration partial,
-  ) {
-    var element = _walker.getVariable();
-    _match(partial.name, element);
-    _walk(_ElementWalker.forVariable(element), () {
-      partial.initializer = full.initializer;
-      _buildLocalElements(partial.initializer);
-    });
-  }
-
-  void _variableDeclarationList(
-    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) {
-      _node(fullList[i], partialList[i]);
-    }
-  }
-
-  void _walk(_ElementWalker walker, void f()) {
-    var outer = _walker;
-    _walker = walker;
-    f();
-    _walker = outer;
-  }
-}
-
-class _ElementWalker {
-  final Element element;
-
-  List<PropertyAccessorElement> _accessors;
-  int _accessorIndex = 0;
-
-  List<ClassElement> _classes;
-  int _classIndex = 0;
-
-  List<ConstructorElement> _constructors;
-  int _constructorIndex = 0;
-
-  List<ClassElement> _enums;
-  int _enumIndex = 0;
-
-  List<ExecutableElement> _functions;
-  int _functionIndex = 0;
-
-  List<ClassElement> _mixins;
-  int _mixinIndex = 0;
-
-  List<ParameterElement> _parameters;
-  int _parameterIndex = 0;
-
-  List<FunctionTypeAliasElement> _typedefs;
-  int _typedefIndex = 0;
-
-  List<TypeParameterElement> _typeParameters;
-  int _typeParameterIndex = 0;
-
-  List<VariableElement> _variables;
-  int _variableIndex = 0;
-
-  _ElementWalker.forClass(ClassElement element)
-      : element = element,
-        _accessors = element.accessors.where(_isNotSynthetic).toList(),
-        _constructors = element.isMixinApplication
-            ? null
-            : element.constructors.where(_isNotSynthetic).toList(),
-        _functions = element.methods,
-        _typeParameters = element.typeParameters,
-        _variables = element.fields.where(_isNotSynthetic).toList();
-
-  _ElementWalker.forCompilationUnit(CompilationUnitElement element)
-      : element = element,
-        _accessors = element.accessors.where(_isNotSynthetic).toList(),
-        _classes = element.types,
-        _enums = element.enums,
-        _functions = element.functions,
-        _mixins = element.mixins,
-        _typedefs = element.functionTypeAliases,
-        _variables = element.topLevelVariables.where(_isNotSynthetic).toList();
-
-  _ElementWalker.forExecutable(ExecutableElement element)
-      : element = element,
-        _parameters = element.parameters,
-        _typeParameters = element.typeParameters;
-
-  _ElementWalker.forGenericFunctionType(GenericFunctionTypeElement element)
-      : element = element,
-        _parameters = element.parameters,
-        _typeParameters = element.typeParameters;
-
-  _ElementWalker.forGenericTypeAlias(FunctionTypeAliasElement element)
-      : element = element,
-        _parameters = element.parameters,
-        _typeParameters = element.typeParameters;
-
-  _ElementWalker.forParameter(ParameterElement element)
-      : element = element,
-        _parameters = element.parameters,
-        _typeParameters = element.typeParameters;
-
-  _ElementWalker.forVariable(VariableElement element) : element = element;
-
-  PropertyAccessorElement getAccessor() {
-    return _accessors[_accessorIndex++];
-  }
-
-  ClassElement getClass() {
-    return _classes[_classIndex++];
-  }
-
-  ConstructorElement getConstructor() {
-    return _constructors[_constructorIndex++];
-  }
-
-  ClassElement getEnum() {
-    return _enums[_enumIndex++];
-  }
-
-  ExecutableElement getFunction() {
-    return _functions[_functionIndex++];
-  }
-
-  ClassElement getMixin() {
-    return _mixins[_mixinIndex++];
-  }
-
-  ParameterElement getParameter() {
-    return _parameters[_parameterIndex++];
-  }
-
-  FunctionTypeAliasElement getTypedef() {
-    return _typedefs[_typedefIndex++];
-  }
-
-  TypeParameterElement getTypeParameter() {
-    return _typeParameters[_typeParameterIndex++];
-  }
-
-  VariableElement getVariable() {
-    return _variables[_variableIndex++];
-  }
-
-  static bool _isNotSynthetic(Element e) => !e.isSynthetic;
-}
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index 05189e2..f958156 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -188,13 +188,14 @@
         var unit = unitContext.unit;
 
         var writer = AstBinaryWriter(linkingBundleContext);
-        var unitLinkedNode = writer.writeNode(unit);
+        var unitLinkedNode = writer.writeUnit(unit);
         builder.node.units.add(
           LinkedNodeUnitBuilder(
             isSynthetic: unitContext.isSynthetic,
             uriStr: unitContext.uriStr,
             lineStarts: unit.lineInfo.lineStarts,
             node: unitLinkedNode,
+            genericFunctionTypes: writer.genericFunctionTypes,
           ),
         );
       }
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index fae3510..b562839 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
@@ -136,6 +137,14 @@
       return _function(enclosing, reference);
     }
 
+    if (parentName == '@genericFunctionType') {
+      CompilationUnitElementImpl enclosing = elementOfReference(parent2);
+      var context = enclosing.linkedContext;
+      var id = int.parse(reference.name);
+      GenericFunctionTypeImpl node = context.getGenericFunctionType(id);
+      return node.declaredElement as GenericFunctionTypeElementImpl;
+    }
+
     if (parentName == '@getter' || parentName == '@setter') {
       var enclosing = elementOfReference(parent2);
       return _accessor(enclosing, reference);
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index ad36d2f..3e8f6d1 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -5,7 +5,6 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -28,14 +27,15 @@
   final bool isSynthetic;
   final LinkedNodeUnit data;
 
+  /// This list is filled lazily with [GenericFunctionType] nodes as they
+  /// are requested by [getGenericFunctionType].
+  List<GenericFunctionType> _genericFunctionTypeNodeList;
+
   AstBinaryReader _astReader;
 
   CompilationUnit _unit;
   bool _hasDirectivesRead = false;
 
-  /// Mapping from identifiers to elements for generic function types.
-  final Map<int, GenericFunctionTypeElementImpl> _genericFunctionTypes = {};
-
   /// Mapping from identifiers to synthetic type parameters.
   ///
   /// Synthetic type parameters are added when [readType] begins reading a
@@ -56,19 +56,16 @@
     _astReader = AstBinaryReader(this);
     _astReader.isLazy = unit == null;
 
+    if (data != null) {
+      _genericFunctionTypeNodeList = List<GenericFunctionType>(
+        data.genericFunctionTypes.length,
+      );
+    }
+
     _unit = unit;
     _hasDirectivesRead = _unit != null;
   }
 
-  LinkedUnitContext._(
-      this.bundleContext,
-      this.libraryContext,
-      this.indexInLibrary,
-      this.uriStr,
-      this.reference,
-      this.isSynthetic,
-      this.data);
-
   bool get hasPartOfDirective {
     for (var directive in unit_withDirectives.directives) {
       if (directive is PartOfDirective) {
@@ -106,31 +103,6 @@
     return _unit;
   }
 
-  /// Every [GenericFunctionType] node has [GenericFunctionTypeElement], which
-  /// is created during reading of this node.
-  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(
-        this.reference.element,
-        null,
-        node,
-      );
-      _genericFunctionTypes[id] = element;
-    }
-
-    node.declaredElement = element;
-
-    var containerRef = this.reference.getChild('@genericFunctionType');
-    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);
@@ -355,9 +327,30 @@
     }
   }
 
+  GenericFunctionTypeImpl getGenericFunctionType(int id) {
+    GenericFunctionTypeImpl node = _genericFunctionTypeNodeList[id];
+    if (node == null) {
+      var data = this.data.genericFunctionTypes[id];
+      node = _astReader.readGenericFunctionType(data);
+      LazyAst.setGenericFunctionTypeId(node, id);
+      _genericFunctionTypeNodeList[id] = node;
+
+      var containerRef = this.reference.getChild('@genericFunctionType');
+      var reference = containerRef.getChild('$id');
+      var element = GenericFunctionTypeElementImpl.forLinkedNode(
+        this.reference.element,
+        reference,
+        node,
+      );
+      node.declaredElement = element;
+    }
+    return node;
+  }
+
   Reference getGenericFunctionTypeReference(GenericFunctionType node) {
+    var containerRef = reference.getChild('@genericFunctionType');
     var id = LazyAst.getGenericFunctionTypeId(node);
-    return reference.getChild('@genericFunctionType').getChild('$id');
+    return containerRef.getChild('$id');
   }
 
   GenericFunctionType getGeneticTypeAliasFunction(GenericTypeAlias node) {
@@ -941,34 +934,6 @@
     }
   }
 
-  /// Read new resolved [CompilationUnit] from the [data], and in contrast to
-  /// reading AST for element model, read it eagerly. We can do this, because
-  /// the element model is fully accessible, so we don't need to worry about
-  /// potential forward references.
-  ///
-  /// The new instance of [CompilationUnit] is required because the client of
-  /// this method is going to modify the unit - merge parsed, not yet resolved
-  /// function bodies into it, and resolve them.
-  CompilationUnit readUnitEagerly() {
-    reference.element.accept(
-      _TypeParameterReader(),
-    );
-    _RecursiveTypeReader(this).read(unit);
-
-    var context = LinkedUnitContext._(
-      bundleContext,
-      libraryContext,
-      indexInLibrary,
-      uriStr,
-      reference,
-      isSynthetic,
-      data,
-    );
-    context._genericFunctionTypes.addAll(_genericFunctionTypes);
-    var astReader = AstBinaryReader(context);
-    return astReader.readNode(data.node);
-  }
-
   void setInheritsCovariant(AstNode node, bool value) {
     if (node is FormalParameter) {
       LazyAst.setInheritsCovariant(node, value);
@@ -1103,95 +1068,3 @@
     }
   }
 }
-
-/// Ensure that all [GenericFunctionType] and [TypeParameter] nodes are read,
-/// so their elements are created and set in [Reference]s.
-class _RecursiveTypeReader {
-  final LinkedUnitContext context;
-
-  _RecursiveTypeReader(this.context);
-
-  void read(AstNode node) {
-    if (node == null) {
-    } else if (node is ClassDeclaration) {
-      _readTypeParameters(node);
-      node.members.forEach(read);
-    } else if (node is ClassTypeAlias) {
-      _readTypeParameters(node);
-    } else if (node is CompilationUnit) {
-      for (var declaration in node.declarations) {
-        read(declaration);
-      }
-    } else if (node is ConstructorDeclaration) {
-      _readFormalParameters(node);
-    } else if (node is EnumDeclaration) {
-    } else if (node is FieldDeclaration) {
-      read(node.fields);
-    } else if (node is FunctionDeclaration) {
-      _readTypeParameters(node);
-      _readFormalParameters(node);
-      _readReturnType(node);
-    } else if (node is FunctionTypeAlias) {
-      _readTypeParameters(node);
-      _readFormalParameters(node);
-      _readReturnType(node);
-    } else if (node is GenericFunctionType) {
-      _readTypeParameters(node);
-      _readFormalParameters(node);
-      _readReturnType(node);
-    } else if (node is GenericTypeAlias) {
-      _readTypeParameters(node);
-      LazyGenericTypeAlias.readFunctionType(context._astReader, node);
-      read(node.functionType);
-    } else if (node is MethodDeclaration) {
-      _readTypeParameters(node);
-      _readFormalParameters(node);
-      _readReturnType(node);
-    } else if (node is MixinDeclaration) {
-      _readTypeParameters(node);
-      node.members.forEach(read);
-    } else if (node is TopLevelVariableDeclaration) {
-      read(node.variables);
-    } else if (node is TypeName) {
-      node.typeArguments?.arguments?.forEach(read);
-    } else if (node is VariableDeclarationList) {
-      LazyVariableDeclarationList.readTypeNode(context._astReader, node);
-      read(node.type);
-    } else {
-      throw StateError('${node.runtimeType}');
-    }
-  }
-
-  void _readFormalParameters(AstNode node) {
-    var formalParameters = context.getFormalParameters(node);
-    if (formalParameters == null) return;
-
-    for (var formalParameter in formalParameters) {
-      if (formalParameter is SimpleFormalParameter) {
-        read(formalParameter.type);
-      }
-    }
-  }
-
-  void _readReturnType(AstNode node) {
-    var returnType = context.getReturnTypeNode(node);
-    read(returnType);
-  }
-
-  void _readTypeParameters(AstNode node) {
-    var typeParameters = context.getTypeParameters2(node);
-    if (typeParameters == null) return;
-
-    for (var typeParameter in typeParameters.typeParameters) {
-      var bound = context.getTypeParameterBound(typeParameter);
-      read(bound);
-    }
-  }
-}
-
-class _TypeParameterReader extends RecursiveElementVisitor<void> {
-  @override
-  void visitTypeParameterElement(TypeParameterElement element) {
-    super.visitTypeParameterElement(element);
-  }
-}
diff --git a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
index 242a9e1..7a7c22d 100644
--- a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
@@ -32,10 +32,6 @@
   final Map<TypeParameterElement, int> _typeParameters = Map.identity();
   int _nextSyntheticTypeParameterId = 0x10000;
 
-  final Map<GenericFunctionTypeElement, int> _genericFunctionTypes =
-      Map.identity();
-  int _nextGenericFunctionTypeId = 1;
-
   LinkingBundleContext(this.dynamicReference);
 
   /// We need indexes for references during linking, but once we are done,
@@ -48,10 +44,6 @@
     }
   }
 
-  int idOfGenericFunctionType(GenericFunctionTypeElement element) {
-    return _genericFunctionTypes[element];
-  }
-
   int idOfTypeParameter(TypeParameterElement element) {
     return _typeParameters[element];
   }
@@ -82,10 +74,6 @@
     return reference.index;
   }
 
-  int nextGenericFunctionTypeId() {
-    return _nextGenericFunctionTypeId++;
-  }
-
   LinkedNodeTypeBuilder writeType(DartType type) {
     if (type == null) return null;
 
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index cfaee14..79f7c1a 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -14,7 +14,6 @@
 import 'package:analyzer/src/summary2/function_type_builder.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';
 import 'package:analyzer/src/summary2/named_type_builder.dart';
 import 'package:analyzer/src/summary2/reference.dart';
@@ -30,18 +29,19 @@
 /// the type is set, otherwise we keep it empty, so we will attempt to infer
 /// it later).
 class ReferenceResolver extends ThrowingAstVisitor<void> {
-  final LinkingBundleContext linkingContext;
   final NodesToBuildType nodesToBuildType;
   final LinkedElementFactory elementFactory;
   final LibraryElement _libraryElement;
   final Reference unitReference;
   final bool nnbd;
 
+  /// The depth-first number of the next [GenericFunctionType] node.
+  int _nextGenericFunctionTypeId = 0;
+
   Reference reference;
   Scope scope;
 
   ReferenceResolver(
-    this.linkingContext,
     this.nodesToBuildType,
     this.elementFactory,
     this._libraryElement,
@@ -261,7 +261,7 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var id = linkingContext.nextGenericFunctionTypeId();
+    var id = _nextGenericFunctionTypeId++;
     LazyAst.setGenericFunctionTypeId(node, id);
 
     var containerRef = unitReference.getChild('@genericFunctionType');