Version 2.13.0-132.0.dev

Merge commit '3c5767ccd34d0aeaf084bbf50b0849e24c17d710' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
index a8634ca..830a57d 100644
--- a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
@@ -427,14 +427,8 @@
     }
     DoStatement statement = node;
     var sb = _sourceBuilderAfterKeyword(statement.doKeyword);
-    // I modified the code and ran the tests with both the old and new parser.
-    // Apparently the old parser sometimes sticks something other than 'while'
-    // into the whileKeyword field, which causes statement completion to throw
-    // an exception further downstream.
-    // TODO(danrubel): change `statement.whileKeyword?.lexeme == "while"`
-    // to `statement.whileKeyword != null` once the fasta parser is the default.
-    var hasWhileKeyword = statement.whileKeyword?.lexeme == 'while' &&
-        !statement.whileKeyword.isSynthetic;
+    var hasWhileKeyword =
+        statement.whileKeyword != null && !statement.whileKeyword.isSynthetic;
     var exitDelta = 0;
     if (!_statementHasValidBody(statement.doKeyword, statement.body)) {
       var text = utils.getNodeText(statement.body);
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index bd86522..2090cf6 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -96,8 +96,6 @@
   /// where there is no `new` or `const` keyword.
   bool get suggestConstructorsWithoutNew => true;
 
-  bool get usingFastaParser => true;
-
   void addTestSource(String content) {
     expect(completionOffset, isNull, reason: 'Call addTestUnit exactly once');
     completionOffset = content.indexOf('^');
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 5bda1ad..84b0ba8 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -528,9 +528,7 @@
   Future<void> test_anonymous_function_async7() async {
     addTestSource('main() {foo("bar", () as^ => null');
     await computeSuggestions();
-    assertSuggestKeywords([],
-        pseudoKeywords:
-            usingFastaParser ? ['async'] : ['async', 'async*', 'sync*']);
+    assertSuggestKeywords([], pseudoKeywords: ['async']);
   }
 
   Future<void> test_anonymous_function_async8() async {
@@ -916,17 +914,13 @@
   Future<void> test_class_implements2() async {
     addTestSource('class A e^ implements foo');
     await computeSuggestions();
-    assertSuggestKeywords(usingFastaParser
-        ? [Keyword.EXTENDS]
-        : [Keyword.EXTENDS, Keyword.IMPLEMENTS]);
+    assertSuggestKeywords([Keyword.EXTENDS]);
   }
 
   Future<void> test_class_implements3() async {
     addTestSource('class A e^ implements foo { }');
     await computeSuggestions();
-    assertSuggestKeywords(usingFastaParser
-        ? [Keyword.EXTENDS]
-        : [Keyword.EXTENDS, Keyword.IMPLEMENTS]);
+    assertSuggestKeywords([Keyword.EXTENDS]);
   }
 
   Future<void> test_class_implements_name() async {
diff --git a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
index 504dc74..5d99721 100644
--- a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
+++ b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
@@ -1398,17 +1398,7 @@
         (s) => _afterLast(s, '  '));
   }
 
-  @failingTest
   Future<void> test_noCloseParenWithSemicolon() async {
-    // TODO(danrubel):
-    // Fasta scanner produces an error message which is converted into
-    // an Analyzer error message before the fasta parser gets a chance
-    // to move it along with the associated synthetic ')' to a more
-    // appropriate location. This means that some statement completions,
-    // which are expecting errors in a particular location, don't work.
-    // Fixing this properly means modifying the scanner not to generate
-    // closing ')', then updating the parser to handle that situation.
-    // This is a fair amount of work and won't be tackled today.
     var before = '''
 main() {
   var s = 'sample'.substring(3;
@@ -1427,12 +1417,6 @@
     await _prepareCompletion('ing(3;', before, atEnd: true);
     _assertHasChange('Insert a newline at the end of the current line', after,
         (s) => _afterLast(s, '  '));
-
-    // The old Analyzer parser passes this test, but will be turned off soon.
-    // It is preferable to throw only if the old analyzer is being used,
-    // but there does not seem to be a reliable way to determine that here.
-    // TODO(danrubel): remove this once fasta parser is enabled by default.
-    throw 'remove this once fasta parser is enabled by default';
   }
 
   Future<void> test_semicolonFn() async {
@@ -1507,12 +1491,6 @@
 f() {}
 ''',
         (s) => _afterLast(s, '  '));
-
-    // The old Analyzer parser passes this test, but will be turned off soon.
-    // It is preferable to throw only if the old analyzer is being used,
-    // but there does not seem to be a reliable way to determine that here.
-    // TODO(danrubel): remove this once fasta parser is enabled by default.
-    throw 'remove this once fasta parser is enabled by default';
   }
 
   Future<void> test_semicolonFnExpr() async {
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 4c261da..41e58eb 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -1381,7 +1381,7 @@
 
   @override
   bool visitNeverType(NeverType type, List<FunctionTypeVariable> bindings) =>
-      false;
+      handleNeverType(type);
 
   @override
   bool visitVoidType(VoidType type, List<FunctionTypeVariable> bindings) =>
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index 474f127..fee1573 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -415,11 +415,17 @@
         case ConstantValueKind.SET:
         case ConstantValueKind.MAP:
         case ConstantValueKind.CONSTRUCTED:
-        case ConstantValueKind.INSTANTIATION:
         case ConstantValueKind.LIST:
           transformed.registerStaticUse(StaticUse.staticInvoke(
               _closedWorld.commonElements.findType, CallStructure.ONE_ARG));
           break;
+        case ConstantValueKind.INSTANTIATION:
+          transformed.registerStaticUse(StaticUse.staticInvoke(
+              _closedWorld.commonElements.findType, CallStructure.ONE_ARG));
+          InstantiationConstantValue instantiation = constantUse.value;
+          _rtiChecksBuilder.registerGenericInstantiation(GenericInstantiation(
+              instantiation.function.type, instantiation.typeArguments));
+          break;
         case ConstantValueKind.DEFERRED_GLOBAL:
           _closedWorld.outputUnitData
               .registerConstantDeferredUse(constantUse.value);
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index c24e828..e7113df 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -533,7 +533,6 @@
     TypeVariableTests typeVariableTests = new TypeVariableTests(
         _elementEnvironment,
         _commonElements,
-        _types,
         codegenWorld,
         _genericInstantiations,
         forRtiNeeds: false);
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
index 7afc77e..9348b79 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
@@ -197,11 +197,17 @@
 }
 
 class TypeVariableTests {
-  Map<ClassEntity, ClassNode> _classes = {};
-  Map<Entity, MethodNode> _methods = {};
-  Map<MemberEntity, CallablePropertyNode> _callableProperties = {};
+  final ElementEnvironment _elementEnvironment;
+  final CommonElements _commonElements;
+  final BuiltWorld _world;
+  final Set<GenericInstantiation> _genericInstantiations;
+  final bool forRtiNeeds;
+
+  final Map<ClassEntity, ClassNode> _classes = {};
+  final Map<Entity, MethodNode> _methods = {};
+  final Map<MemberEntity, CallablePropertyNode> _callableProperties = {};
   Map<Selector, Set<Entity>> _appliedSelectorMap;
-  Map<GenericInstantiation, Set<Entity>> _instantiationMap;
+  final Map<Entity, Set<GenericInstantiation>> _instantiationMap = {};
 
   /// All explicit is-tests.
   final Set<DartType> explicitIsChecks;
@@ -209,25 +215,20 @@
   /// All implicit is-tests.
   final Set<DartType> implicitIsChecks = new Set<DartType>();
 
-  TypeVariableTests(
-      ElementEnvironment elementEnvironment,
-      CommonElements commonElements,
-      DartTypes types,
-      BuiltWorld world,
-      Set<GenericInstantiation> genericInstantiations,
-      {bool forRtiNeeds: true})
-      : explicitIsChecks = new Set<DartType>.from(world.isChecks) {
-    _setupDependencies(
-        elementEnvironment, commonElements, world, genericInstantiations,
-        forRtiNeeds: forRtiNeeds);
-    _propagateTests(commonElements, elementEnvironment, world);
+  TypeVariableTests(this._elementEnvironment, this._commonElements, this._world,
+      this._genericInstantiations,
+      {this.forRtiNeeds: true})
+      : explicitIsChecks = _world.isChecks.toSet() {
+    _setupDependencies();
+    _propagateTests();
     if (forRtiNeeds) {
-      _propagateLiterals(elementEnvironment, world);
+      _propagateLiterals();
     }
-    _collectResults(commonElements, elementEnvironment, types, world,
-        forRtiNeeds: forRtiNeeds);
+    _collectResults();
   }
 
+  DartTypes get _dartTypes => _commonElements.dartTypes;
+
   /// Classes whose type variables are explicitly or implicitly used in
   /// is-tests.
   ///
@@ -323,9 +324,9 @@
 
   /// Calls [f] for each generic instantiation that applies to generic
   /// closurized [targets].
-  void forEachGenericInstantiation(
-      void f(GenericInstantiation instantiation, Set<Entity> targets)) {
-    _instantiationMap?.forEach(f);
+  void forEachInstantiatedEntity(
+      void f(Entity target, Set<GenericInstantiation> instantiations)) {
+    _instantiationMap.forEach(f);
   }
 
   ClassNode _getClassNode(ClassEntity cls) {
@@ -366,12 +367,7 @@
       _callableProperties.putIfAbsent(
           property, () => CallablePropertyNode(property, type));
 
-  void _setupDependencies(
-      ElementEnvironment elementEnvironment,
-      CommonElements commonElements,
-      BuiltWorld world,
-      Set<GenericInstantiation> genericInstantiations,
-      {bool forRtiNeeds: true}) {
+  void _setupDependencies() {
     /// Register that if `node.entity` needs type arguments then so do entities
     /// whose type variables occur in [type].
     ///
@@ -387,11 +383,33 @@
           node.addDependency(_getClassNode(typeDeclaration));
         } else {
           node.addDependency(
-              _getMethodNode(elementEnvironment, world, typeDeclaration));
+              _getMethodNode(_elementEnvironment, _world, typeDeclaration));
         }
       });
     }
 
+    void registerDependenciesForInstantiation(RtiNode node, DartType type) {
+      void onInterface(InterfaceType type) {
+        if (type.typeArguments.isNotEmpty) {
+          node.addDependency(_getClassNode(type.element));
+        }
+      }
+
+      void onTypeVariable(TypeVariableType type) {
+        Entity declaration = type.element.typeDeclaration;
+        if (declaration is ClassEntity) {
+          node.addDependency(_getClassNode(declaration));
+        } else {
+          node.addDependency(
+              _getMethodNode(_elementEnvironment, _world, declaration));
+        }
+      }
+
+      _DependencyVisitor(
+              onInterface: onInterface, onTypeVariable: onTypeVariable)
+          .run(type);
+    }
+
     // Add the rti dependencies that are implicit in the way the backend
     // generates code: when we create a new [List], we actually create a
     // [JSArray] in the backend and we need to add type arguments to the calls
@@ -412,17 +430,17 @@
     //
     // TODO(johnniwinther): Make this dependency visible from code, possibly
     // using generic methods.
-    if (commonElements.jsArrayClass != null) {
-      _getClassNode(commonElements.jsArrayClass)
-          .addDependency(_getClassNode(commonElements.listClass));
+    if (_commonElements.jsArrayClass != null) {
+      _getClassNode(_commonElements.jsArrayClass)
+          .addDependency(_getClassNode(_commonElements.listClass));
     }
-    if (commonElements.setLiteralClass != null) {
-      _getClassNode(commonElements.setLiteralClass)
-          .addDependency(_getClassNode(commonElements.setClass));
+    if (_commonElements.setLiteralClass != null) {
+      _getClassNode(_commonElements.setLiteralClass)
+          .addDependency(_getClassNode(_commonElements.setClass));
     }
-    if (commonElements.mapLiteralClass != null) {
-      _getClassNode(commonElements.mapLiteralClass)
-          .addDependency(_getClassNode(commonElements.mapClass));
+    if (_commonElements.mapLiteralClass != null) {
+      _getClassNode(_commonElements.mapLiteralClass)
+          .addDependency(_getClassNode(_commonElements.mapClass));
     }
 
     void processCheckedType(DartType type) {
@@ -439,36 +457,36 @@
         // For the implied `is Future<X>` test, register that if `Future` needs
         // type arguments then so do the entities that declare type variables
         // occurring in `type.typeArgument`.
-        registerDependencies(_getClassNode(commonElements.futureClass),
+        registerDependencies(_getClassNode(_commonElements.futureClass),
             typeWithoutNullability.typeArgument);
         // Process `type.typeArgument` for the implied `is X` test.
         processCheckedType(typeWithoutNullability.typeArgument);
       }
     }
 
-    world.isChecks.forEach(processCheckedType);
+    _world.isChecks.forEach(processCheckedType);
 
-    world.instantiatedTypes.forEach((InterfaceType type) {
+    _world.instantiatedTypes.forEach((InterfaceType type) {
       // Register that if [cls] needs type arguments then so do the entities
       // that declare type variables occurring in [type].
       ClassEntity cls = type.element;
       registerDependencies(_getClassNode(cls), type);
     });
 
-    world.forEachStaticTypeArgument(
+    _world.forEachStaticTypeArgument(
         (Entity entity, Iterable<DartType> typeArguments) {
       for (DartType type in typeArguments) {
         // Register that if [entity] needs type arguments then so do the
         // entities that declare type variables occurring in [type].
         registerDependencies(
-            _getMethodNode(elementEnvironment, world, entity), type);
+            _getMethodNode(_elementEnvironment, _world, entity), type);
       }
     });
 
-    world.forEachDynamicTypeArgument(
+    _world.forEachDynamicTypeArgument(
         (Selector selector, Iterable<DartType> typeArguments) {
       void processCallableNode(CallableNode node) {
-        if (node.selectorApplies(selector, world)) {
+        if (node.selectorApplies(selector, _world)) {
           for (DartType type in typeArguments) {
             // Register that if `node.entity` needs type arguments then so do
             // the entities that declare type variables occurring in [type].
@@ -478,7 +496,7 @@
       }
 
       void processMethod(Entity entity) {
-        MethodNode node = _getMethodNode(elementEnvironment, world, entity);
+        MethodNode node = _getMethodNode(_elementEnvironment, _world, entity);
         processCallableNode(node);
       }
 
@@ -487,47 +505,38 @@
         processCallableNode(node);
       }
 
-      world.forEachGenericInstanceMethod(processMethod);
-      world.genericLocalFunctions.forEach(processMethod);
-      world.closurizedStatics.forEach(processMethod);
-      world.userNoSuchMethods.forEach(processMethod);
-      world.genericCallableProperties.forEach(processCallableProperty);
+      _world.forEachGenericInstanceMethod(processMethod);
+      _world.genericLocalFunctions.forEach(processMethod);
+      _world.closurizedStatics.forEach(processMethod);
+      _world.userNoSuchMethods.forEach(processMethod);
+      _world.genericCallableProperties.forEach(processCallableProperty);
     });
 
-    for (GenericInstantiation instantiation in genericInstantiations) {
+    for (GenericInstantiation instantiation in _genericInstantiations) {
       void processEntity(Entity entity) {
-        MethodNode node = _getMethodNode(elementEnvironment, world, entity);
-        if (node.parameterStructure.typeParameters ==
-            instantiation.typeArguments.length) {
-          if (forRtiNeeds) {
-            _instantiationMap ??= <GenericInstantiation, Set<Entity>>{};
-            _instantiationMap
-                .putIfAbsent(instantiation, () => new Set<Entity>())
-                .add(entity);
-          }
+        MethodNode node = _getMethodNode(_elementEnvironment, _world, entity);
+        if (node.parameterStructure ==
+            ParameterStructure.fromType(instantiation.functionType)) {
+          _instantiationMap.putIfAbsent(entity, () => {}).add(instantiation);
           for (DartType type in instantiation.typeArguments) {
-            // Register that if `node.entity` needs type arguments then so do
-            // the entities that declare type variables occurring in [type].
-            registerDependencies(node, type);
+            registerDependenciesForInstantiation(node, type);
           }
         }
       }
 
-      world.closurizedMembers.forEach(processEntity);
-      world.closurizedStatics.forEach(processEntity);
-      world.genericLocalFunctions.forEach(processEntity);
+      _world.closurizedMembers.forEach(processEntity);
+      _world.closurizedStatics.forEach(processEntity);
+      _world.genericLocalFunctions.forEach(processEntity);
     }
   }
 
-  void _propagateTests(CommonElements commonElements,
-      ElementEnvironment elementEnvironment, BuiltWorld worldBuilder) {
+  void _propagateTests() {
     void processTypeVariableType(TypeVariableType type, {bool direct: true}) {
       TypeVariableEntity variable = type.element;
       if (variable.typeDeclaration is ClassEntity) {
         _getClassNode(variable.typeDeclaration).markTest(direct: direct);
       } else {
-        _getMethodNode(
-                elementEnvironment, worldBuilder, variable.typeDeclaration)
+        _getMethodNode(_elementEnvironment, _world, variable.typeDeclaration)
             .markTest(direct: direct);
       }
     }
@@ -535,7 +544,7 @@
     void processType(DartType type, {bool direct: true}) {
       var typeWithoutNullability = type.withoutNullability;
       if (typeWithoutNullability is FutureOrType) {
-        _getClassNode(commonElements.futureClass).markIndirectTest();
+        _getClassNode(_commonElements.futureClass).markIndirectTest();
         processType(typeWithoutNullability.typeArgument, direct: false);
       } else {
         typeWithoutNullability.forEachTypeVariable((TypeVariableType type) {
@@ -544,17 +553,17 @@
       }
     }
 
-    worldBuilder.isChecks.forEach(processType);
+    _world.isChecks.forEach(processType);
   }
 
-  void _propagateLiterals(
-      ElementEnvironment elementEnvironment, BuiltWorld world) {
-    world.typeVariableTypeLiterals.forEach((TypeVariableType typeVariableType) {
+  void _propagateLiterals() {
+    _world.typeVariableTypeLiterals
+        .forEach((TypeVariableType typeVariableType) {
       TypeVariableEntity variable = typeVariableType.element;
       if (variable.typeDeclaration is ClassEntity) {
         _getClassNode(variable.typeDeclaration).markDirectLiteral();
       } else {
-        _getMethodNode(elementEnvironment, world, variable.typeDeclaration)
+        _getMethodNode(_elementEnvironment, _world, variable.typeDeclaration)
             .markDirectLiteral();
       }
     });
@@ -608,34 +617,45 @@
     return sb.toString();
   }
 
-  void _collectResults(CommonElements commonElements,
-      ElementEnvironment elementEnvironment, DartTypes types, BuiltWorld world,
-      {bool forRtiNeeds: true}) {
-    /// Register the implicit is-test of [type].
-    ///
-    /// If [type] is of the form `FutureOr<X>`, also register the implicit
-    /// is-tests of `Future<X>` and `X`.
-    void addImplicitCheck(DartType type) {
-      var typeWithoutNullability = type.withoutNullability;
-      if (implicitIsChecks.add(typeWithoutNullability)) {
-        if (typeWithoutNullability is FutureOrType) {
-          addImplicitCheck(
-              commonElements.futureType(typeWithoutNullability.typeArgument));
-          addImplicitCheck(typeWithoutNullability.typeArgument);
-        }
+  /// Register the implicit is-test of [type].
+  ///
+  /// If [type] is of the form `FutureOr<X>`, also register the implicit
+  /// is-tests of `Future<X>` and `X`.
+  void _addImplicitCheck(DartType type) {
+    var typeWithoutNullability = type.withoutNullability;
+    if (implicitIsChecks.add(typeWithoutNullability)) {
+      if (typeWithoutNullability is FutureOrType) {
+        _addImplicitCheck(
+            _commonElements.futureType(typeWithoutNullability.typeArgument));
+        _addImplicitCheck(typeWithoutNullability.typeArgument);
+      } else if (typeWithoutNullability is TypeVariableType) {
+        _addImplicitChecksViaInstantiation(typeWithoutNullability);
       }
     }
+  }
 
-    void addImplicitChecks(Iterable<DartType> types) {
-      types.forEach(addImplicitCheck);
-    }
+  void _addImplicitChecks(Iterable<DartType> types) {
+    types.forEach(_addImplicitCheck);
+  }
 
-    world.isChecks.forEach((DartType type) {
+  void _addImplicitChecksViaInstantiation(TypeVariableType variable) {
+    TypeVariableEntity entity = variable.element;
+    Entity declaration = entity.typeDeclaration;
+    _instantiationMap[declaration]
+        ?.forEach((GenericInstantiation instantiation) {
+      _addImplicitCheck(instantiation.typeArguments[entity.index]);
+    });
+  }
+
+  void _collectResults() {
+    _world.isChecks.forEach((DartType type) {
       var typeWithoutNullability = type.withoutNullability;
       if (typeWithoutNullability is FutureOrType) {
-        addImplicitCheck(
-            commonElements.futureType(typeWithoutNullability.typeArgument));
-        addImplicitCheck(typeWithoutNullability.typeArgument);
+        _addImplicitCheck(
+            _commonElements.futureType(typeWithoutNullability.typeArgument));
+        _addImplicitCheck(typeWithoutNullability.typeArgument);
+      } else if (typeWithoutNullability is TypeVariableType) {
+        _addImplicitChecksViaInstantiation(typeWithoutNullability);
       }
     });
 
@@ -646,45 +666,45 @@
       // Find all instantiated types that are a subtype of a class that uses
       // one of its type arguments in an is-check and add the arguments to the
       // set of is-checks.
-      for (InterfaceType type in world.instantiatedTypes) {
+      for (InterfaceType type in _world.instantiatedTypes) {
         // We need the type as instance of its superclass anyway, so we just
         // try to compute the substitution; if the result is [:null:], the
         // classes are not related.
-        InterfaceType instance = types.asInstanceOf(type, cls);
+        InterfaceType instance = _dartTypes.asInstanceOf(type, cls);
         if (instance != null) {
           for (DartType argument in instance.typeArguments) {
-            addImplicitCheck(argument);
+            _addImplicitCheck(argument);
           }
         }
       }
     });
 
-    world.forEachStaticTypeArgument(
+    _world.forEachStaticTypeArgument(
         (Entity function, Iterable<DartType> typeArguments) {
-      if (!_getMethodNode(elementEnvironment, world, function).hasTest) {
+      if (!_getMethodNode(_elementEnvironment, _world, function).hasTest) {
         return;
       }
-      addImplicitChecks(typeArguments);
+      _addImplicitChecks(typeArguments);
     });
 
     if (forRtiNeeds) {
       _appliedSelectorMap = <Selector, Set<Entity>>{};
     }
 
-    world.forEachDynamicTypeArgument(
+    _world.forEachDynamicTypeArgument(
         (Selector selector, Iterable<DartType> typeArguments) {
       for (CallableNode node in [
         ..._methods.values,
         ..._callableProperties.values
       ]) {
-        if (node.selectorApplies(selector, world)) {
+        if (node.selectorApplies(selector, _world)) {
           if (forRtiNeeds) {
             _appliedSelectorMap
                 .putIfAbsent(selector, () => {})
                 .add(node.entity);
           }
           if (node.hasTest) {
-            addImplicitChecks(typeArguments);
+            _addImplicitChecks(typeArguments);
           }
         }
       }
@@ -692,6 +712,25 @@
   }
 }
 
+class _DependencyVisitor extends DartTypeStructuralPredicateVisitor {
+  void Function(InterfaceType) onInterface;
+  void Function(TypeVariableType) onTypeVariable;
+
+  _DependencyVisitor({this.onInterface, this.onTypeVariable});
+
+  @override
+  bool handleInterfaceType(InterfaceType type) {
+    onInterface(type);
+    return false;
+  }
+
+  @override
+  bool handleTypeVariableType(TypeVariableType type) {
+    onTypeVariable(type);
+    return false;
+  }
+}
+
 /// Interface for the classes and methods that need runtime types.
 abstract class RuntimeTypesNeed {
   /// Deserializes a [RuntimeTypesNeed] object from [source].
@@ -770,7 +809,7 @@
   /// arguments.
   // TODO(johnniwinther): Use [functionType].
   bool instantiationNeedsTypeArguments(
-      DartType functionType, int typeArgumentCount);
+      FunctionType functionType, int typeArgumentCount);
 }
 
 class TrivialRuntimeTypesNeed implements RuntimeTypesNeed {
@@ -804,7 +843,7 @@
 
   @override
   bool instantiationNeedsTypeArguments(
-      DartType functionType, int typeArgumentCount) {
+      FunctionType functionType, int typeArgumentCount) {
     return true;
   }
 }
@@ -903,7 +942,7 @@
 
   @override
   bool instantiationNeedsTypeArguments(
-      DartType functionType, int typeArgumentCount) {
+      FunctionType functionType, int typeArgumentCount) {
     return instantiationsNeedingTypeArguments.contains(typeArgumentCount);
   }
 }
@@ -963,8 +1002,11 @@
 
   Map<Selector, Set<Entity>> selectorsNeedingTypeArgumentsForTesting;
 
-  Map<GenericInstantiation, Set<Entity>>
-      instantiationsNeedingTypeArgumentsForTesting;
+  Map<Entity, Set<GenericInstantiation>>
+      _instantiatedEntitiesNeedingTypeArgumentsForTesting;
+  Map<Entity, Set<GenericInstantiation>>
+      get instantiatedEntitiesNeedingTypeArgumentsForTesting =>
+          _instantiatedEntitiesNeedingTypeArgumentsForTesting ?? const {};
 
   final Set<GenericInstantiation> _genericInstantiations =
       new Set<GenericInstantiation>();
@@ -999,7 +1041,6 @@
     TypeVariableTests typeVariableTests = new TypeVariableTests(
         closedWorld.elementEnvironment,
         closedWorld.commonElements,
-        closedWorld.dartTypes,
         closedWorld,
         _genericInstantiations);
     Set<ClassEntity> classesNeedingTypeArguments = new Set<ClassEntity>();
@@ -1348,24 +1389,19 @@
       }
     });
     Set<int> instantiationsNeedingTypeArguments = new Set<int>();
-    typeVariableTests.forEachGenericInstantiation(
-        (GenericInstantiation instantiation, Set<Entity> targets) {
-      for (Entity target in targets) {
-        if (methodsNeedingTypeArguments.contains(target) ||
-            localFunctionsNeedingTypeArguments.contains(target)) {
-          // TODO(johnniwinther): Use the static type of the instantiated
-          // expression.
-          instantiationsNeedingTypeArguments
-              .add(instantiation.typeArguments.length);
-          if (retainDataForTesting) {
-            instantiationsNeedingTypeArgumentsForTesting ??=
-                <GenericInstantiation, Set<Entity>>{};
-            instantiationsNeedingTypeArgumentsForTesting
-                .putIfAbsent(instantiation, () => new Set<Entity>())
-                .add(target);
-          } else {
-            return;
-          }
+    typeVariableTests.forEachInstantiatedEntity(
+        (Entity target, Set<GenericInstantiation> instantiations) {
+      if (methodsNeedingTypeArguments.contains(target) ||
+          localFunctionsNeedingTypeArguments.contains(target)) {
+        // TODO(johnniwinther): Use the static type of the instantiated
+        // expression.
+        instantiationsNeedingTypeArguments
+            .add(instantiations.first.typeArguments.length);
+        if (retainDataForTesting) {
+          _instantiatedEntitiesNeedingTypeArgumentsForTesting ??= {};
+          _instantiatedEntitiesNeedingTypeArgumentsForTesting
+              .putIfAbsent(target, () => {})
+              .addAll(instantiations);
         }
       }
     });
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 41f9170..216f25e 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -1411,5 +1411,5 @@
   bool selectorNeedsTypeArguments(Selector selector);
 
   bool instantiationNeedsTypeArguments(
-      DartType functionType, int typeArgumentCount);
+      FunctionType functionType, int typeArgumentCount);
 }
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index f2fdbe6..c07ccea 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -528,7 +528,7 @@
 
   @override
   bool instantiationNeedsTypeArguments(
-          DartType functionType, int typeArgumentCount) =>
+          FunctionType functionType, int typeArgumentCount) =>
       true;
 }
 
@@ -568,7 +568,7 @@
 
   @override
   bool instantiationNeedsTypeArguments(
-          DartType functionType, int typeArgumentCount) =>
+          FunctionType functionType, int typeArgumentCount) =>
       rtiNeed.instantiationNeedsTypeArguments(functionType, typeArgumentCount);
 }
 
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index f3df3a2..9a40f68 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -700,7 +700,7 @@
       ir.FunctionType expressionType, List<ir.DartType> typeArguments) {
     // TODO(johnniwinther): Track which arities are used in instantiation.
     impactBuilder.registerInstantiation(new GenericInstantiation(
-        elementMap.getDartType(expressionType),
+        elementMap.getDartType(expressionType).withoutNullability,
         typeArguments.map(elementMap.getDartType).toList()));
   }
 
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 083df95..2831f5c 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -5193,15 +5193,16 @@
     node.expression.accept(this);
     arguments.add(pop());
     StaticType expressionType = _getStaticType(node.expression);
+    FunctionType functionType = expressionType.type.withoutNullability;
     bool typeArgumentsNeeded = _rtiNeed.instantiationNeedsTypeArguments(
-        expressionType.type, node.typeArguments.length);
+        functionType, node.typeArguments.length);
     List<DartType> typeArguments = node.typeArguments
         .map((type) => typeArgumentsNeeded
             ? _elementMap.getDartType(type)
             : _commonElements.dynamicType)
         .toList();
     registry.registerGenericInstantiation(
-        new GenericInstantiation(expressionType.type, typeArguments));
+        new GenericInstantiation(functionType, typeArguments));
     // TODO(johnniwinther): Can we avoid creating the instantiation object?
     for (DartType type in typeArguments) {
       HInstruction instruction =
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index 7ea60b7..f907c36 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -237,7 +237,7 @@
   static const String tag = 'generic-instantiation';
 
   /// The static type of the instantiated expression.
-  final DartType functionType;
+  final FunctionType functionType;
 
   /// The type arguments of the instantiation.
   final List<DartType> typeArguments;
diff --git a/pkg/compiler/test/rti/data/instantiation1.dart b/pkg/compiler/test/rti/data/instantiation1.dart
index 8fbd5f3..c838bbe 100644
--- a/pkg/compiler/test/rti/data/instantiation1.dart
+++ b/pkg/compiler/test/rti/data/instantiation1.dart
@@ -10,7 +10,7 @@
 
 typedef int F<R>(R a);
 
-/*spec.class: B:explicit=[int* Function(B.S*)*],indirect,needsArgs*/
+/*spec.class: B:explicit=[int* Function(B.S*)*],implicit=[B.S],indirect,needsArgs*/
 class B<S> {
   F<S> c;
 
diff --git a/pkg/compiler/test/rti/data/instantiation2.dart b/pkg/compiler/test/rti/data/instantiation2.dart
index dbb5db8..934152a 100644
--- a/pkg/compiler/test/rti/data/instantiation2.dart
+++ b/pkg/compiler/test/rti/data/instantiation2.dart
@@ -9,8 +9,8 @@
 
 typedef bool F<R>(R a);
 
-/*spec.class: B:explicit=[bool* Function(B.S*)*],indirect,needsArgs*/
-/*prod.class: B:indirect,needsArgs*/
+/*spec.class: B:explicit=[bool* Function(B.S*)*],implicit=[B.S],indirect,needsArgs*/
+/*prod.class: B:implicit=[B.S],indirect,needsArgs*/
 class B<S> {
   F<S> c;
 
diff --git a/pkg/compiler/test/rti/data/instantiation3.dart b/pkg/compiler/test/rti/data/instantiation3.dart
index 96e7c7a..f852f9f 100644
--- a/pkg/compiler/test/rti/data/instantiation3.dart
+++ b/pkg/compiler/test/rti/data/instantiation3.dart
@@ -10,7 +10,7 @@
 
 typedef int F<R>(R a);
 
-/*spec.class: B:direct,explicit=[int* Function(B.S*)*],needsArgs*/
+/*spec.class: B:direct,explicit=[int* Function(B.S*)*],implicit=[B.S],needsArgs*/
 class B<S> {
   F<S> c;
 
diff --git a/pkg/compiler/test/rti/data/instantiation4.dart b/pkg/compiler/test/rti/data/instantiation4.dart
index 7ec0433..be3b975 100644
--- a/pkg/compiler/test/rti/data/instantiation4.dart
+++ b/pkg/compiler/test/rti/data/instantiation4.dart
@@ -9,8 +9,8 @@
 
 typedef bool F<R>(R a);
 
-/*spec.class: B:direct,explicit=[bool* Function(B.S*)*],needsArgs*/
-/*prod.class: B:indirect,needsArgs*/
+/*spec.class: B:direct,explicit=[bool* Function(B.S*)*],implicit=[B.S],needsArgs*/
+/*prod.class: B:implicit=[B.S],indirect,needsArgs*/
 class B<S> {
   F<S> c;
 
diff --git a/pkg/compiler/test/rti/data/instantiation5.dart b/pkg/compiler/test/rti/data/instantiation5.dart
index 80063c5..525be33 100644
--- a/pkg/compiler/test/rti/data/instantiation5.dart
+++ b/pkg/compiler/test/rti/data/instantiation5.dart
@@ -10,7 +10,7 @@
 
 typedef int F<R>(R a);
 
-/*spec.member: method:indirect,needsArgs*/
+/*spec.member: method:implicit=[method.S],indirect,needsArgs*/
 method<S>() {
   F<S> c;
 
diff --git a/pkg/compiler/test/rti/data/instantiation6.dart b/pkg/compiler/test/rti/data/instantiation6.dart
index fdfa1d2..e596af2 100644
--- a/pkg/compiler/test/rti/data/instantiation6.dart
+++ b/pkg/compiler/test/rti/data/instantiation6.dart
@@ -9,7 +9,7 @@
 
 typedef bool F<R>(R a);
 
-/*member: method:indirect,needsArgs*/
+/*member: method:implicit=[method.S],indirect,needsArgs*/
 method<S>() {
   F<S> c;
 
diff --git a/pkg/compiler/test/rti/data/instantiation7.dart b/pkg/compiler/test/rti/data/instantiation7.dart
index fda2e4a..a47924b 100644
--- a/pkg/compiler/test/rti/data/instantiation7.dart
+++ b/pkg/compiler/test/rti/data/instantiation7.dart
@@ -20,7 +20,7 @@
 typedef int F2<R, P>(R a, P b, P c);
 typedef int F3<R, P, Q>(R a, P b, Q c);
 
-/*spec.member: method:indirect,needsArgs*/
+/*spec.member: method:implicit=[method.X,method.Y,method.Z],indirect,needsArgs*/
 method<X, Y, Z>() {
   F1<X> c1;
   F2<X, Y> c2;
diff --git a/pkg/compiler/test/rti/data/local_function_signatures_generic.dart b/pkg/compiler/test/rti/data/local_function_signatures_generic.dart
index dc86b33..7956fe4 100644
--- a/pkg/compiler/test/rti/data/local_function_signatures_generic.dart
+++ b/pkg/compiler/test/rti/data/local_function_signatures_generic.dart
@@ -89,8 +89,8 @@
 }
 
 method12() {
-  /*spec.direct,explicit=[local.T*],needsArgs,needsInst=[<dynamic>,<num*>,<num*>],needsSignature*/
-  /*prod.needsArgs,needsInst=[<dynamic>,<num*>,<num*>],needsSignature*/num local<T>(num n, T t) => null;
+  /*spec.direct,explicit=[local.T*],needsArgs,needsSignature*/
+  /*prod.needsArgs,needsSignature*/num local<T>(num n, T t) => null;
   return local;
 }
 
diff --git a/pkg/compiler/test/rti/data/method_signatures_generic.dart b/pkg/compiler/test/rti/data/method_signatures_generic.dart
index b3866f8..0d2c352 100644
--- a/pkg/compiler/test/rti/data/method_signatures_generic.dart
+++ b/pkg/compiler/test/rti/data/method_signatures_generic.dart
@@ -28,7 +28,7 @@
 }
 
 class Class4 {
-  /*spec.member: Class4.method6:direct,explicit=[method6.T*],needsArgs,needsInst=[<num*>,<num*>,<num*>,<num*>]*/
+  /*spec.member: Class4.method6:direct,explicit=[method6.T*],needsArgs*/
   num method6<T>(num n, T t) => null;
 }
 
@@ -38,7 +38,7 @@
 /*member: method8:*/
 T method8<T>(num n) => null;
 
-/*spec.member: method9:direct,explicit=[method9.T*],needsArgs,needsInst=[<num*>,<num*>,<num*>,<num*>]*/
+/*spec.member: method9:direct,explicit=[method9.T*],needsArgs*/
 num method9<T>(num n, T t) => null;
 
 @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/rti_need_test_helper.dart b/pkg/compiler/test/rti/rti_need_test_helper.dart
index 4170976..4206006 100644
--- a/pkg/compiler/test/rti/rti_need_test_helper.dart
+++ b/pkg/compiler/test/rti/rti_need_test_helper.dart
@@ -160,12 +160,11 @@
             features.addElement(Tags.selectors, selector);
           }
         });
-        rtiNeedBuilder.instantiationsNeedingTypeArgumentsForTesting?.forEach(
-            (GenericInstantiation instantiation, Set<Entity> targets) {
-          if (targets.contains(entity)) {
-            features.addElement(
-                Tags.instantiationsNeedTypeArguments, instantiation.shortText);
-          }
+        rtiNeedBuilder
+            .instantiatedEntitiesNeedingTypeArgumentsForTesting[entity]
+            ?.forEach((GenericInstantiation instantiation) {
+          features.addElement(
+              Tags.instantiationsNeedTypeArguments, instantiation.shortText);
         });
       }
 
diff --git a/tests/web/45046_test.dart b/tests/web/45046_test.dart
new file mode 100644
index 0000000..1e4f9b1
--- /dev/null
+++ b/tests/web/45046_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2021, 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:expect/expect.dart';
+
+class A {}
+
+class B extends A {}
+
+class Foo<T> {}
+
+T cast<T>(dynamic x) => x as T;
+
+void test(Foo<A> Function(dynamic) f) {
+  var foo = Foo<B>();
+  Expect.identical(foo, f(foo));
+}
+
+void main() {
+  test(cast);
+}
diff --git a/tests/web_2/45046_test.dart b/tests/web_2/45046_test.dart
new file mode 100644
index 0000000..7f5333e
--- /dev/null
+++ b/tests/web_2/45046_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2021, 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.
+
+// @dart = 2.7
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+class B extends A {}
+
+class Foo<T> {}
+
+T cast<T>(dynamic x) => x as T;
+
+void test(Foo<A> Function(dynamic) f) {
+  var foo = Foo<B>();
+  Expect.identical(foo, f(foo));
+}
+
+void main() {
+  test(cast);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 5b87bd5..132037c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 131
+PRERELEASE 132
 PRERELEASE_PATCH 0
\ No newline at end of file