Revert "[vm/aot/tfa] Analyze function calls"

This reverts commit 66d3eedb33d80273385bcba9aeaf988c07f3ef3f.

Reason for revert: breaks google3 (b/320642692)

Original change's description:
> [vm/aot/tfa] Analyze function calls
>
> This change adds analysis of function calls when closure target
> of a call can be inferred. Local functions are now analyzed separately
> from enclosing members. Inferred result type of function calls is now
> used in the AOT compiler.
>
> Time of AOT compilation step 2 (TFA) on a large Flutter application:
> Before: 59.448s
> After: 61.870s (+4%)
>
> Maintaining hierarchy of function types and analysis of all function
> calls is not feasible as it causes unbearable increase in AOT
> compilation time.
>
> TEST=existing
> Issue: https://github.com/dart-lang/sdk/issues/39692
>
> Change-Id: Ieb4d5dce23868b5ab5c87fa1e77e49b85fd656fe
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345083
> Reviewed-by: Slava Egorov <vegorov@google.com>
> Reviewed-by: Martin Kustermann <kustermann@google.com>
> Commit-Queue: Alexander Markov <alexmarkov@google.com>

Issue: https://github.com/dart-lang/sdk/issues/39692
Change-Id: Ieb9104f4263e19ef9e5bd749e935f6c2dbec3046
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/346780
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Emmanuel Pellereau <emmanuelp@google.com>
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 5f10826..e6ad923 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -36,6 +36,7 @@
 // === Precision ===
 // * Handle '==' with null.
 // * Special type inference rules for binary int operators.
+// * Support function types, better handle closures.
 // * Support generic types: substitution, passing type arguments. Figure out
 //   when generic type should be approximated.
 //
@@ -185,75 +186,11 @@
 
     return type;
   }
-
-  // Process [receiver].call(args) for calls via field or getter.
-  Type _processCallWithSubstitutedReceiver(
-      Type receiver, TypeFlowAnalysis typeFlowAnalysis) {
-    if (receiver == emptyType) {
-      return emptyType;
-    }
-    final closure = receiver.closure;
-    if (closure != null) {
-      final target = typeFlowAnalysis.getClosureCallMethod(closure);
-      if (!areArgumentsValidFor(target)) {
-        return emptyType;
-      }
-      return typeFlowAnalysis.applyCall(/* callSite = */ null,
-          DirectSelector(target), Args.withReceiver(args, receiver));
-    } else {
-      typeFlowAnalysis.applyCall(/* callSite = */ null, DynamicSelector.kCall,
-          Args.withReceiver(args, receiver),
-          isResultUsed: false, processImmediately: false);
-      return nullableAnyType;
-    }
-  }
-
-  // Returns true if the argument count and the names
-  // of optional arguments are valid for calling [member].
-  bool areArgumentsValidFor(Member member) {
-    if (member is Field ||
-        (member is Procedure && (member.isGetter || member.isSetter)) ||
-        selector.callKind == CallKind.PropertyGet) {
-      return true;
-    }
-    final function = member.function!;
-    final int positionalArguments = args.positionalCount;
-
-    final int firstParamIndex =
-        numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
-    final int requiredParameters =
-        firstParamIndex + function.requiredParameterCount;
-    if (positionalArguments < requiredParameters) {
-      return false;
-    }
-
-    final int positionalParameters =
-        firstParamIndex + function.positionalParameters.length;
-    if (positionalArguments > positionalParameters) {
-      return false;
-    }
-
-    if (args.names.isNotEmpty) {
-      // TODO(dartbug.com/32292): make sure parameters are sorted in kernel AST
-      // and iterate parameters in parallel, without lookup.
-      for (var name in args.names) {
-        if (findNamedParameter(function, name) == null) {
-          return false;
-        }
-      }
-    }
-
-    return true;
-  }
 }
 
 final class _DirectInvocation extends _Invocation {
   _DirectInvocation(DirectSelector selector, Args<Type> args)
-      : super(selector, args) {
-    if (!areArgumentsValidFor(selector.member)) {
-      throw 'Creating _DirectInvocation($selector, $args) with invalid args';
-    }
-  }
+      : super(selector, args);
 
   @override
   void init() {
@@ -318,10 +255,17 @@
 
       case CallKind.Method:
         // Call via field.
+        // TODO(alexmarkov): support function types and use inferred type
+        // to get more precise return type.
         fieldValue.isGetterUsed = true;
         final receiver = fieldValue.getValue(
             typeFlowAnalysis, field.isStatic ? null : args.values[0]);
-        return _processCallWithSubstitutedReceiver(receiver, typeFlowAnalysis);
+        if (receiver != emptyType) {
+          typeFlowAnalysis.applyCall(/* callSite = */ null,
+              DynamicSelector.kCall, new Args.withReceiver(args, receiver),
+              isResultUsed: false, processImmediately: false);
+        }
+        return nullableAnyType;
 
       case CallKind.FieldInitializer:
         assert(args.values.length == firstParamIndex);
@@ -349,68 +293,28 @@
   }
 
   Type _processFunction(TypeFlowAnalysis typeFlowAnalysis) {
-    Member member = selector.member!;
-    assert(areArgumentsValidFor(member));
-    Args<Type> args = this.args;
+    final Member member = selector.member!;
     if (selector.memberAgreesToCallKind(member)) {
-      final closure = typeFlowAnalysis._closureByCallMethod[member];
-      if (closure != null && closure.function == null) {
-        // Calling tear-off.
-        //
-        // Only factories can take type parameters as arguments in TFA.
-        // Invocation of a tear-off (its call method) doesn't take
-        // type parameters, but target member may need to receive
-        // type parameters if it happens to be a factory of generic class.
-        assert(numTypeParams(member) == 0);
-        // Get the actual target of the call.
-        member = closure.member;
-        if (member is Constructor) {
-          final receiver =
-              typeFlowAnalysis.addAllocatedClass(member.enclosingClass);
-          // Generative constructors do not take type parameters as arguments.
-          assert(numTypeParams(member) == 0);
-          args = Args.withReceiver(args, receiver);
-        } else if (member.isInstanceMember) {
-          final receiver = typeFlowAnalysis
-              .getSharedCapturedThis(member)
-              .getValue(typeFlowAnalysis.hierarchyCache, typeFlowAnalysis);
-          if (receiver == emptyType) {
-            return emptyType;
-          }
-          // Instance members do not take type parameters as arguments.
-          assert(numTypeParams(member) == 0);
-          args = Args.withReceiver(args, receiver);
-        } else {
-          // Drop closure receiver.
-          List<Type> argValues = args.values.sublist(1);
-          // Prepend type parameters if target member needs them.
-          final numTypeParameters = numTypeParams(member);
-          if (numTypeParameters != 0) {
-            argValues = [
-              for (int i = 0; i < numTypeParameters; ++i) unknownType,
-              ...argValues
-            ];
-          }
-          args = Args(argValues, names: args.names);
+      if (_argumentsValid()) {
+        final summary = typeFlowAnalysis.getSummary(member);
+        // If result type is known upfront (doesn't depend on the flow),
+        // set it eagerly so recursive invocations are able to use it.
+        final summaryResult = summary.result;
+        if (summaryResult is Type &&
+            !typeFlowAnalysis.workList._isPending(this)) {
+          assert(result == null || result == summaryResult);
+          setResult(typeFlowAnalysis, summaryResult);
         }
-        final result = typeFlowAnalysis.applyCall(/* callSite = */ null,
-            DirectSelector(member, callKind: CallKind.Method), args);
-        return (member is Constructor) ? args.receiver : result;
+        return summary.apply(
+            args, typeFlowAnalysis.hierarchyCache, typeFlowAnalysis);
+      } else {
+        assert(selector.callKind == CallKind.Method);
+        return _processNoSuchMethod(args.receiver, typeFlowAnalysis);
       }
-      final summary = typeFlowAnalysis.getSummary(member);
-      // If result type is known upfront (doesn't depend on the flow),
-      // set it eagerly so recursive invocations are able to use it.
-      final summaryResult = summary.result;
-      if (summaryResult is Type &&
-          !typeFlowAnalysis.workList._isPending(this)) {
-        assert(result == null || result == summaryResult);
-        setResult(typeFlowAnalysis, summaryResult);
-      }
-      return summary.apply(
-          args, typeFlowAnalysis.hierarchyCache, typeFlowAnalysis);
     } else {
       if (selector.callKind == CallKind.PropertyGet) {
-        // Taking tear-off.
+        // Tear-off.
+        // TODO(alexmarkov): capture receiver type
         assert((member is Procedure) &&
             !member.isGetter &&
             !member.isSetter &&
@@ -418,10 +322,6 @@
             !member.isAbstract);
         typeFlowAnalysis.addRawCall(new DirectSelector(member));
         typeFlowAnalysis._tearOffTaken.add(member);
-        if (member.isInstanceMember) {
-          typeFlowAnalysis.getSharedCapturedThis(member).setValue(
-              args.receiver, typeFlowAnalysis.hierarchyCache, typeFlowAnalysis);
-        }
         final Class? concreteClass = typeFlowAnalysis.target
             .concreteClosureClass(typeFlowAnalysis.coreTypes);
         if (concreteClass != null) {
@@ -441,17 +341,51 @@
         return nullableAnyType;
       } else {
         // Call via getter.
+        // TODO(alexmarkov): capture receiver type
         assert((selector.callKind == CallKind.Method) &&
             (member is Procedure) &&
             member.isGetter);
-        final receiver = typeFlowAnalysis.applyCall(
-            /* callSite = */ null,
-            DirectSelector(member, callKind: CallKind.PropertyGet),
-            Args([args.receiver]));
-        return _processCallWithSubstitutedReceiver(receiver, typeFlowAnalysis);
+        typeFlowAnalysis.addRawCall(
+            new DirectSelector(member, callKind: CallKind.PropertyGet));
+        typeFlowAnalysis.applyCall(/* callSite = */ null, DynamicSelector.kCall,
+            new Args.withReceiver(args, nullableAnyType),
+            isResultUsed: false, processImmediately: false);
+        return nullableAnyType;
       }
     }
   }
+
+  bool _argumentsValid() {
+    final member = selector.member!;
+    final function = member.function!;
+    final int positionalArguments = args.positionalCount;
+
+    final int firstParamIndex =
+        numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
+    final int requiredParameters =
+        firstParamIndex + function.requiredParameterCount;
+    if (positionalArguments < requiredParameters) {
+      return false;
+    }
+
+    final int positionalParameters =
+        firstParamIndex + function.positionalParameters.length;
+    if (positionalArguments > positionalParameters) {
+      return false;
+    }
+
+    if (args.names.isNotEmpty) {
+      // TODO(dartbug.com/32292): make sure parameters are sorted in kernel AST
+      // and iterate parameters in parallel, without lookup.
+      for (var name in args.names) {
+        if (findNamedParameter(function, name) == null) {
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
 }
 
 final class _DispatchableInvocation extends _Invocation {
@@ -486,16 +420,7 @@
     // Collect all possible targets for this invocation,
     // along with more accurate receiver types for each target.
     final targets = <Member, _ReceiverTypeBuilder>{};
-    final selector = this.selector;
-    if (selector is FunctionSelector) {
-      if (!_collectTargetsForFunctionCall(
-          args.receiver, targets, typeFlowAnalysis)) {
-        // No known closure target, approximate function call with static type.
-        return selector.staticResultType;
-      }
-    } else {
-      _collectTargetsForReceiverType(args.receiver, targets, typeFlowAnalysis);
-    }
+    _collectTargetsForReceiverType(args.receiver, targets, typeFlowAnalysis);
 
     // Calculate result as a union of results of direct invocations
     // corresponding to each target.
@@ -574,6 +499,7 @@
       });
     }
 
+    // TODO(alexmarkov): handle closures more precisely
     if ((selector is DynamicSelector) && (selector.name.text == "call")) {
       tracePrint("Possible closure call, result is dynamic");
       result = nullableAnyType;
@@ -594,10 +520,9 @@
       assert(receiver is! NullableType);
     }
 
-    final selector = this.selector;
     if (selector is InterfaceSelector) {
       final staticReceiverType = typeFlowAnalysis.hierarchyCache
-          .getTFClass(selector.member.enclosingClass!)
+          .getTFClass(selector.member!.enclosingClass!)
           .coneType;
       receiver = receiver.intersection(
           staticReceiverType, typeFlowAnalysis.hierarchyCache);
@@ -639,7 +564,7 @@
       TypeFlowAnalysis typeFlowAnalysis) {
     final Member? target = typeFlowAnalysis.hierarchyCache._nullTFClass
         .getDispatchTarget(selector);
-    if (target != null && areArgumentsValidFor(target)) {
+    if (target != null) {
       if (kPrintTrace) {
         tracePrint("Found $target for null receiver");
       }
@@ -656,34 +581,28 @@
     Member? target = cls.getDispatchTarget(selector);
 
     if (target != null) {
-      if (areArgumentsValidFor(target)) {
-        if (kPrintTrace) {
-          tracePrint("Found $target for concrete receiver $receiver");
-        }
-        _getReceiverTypeBuilder(targets, target).addConcreteType(receiver);
-        return;
-      } else {
-        assert(selector is DynamicSelector);
-        _recordMismatchedDynamicInvocation(target, typeFlowAnalysis);
-        // Fall through to add NSM marker.
-      }
-    }
-    if (typeFlowAnalysis.hierarchyCache.hasNonTrivialNoSuchMethod(cls)) {
       if (kPrintTrace) {
-        tracePrint("Found non-trivial noSuchMethod for receiver $receiver");
+        tracePrint("Found $target for concrete receiver $receiver");
       }
-      _getReceiverTypeBuilder(targets, kNoSuchMethodMarker)
-          .addConcreteType(receiver);
-    } else if (selector is DynamicSelector) {
-      if (kPrintTrace) {
-        tracePrint(
-            "Dynamic selector - adding noSuchMethod for receiver $receiver");
-      }
-      _getReceiverTypeBuilder(targets, kNoSuchMethodMarker)
-          .addConcreteType(receiver);
+      _getReceiverTypeBuilder(targets, target).addConcreteType(receiver);
     } else {
-      if (kPrintTrace) {
-        tracePrint("Target is not found for receiver $receiver");
+      if (typeFlowAnalysis.hierarchyCache.hasNonTrivialNoSuchMethod(cls)) {
+        if (kPrintTrace) {
+          tracePrint("Found non-trivial noSuchMethod for receiver $receiver");
+        }
+        _getReceiverTypeBuilder(targets, kNoSuchMethodMarker)
+            .addConcreteType(receiver);
+      } else if (selector is DynamicSelector) {
+        if (kPrintTrace) {
+          tracePrint(
+              "Dynamic selector - adding noSuchMethod for receiver $receiver");
+        }
+        _getReceiverTypeBuilder(targets, kNoSuchMethodMarker)
+            .addConcreteType(receiver);
+      } else {
+        if (kPrintTrace) {
+          tracePrint("Target is not found for receiver $receiver");
+        }
       }
     }
   }
@@ -691,23 +610,23 @@
   void _collectTargetsForSelector(Map<Member, _ReceiverTypeBuilder> targets,
       TypeFlowAnalysis typeFlowAnalysis) {
     Selector selector = this.selector;
-    if (selector is! DynamicSelector) {
-      selector = DynamicSelector(selector.callKind, selector.name);
+    if (selector is InterfaceSelector) {
+      // TODO(alexmarkov): support generic types and make sure inferred types
+      // are always same or better than static types.
+//      assert(selector.member.enclosingClass ==
+//          _typeFlowAnalysis.coreTypes.objectClass);
+      selector = new DynamicSelector(selector.callKind, selector.name);
     }
 
     final receiver = args.receiver;
-    final _DynamicTargetSet dynamicTargetSet =
-        typeFlowAnalysis.hierarchyCache.getDynamicTargetSet(selector);
+    final _DynamicTargetSet dynamicTargetSet = typeFlowAnalysis.hierarchyCache
+        .getDynamicTargetSet(selector as DynamicSelector);
 
     dynamicTargetSet.addDependentInvocation(this);
 
     assert(targets.isEmpty);
     for (Member target in dynamicTargetSet.targets) {
-      if (areArgumentsValidFor(target)) {
-        _getReceiverTypeBuilder(targets, target).addType(receiver);
-      } else {
-        _recordMismatchedDynamicInvocation(target, typeFlowAnalysis);
-      }
+      _getReceiverTypeBuilder(targets, target).addType(receiver);
     }
 
     // Conservatively include noSuchMethod if selector is not from Object,
@@ -717,38 +636,6 @@
     }
   }
 
-  bool _collectTargetsForFunctionCall(
-      Type receiver,
-      Map<Member, _ReceiverTypeBuilder> targets,
-      TypeFlowAnalysis typeFlowAnalysis) {
-    final closure = receiver.closure;
-    if (closure != null) {
-      final target = typeFlowAnalysis.getClosureCallMethod(closure);
-      if (areArgumentsValidFor(target)) {
-        if (kPrintTrace) {
-          tracePrint("Found closure target $closure");
-        }
-        _getReceiverTypeBuilder(targets, target)
-            .addConcreteType(receiver as ConcreteType);
-      }
-      return true;
-    }
-    return false;
-  }
-
-  void _recordMismatchedDynamicInvocation(
-      Member target, TypeFlowAnalysis typeFlowAnalysis) {
-    // Although target is not going to be called because of
-    // the mismatch in the number or names of arguments,
-    // it still participates in the dynamic lookup.
-    // So mark it as called dynamically so its signature is preserved.
-    if (selector.callKind != CallKind.PropertyGet) {
-      typeFlowAnalysis._methodsAndSettersCalledDynamically.add(target);
-    } else {
-      typeFlowAnalysis._gettersCalledDynamically.add(target);
-    }
-  }
-
   _ReceiverTypeBuilder _getReceiverTypeBuilder(
           Map<Member, _ReceiverTypeBuilder> targets, Member member) =>
       targets[member] ??= new _ReceiverTypeBuilder();
@@ -1121,7 +1008,7 @@
   final String name;
   Type value = emptyType;
 
-  _SharedVariableImpl(this.name);
+  _SharedVariableImpl(VariableDeclaration decl) : name = decl.name ?? '__tmp';
 
   @override
   Type getValue(
@@ -1338,6 +1225,7 @@
 // TODO(alexmarkov): Rename to _TypeHierarchyImpl.
 class _ClassHierarchyCache extends TypeHierarchy {
   final TypeFlowAnalysis _typeFlowAnalysis;
+  final CoreTypes coreTypes;
   final GenericInterfacesInfo genericInterfacesInfo;
   final Map<Class, _TFClassImpl> classes = <Class, _TFClassImpl>{};
   final Set<Class> allocatedClasses = Set<Class>();
@@ -1367,24 +1255,32 @@
       getTFClass(coreTypes.deprecatedNullClass);
 
   _ClassHierarchyCache(this._typeFlowAnalysis, this.genericInterfacesInfo,
-      super.coreTypes, super.target, super.soundNullSafety)
+      this.coreTypes, bool soundNullSafety)
       : objectNoSuchMethod =
-            coreTypes.index.getProcedure('dart:core', 'Object', 'noSuchMethod');
+            coreTypes.index.getProcedure('dart:core', 'Object', 'noSuchMethod'),
+        super(coreTypes, soundNullSafety);
 
   @override
   _TFClassImpl getTFClass(Class c) {
-    return classes[c] ??= _createOrdinaryClass(c);
+    return classes[c] ??= _createTFClass(c, null);
   }
 
-  _TFClassImpl _createOrdinaryClass(Class c) {
+  _TFClassImpl _createTFClass(Class c, RecordShape? recordShape) {
     final supertypes = Set<TFClass>();
-    for (var sup in c.supers) {
-      supertypes.addAll(getTFClass(sup.classNode).supertypes);
+    _TFClassImpl? superclass;
+    if (recordShape != null) {
+      // Record class has an ordinary class as its superclass.
+      superclass = getTFClass(c);
+      supertypes.addAll(superclass.supertypes);
+    } else {
+      for (var sup in c.supers) {
+        supertypes.addAll(getTFClass(sup.classNode).supertypes);
+      }
+      Class? superclassNode = c.superclass;
+      superclass = superclassNode != null ? getTFClass(superclassNode) : null;
     }
-    Class? superclassNode = c.superclass;
-    _TFClassImpl? superclass =
-        superclassNode != null ? getTFClass(superclassNode) : null;
-    return _TFClassImpl(++_classIdCounter, c, superclass, supertypes, null);
+    return _TFClassImpl(
+        ++_classIdCounter, c, superclass, supertypes, recordShape);
   }
 
   ConcreteType addAllocatedClass(_TFClassImpl cls) {
@@ -1423,16 +1319,12 @@
       recordClasses[shape] ??= _createRecordClass(shape);
 
   _TFClassImpl _createRecordClass(RecordShape shape) {
-    final Class c = target.getRecordImplementationClass(
+    final Class c = _typeFlowAnalysis.target.getRecordImplementationClass(
         coreTypes, shape.numPositionalFields, shape.namedFields);
     if (c.isAbstract) {
       throw 'Record class $c should not be abstract';
     }
-    // Record class has an ordinary class as its superclass.
-    _TFClassImpl superclass = getTFClass(c);
-    final supertypes = Set<TFClass>();
-    supertypes.addAll(superclass.supertypes);
-    return _TFClassImpl(++_classIdCounter, c, superclass, supertypes, shape);
+    return _createTFClass(c, shape);
   }
 
   Field getRecordField(RecordShape shape, String name) {
@@ -1722,9 +1614,6 @@
   final Map<Field, _FieldValue> _fieldValues = <Field, _FieldValue>{};
   final Map<VariableDeclaration, _SharedVariableImpl> _sharedCapturedVariables =
       {};
-  final Map<Member, _SharedVariableImpl> _sharedCapturedThisVariables = {};
-  final Map<Member, Closure> _closureByCallMethod = {};
-  final Map<Closure, Procedure> _callMethodByClosure = {};
   final Set<Member> _tearOffTaken = new Set<Member>();
   final Set<Member> _methodsAndSettersCalledDynamically = new Set<Member>();
   final Set<Member> _gettersCalledDynamically = new Set<Member>();
@@ -1744,8 +1633,8 @@
       : annotationMatcher =
             matcher ?? new ConstantPragmaAnnotationParser(coreTypes, target) {
     nativeCodeOracle = new NativeCodeOracle(libraryIndex, annotationMatcher);
-    hierarchyCache = new _ClassHierarchyCache(this, _genericInterfacesInfo,
-        coreTypes, target, target.flags.soundNullSafety);
+    hierarchyCache = new _ClassHierarchyCache(
+        this, _genericInterfacesInfo, coreTypes, target.flags.soundNullSafety);
     summaryCollector = new SummaryCollector(
         target,
         environment,
@@ -1768,14 +1657,7 @@
   Summary getSummary(Member member) {
     Summary? summary = _summaries[member];
     if (summary == null) {
-      final closure = _closureByCallMethod[member];
-      if (closure != null) {
-        summary =
-            summaryCollector.createSummary(closure.member, closure.function!);
-      } else {
-        summary = summaryCollector.createSummary(member, null);
-      }
-      _summaries[member] = summary;
+      _summaries[member] = summary = summaryCollector.createSummary(member);
       if (summary.statements.length >=
           _SelectorApproximation.largeSummarySize) {
         final DirectSelector selector =
@@ -1791,7 +1673,7 @@
     if (fieldValue == null) {
       Summary? typeGuardSummary = null;
       if (field.isCovariantByClass) {
-        typeGuardSummary = summaryCollector.createSummary(field, null,
+        typeGuardSummary = summaryCollector.createSummary(field,
             fieldSummaryType: FieldSummaryType.kFieldGuard);
       }
       fieldValue = _FieldValue(field, typeGuardSummary, hierarchyCache);
@@ -1957,7 +1839,7 @@
     if (kPrintDebug) {
       debugPrint("ADD RAW CALL: $selector");
     }
-    assert(selector is! DynamicSelector);
+    assert(selector is! DynamicSelector); // TODO(alexmarkov)
 
     applyCall(null, selector, summaryCollector.rawArguments(selector),
         isResultUsed: false, processImmediately: false);
@@ -1994,25 +1876,9 @@
     _tearOffTaken.add(target);
   }
 
-  @override
-  Procedure getClosureCallMethod(Closure closure) =>
-      _callMethodByClosure[closure] ??= _createCallMethod(closure);
-
-  Procedure _createCallMethod(Closure closure) {
-    final callMethod = closure.createCallMethod();
-    _closureByCallMethod[callMethod] = closure;
-    return callMethod;
-  }
-
   /// ---- Implementation of [SharedVariableBuilder] interface. ----
 
   @override
   SharedVariable getSharedVariable(VariableDeclaration variable) =>
-      _sharedCapturedVariables[variable] ??=
-          _SharedVariableImpl(variable.name ?? '__tmp');
-
-  @override
-  SharedVariable getSharedCapturedThis(Member member) =>
-      _sharedCapturedThisVariables[member] ??=
-          _SharedVariableImpl('${nodeToText(member)}::this');
+      _sharedCapturedVariables[variable] ??= _SharedVariableImpl(variable);
 }
diff --git a/pkg/vm/lib/transformations/type_flow/calls.dart b/pkg/vm/lib/transformations/type_flow/calls.dart
index 5c0edf7..035e176 100644
--- a/pkg/vm/lib/transformations/type_flow/calls.dart
+++ b/pkg/vm/lib/transformations/type_flow/calls.dart
@@ -163,7 +163,7 @@
   @override
   final Name name;
 
-  static final kCall = DynamicSelector(CallKind.Method, Name.callName);
+  static final kCall = new DynamicSelector(CallKind.Method, new Name('call'));
 
   DynamicSelector(CallKind callKind, this.name) : super(callKind);
 
@@ -182,32 +182,6 @@
   String toString() => 'dynamic ${_callKindPrefix}[${nodeToText(name)}]';
 }
 
-/// Function call with known function type.
-class FunctionSelector extends Selector {
-  final Type staticResultType;
-
-  @override
-  Name get name => Name.callName;
-
-  FunctionSelector(this.staticResultType) : super(CallKind.Method);
-
-  @override
-  Member? get member => null;
-
-  @override
-  int get hashCode => combineHashes(super.hashCode, staticResultType.hashCode);
-
-  @override
-  bool operator ==(other) =>
-      identical(this, other) ||
-      other is FunctionSelector &&
-          super == (other) &&
-          other.staticResultType == staticResultType;
-
-  @override
-  String toString() => 'function [=> ${staticResultType}]';
-}
-
 /// Arguments passed to a call, including implicit receiver argument.
 // TODO(alexmarkov): take type arguments into account
 class Args<T extends TypeExpr> {
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index a6d6fb0..d8a8581 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -39,9 +39,6 @@
 
   /// Record the fact that given member is torn off.
   void recordTearOff(Member target) {}
-
-  /// Artificial call method corresponding to the given [closure].
-  Procedure getClosureCallMethod(Closure closure);
 }
 
 class PragmaEntryPointsVisitor extends RecursiveVisitor {
diff --git a/pkg/vm/lib/transformations/type_flow/rta.dart b/pkg/vm/lib/transformations/type_flow/rta.dart
index d5d16e4..e0e6f7f 100644
--- a/pkg/vm/lib/transformations/type_flow/rta.dart
+++ b/pkg/vm/lib/transformations/type_flow/rta.dart
@@ -18,7 +18,7 @@
 import 'native_code.dart'
     show EntryPointsListener, NativeCodeOracle, PragmaEntryPointsVisitor;
 import 'protobuf_handler.dart' show ProtobufHandler;
-import 'types.dart' show Closure, ConcreteType, RecordShape, TFClass, Type;
+import 'types.dart' show TFClass, Type, ConcreteType, RecordShape;
 import 'utils.dart' show combineHashes;
 import '../pragma.dart' show ConstantPragmaAnnotationParser;
 
@@ -574,8 +574,4 @@
 
   @override
   void recordTearOff(Member target) => throw 'Unsupported operation';
-
-  @override
-  Procedure getClosureCallMethod(Closure closure) =>
-      throw 'Unsupported operation';
 }
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index 77ea809..8ca5d00 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -318,7 +318,9 @@
 
   Call(this.selector, this.args, this.staticResultType,
       bool isInstanceCreation) {
-    if (selector is! InterfaceSelector) {
+    // TODO(sjindel/tfa): Support inferring unchecked entry-points for dynamic
+    // and direct calls as well.
+    if (selector is DynamicSelector || selector is DirectSelector) {
       setUseCheckedEntry();
     }
     if (isInstanceCreation) {
@@ -446,13 +448,11 @@
     if (receiver is NullableType) {
       _flags |= kNullableReceiver;
     }
-    if (!receiverMayBeInt) {
-      final receiverIntIntersect =
-          receiver.intersection(typeHierarchy.intType, typeHierarchy);
-      if (receiverIntIntersect != emptyType &&
-          receiverIntIntersect != nullableEmptyType) {
-        _flags |= kReceiverMayBeInt;
-      }
+    final receiverIntIntersect =
+        receiver.intersection(typeHierarchy.intType, typeHierarchy);
+    if (receiverIntIntersect != emptyType &&
+        receiverIntIntersect != nullableEmptyType) {
+      _flags |= kReceiverMayBeInt;
     }
   }
 
@@ -901,11 +901,8 @@
 }
 
 abstract class SharedVariableBuilder {
-  /// [SharedVariable] representing captured [variable].
+  /// Returns [SharedVariable] representing captured [variable].
   SharedVariable getSharedVariable(VariableDeclaration variable);
-
-  /// [SharedVariable] representing captured `this` in [member].
-  SharedVariable getSharedCapturedThis(Member member);
 }
 
 /// Reads value from [variable].
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index 369572a..e6b90d1 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -296,13 +296,7 @@
   /// Number of variables at entry of active statements.
   List<int>? numVariablesAtActiveStatements;
 
-  bool isInsideLocalFunction = false;
-  bool isReceiverCaptured = false;
-
-  LocalFunction? summaryFunction;
-  int numVariablesAtSummaryFunctionEntry = 0;
-
-  _VariablesInfoCollector(Member member, this.summaryFunction) {
+  _VariablesInfoCollector(Member member) {
     member.accept(this);
   }
 
@@ -324,12 +318,6 @@
     numVariablesAtActiveStatements = null;
     final savedNumVariablesAtFunctionEntry = numVariablesAtFunctionEntry;
     numVariablesAtFunctionEntry = numVariables;
-    final savedIsInsideLocalFunction = isInsideLocalFunction;
-    isInsideLocalFunction = true;
-
-    if (node == summaryFunction) {
-      numVariablesAtSummaryFunctionEntry = numVariablesAtFunctionEntry;
-    }
 
     final function = node.function;
     function.accept(this);
@@ -337,7 +325,6 @@
     activeStatements = savedActiveStatements;
     numVariablesAtActiveStatements = savedNumVariablesAtActiveStatements;
     numVariablesAtFunctionEntry = savedNumVariablesAtFunctionEntry;
-    isInsideLocalFunction = savedIsInsideLocalFunction;
   }
 
   bool _isDeclaredBefore(int variableIndex, int entryDeclarationCounter) =>
@@ -376,12 +363,6 @@
     numVariablesAtActiveStatements!.removeLast();
   }
 
-  void _useReceiver() {
-    if (isInsideLocalFunction) {
-      isReceiverCaptured = true;
-    }
-  }
-
   @override
   visitConstructor(Constructor node) {
     // Need to visit parameters before initializers.
@@ -478,56 +459,6 @@
     visitList(node.cases, this);
     _endCollectingModifiedVariables();
   }
-
-  @override
-  visitSuperMethodInvocation(SuperMethodInvocation node) {
-    _useReceiver();
-    super.visitSuperMethodInvocation(node);
-  }
-
-  @override
-  visitSuperPropertyGet(SuperPropertyGet node) {
-    _useReceiver();
-    super.visitSuperPropertyGet(node);
-  }
-
-  @override
-  visitSuperPropertySet(SuperPropertySet node) {
-    _useReceiver();
-    super.visitSuperPropertySet(node);
-  }
-
-  @override
-  visitThisExpression(ThisExpression node) {
-    _useReceiver();
-    super.visitThisExpression(node);
-  }
-
-  @override
-  visitFieldInitializer(FieldInitializer node) {
-    assert(!isInsideLocalFunction);
-    super.visitFieldInitializer(node);
-  }
-
-  @override
-  visitRedirectingInitializer(RedirectingInitializer node) {
-    assert(!isInsideLocalFunction);
-    super.visitRedirectingInitializer(node);
-  }
-
-  @override
-  visitSuperInitializer(SuperInitializer node) {
-    assert(!isInsideLocalFunction);
-    super.visitSuperInitializer(node);
-  }
-
-  @override
-  visitTypeParameterType(TypeParameterType node) {
-    if (node.parameter.declaration is Class) {
-      _useReceiver();
-    }
-    super.visitTypeParameterType(node);
-  }
 }
 
 Iterable<Name> getSelectors(ClassHierarchy hierarchy, Class cls,
@@ -596,11 +527,14 @@
   Join? _returnValue;
 
   Member? _enclosingMember;
-  TypeExpr? _receiver;
+  Parameter? _receiver;
   late ConstantAllocationCollector constantAllocationCollector;
   late RuntimeTypeTranslatorImpl _translator;
   StaticTypeContext? _staticTypeContext;
 
+  // Currently only used for factory constructors.
+  Map<TypeParameter, TypeExpr>? _fnTypeVariables;
+
   SummaryCollector(
       this.target,
       this._environment,
@@ -620,48 +554,32 @@
         setters: true));
   }
 
-  Summary createSummary(Member member, LocalFunction? localFunction,
+  Summary createSummary(Member member,
       {fieldSummaryType = FieldSummaryType.kInitializer}) {
-    String summaryName = member.toString();
-    if (fieldSummaryType == FieldSummaryType.kFieldGuard) {
-      summaryName += ' (guard)';
-    }
-    if (localFunction != null) {
-      summaryName += '::${localFunctionName(localFunction)}';
-    }
+    final String summaryName =
+        "${member}${fieldSummaryType == FieldSummaryType.kFieldGuard ? " (guard)" : ""}";
     debugPrint("===== $summaryName =====");
     assert(!member.isAbstract);
     _enclosingMember = member;
 
-    if (localFunction == null) {
-      _protobufHandler?.beforeSummaryCreation(member);
-    }
+    _protobufHandler?.beforeSummaryCreation(member);
 
-    _staticTypeContext = StaticTypeContext(member, _environment);
-    _variablesInfo = _VariablesInfoCollector(member, localFunction);
-    _variableValues = List<TypeExpr?>.filled(_variablesInfo.numVariables, null);
-    _aggregateVariable = List<bool>.filled(_variablesInfo.numVariables, false);
+    _staticTypeContext = new StaticTypeContext(member, _environment);
+    _variablesInfo = new _VariablesInfoCollector(member);
+    _variableValues =
+        new List<TypeExpr?>.filled(_variablesInfo.numVariables, null);
+    _aggregateVariable =
+        new List<bool>.filled(_variablesInfo.numVariables, false);
     _capturedVariableReads = null;
-    _variableVersions = List<int>.filled(_variablesInfo.numVariables, 0);
+    _variableVersions = new List<int>.filled(_variablesInfo.numVariables, 0);
     _jumpHandlers = null;
     _returnValue = null;
     _receiver = null;
     _currentCondition = null;
 
-    // Summary collector doesn't visit outer functions, so
-    // captured variables declared in the outer functions should be
-    // "pre-declared" and marked as aggregate.
-    for (int i = 0;
-        i < _variablesInfo.numVariablesAtSummaryFunctionEntry;
-        ++i) {
-      if (_variablesInfo.isCaptured(_variablesInfo.varDeclarations[i])) {
-        _aggregateVariable[i] = true;
-      }
-    }
-
     final hasReceiver = hasReceiverArg(member);
 
-    if (member is Field && localFunction == null) {
+    if (member is Field) {
       if (hasReceiver) {
         final int numArgs =
             fieldSummaryType == FieldSummaryType.kInitializer ? 1 : 2;
@@ -671,18 +589,12 @@
         _receiver = _declareParameter("this",
             _environment.coreTypes.legacyRawType(member.enclosingClass!), null,
             isReceiver: true);
-        if (_variablesInfo.isReceiverCaptured) {
-          final capturedReceiver =
-              _sharedVariableBuilder.getSharedCapturedThis(_enclosingMember!);
-          final write = WriteVariable(capturedReceiver, _receiver!);
-          _summary.add(write);
-        }
       } else {
         _summary = new Summary(summaryName);
       }
 
-      _translator = new RuntimeTypeTranslatorImpl(
-          _environment.coreTypes, _summary, this, null, _genericInterfacesInfo);
+      _translator = new RuntimeTypeTranslatorImpl(_environment.coreTypes,
+          _summary, _receiver, null, _genericInterfacesInfo);
 
       if (fieldSummaryType == FieldSummaryType.kInitializer) {
         _summary.result = _visit(member.initializer!);
@@ -692,13 +604,10 @@
         _summary.result = _typeCheck(valueParam, member.type, member);
       }
     } else {
-      final FunctionNode function =
-          localFunction != null ? localFunction.function : member.function!;
+      final FunctionNode function = member.function!;
 
-      final numTypeParameters =
-          localFunction == null ? numTypeParams(member) : 0;
-      final firstParamIndex =
-          ((hasReceiver || localFunction != null) ? 1 : 0) + numTypeParameters;
+      final numTypeParameters = numTypeParams(member);
+      final firstParamIndex = (hasReceiver ? 1 : 0) + numTypeParameters;
 
       _summary = new Summary(summaryName,
           parameterCount: firstParamIndex +
@@ -709,32 +618,27 @@
           requiredParameterCount:
               firstParamIndex + function.requiredParameterCount);
 
-      Map<TypeParameter, TypeExpr>? fnTypeVariables;
       if (numTypeParameters > 0) {
-        fnTypeVariables = <TypeParameter, TypeExpr>{
+        _fnTypeVariables = <TypeParameter, TypeExpr>{
           for (TypeParameter tp in function.typeParameters)
             tp: _declareParameter(tp.name!, null, null)
         };
       }
 
-      if (localFunction != null) {
-        _declareParameter('#closure', const DynamicType(), null);
-      } else if (hasReceiver) {
+      if (hasReceiver) {
         // TODO(alexmarkov): subclass cone
-        _receiver = _declareParameter('this',
+        _receiver = _declareParameter("this",
             _environment.coreTypes.legacyRawType(member.enclosingClass!), null,
             isReceiver: true);
       }
 
       _translator = new RuntimeTypeTranslatorImpl(_environment.coreTypes,
-          _summary, this, fnTypeVariables, _genericInterfacesInfo);
+          _summary, _receiver, _fnTypeVariables, _genericInterfacesInfo);
 
       // Handle forwarding stubs. We need to check types against the types of
       // the forwarding stub's target, [member.concreteForwardingStubTarget].
       FunctionNode useTypesFrom = function;
-      if (member is Procedure &&
-          member.isForwardingStub &&
-          localFunction == null) {
+      if (member is Procedure && member.isForwardingStub) {
         final target = member.concreteForwardingStubTarget;
         if (target != null) {
           if (target is Field) {
@@ -767,18 +671,6 @@
             decl.initializer);
       }
 
-      if (hasReceiver && _variablesInfo.isReceiverCaptured) {
-        final capturedReceiver =
-            _sharedVariableBuilder.getSharedCapturedThis(_enclosingMember!);
-        if (localFunction != null) {
-          final read = _receiver = ReadVariable(capturedReceiver);
-          _summary.add(read);
-        } else {
-          final write = WriteVariable(capturedReceiver, _receiver!);
-          _summary.add(write);
-        }
-      }
-
       int count = firstParamIndex;
       for (int i = 0; i < function.positionalParameters.length; ++i) {
         final decl = function.positionalParameters[i];
@@ -803,7 +695,7 @@
       _returnValue = new Join("%result", function.returnType);
       _summary.add(_returnValue!);
 
-      if (member is Constructor && localFunction == null) {
+      if (member is Constructor) {
         // Make sure instance field initializers are visited.
         for (var f in member.enclosingClass.members) {
           if ((f is Field) &&
@@ -818,7 +710,6 @@
       }
 
       if (function.body == null) {
-        assert(localFunction == null);
         TypeExpr type = _nativeCodeOracle.handleNativeProcedure(
             member, _entryPointsListener, _typesBuilder, _translator);
         if (type is! ConcreteType && type is! Statement) {
@@ -839,7 +730,7 @@
 
       _currentCondition = null;
 
-      if (member.name.text == '==' && localFunction == null) {
+      if (member.name.text == '==') {
         // In addition to what is returned from the function body,
         // operator == performs implicit comparison with null
         // and returns bool.
@@ -876,11 +767,9 @@
       }
     }
 
-    if (localFunction == null) {
-      member.annotations.forEach(_visit);
-      member.enclosingClass?.annotations.forEach(_visit);
-      member.enclosingLibrary.annotations.forEach(_visit);
-    }
+    member.annotations.forEach(_visit);
+    member.enclosingClass?.annotations.forEach(_visit);
+    member.enclosingLibrary.annotations.forEach(_visit);
 
     _enclosingMember = null;
     _staticTypeContext = null;
@@ -889,7 +778,7 @@
     debugPrint(_summary);
     debugPrint("---------------------------------");
 
-    _SummaryNormalizer(_summary, _typesBuilder).normalize();
+    new _SummaryNormalizer(_summary, _typesBuilder).normalize();
 
     debugPrint("---------- NORM SUMMARY ---------");
     debugPrint(_summary);
@@ -915,18 +804,10 @@
     }
 
     if (hasReceiverArg(member)) {
-      final enclosingClass = member.enclosingClass;
-      if (enclosingClass == null) {
-        if (isArtificialNode(member) && member.name == Name.callName) {
-          // Approximate closure parameter of the artificial call method.
-          args.add(nullableAnyType);
-        } else {
-          throw 'Unexpected $member without enclosing class.';
-        }
-      } else {
-        final receiver = _typesBuilder.getTFClass(enclosingClass).coneType;
-        args.add(receiver);
-      }
+      assert(member.enclosingClass != null);
+      final receiver =
+          _typesBuilder.getTFClass(member.enclosingClass!).coneType;
+      args.add(receiver);
     }
 
     switch (selector.callKind) {
@@ -1068,8 +949,6 @@
     }
   }
 
-  TypeExpr _readReceiver() => _receiver!;
-
   TypeExpr _readVariable(VariableDeclaration variable, TreeNode node) {
     if (_variablesInfo.isCaptured(variable)) {
       assert(_aggregateVariable[_variablesInfo.varIndex[variable]!]);
@@ -1282,10 +1161,7 @@
     if (target is Procedure && node is Expression) {
       final returnType = target.function.returnType;
       final staticDartType = _staticDartType(node);
-      // TODO(dartbug.com/54200): static type cannot be trusted when
-      // function type is returned.
-      if (returnType is TypeParameterType ||
-          (returnType != staticDartType && returnType is! FunctionType)) {
+      if (returnType is TypeParameterType || returnType != staticDartType) {
         staticResultType = _typesBuilder.fromStaticType(staticDartType, true);
       }
     }
@@ -1480,6 +1356,25 @@
     return _stringType;
   }
 
+  void _handleNestedFunctionNode(FunctionNode node) {
+    final savedReturn = _returnValue;
+    _returnValue = null;
+    final savedCondition = _currentCondition;
+    final savedVariableValues = _variableValues;
+    _variableValues = _makeEmptyVariableValues();
+
+    // Approximate parameters of nested functions with static types.
+    // TODO(sjindel/tfa): Use TypeCheck for closure parameters.
+    node.positionalParameters.forEach(_declareVariableWithStaticType);
+    node.namedParameters.forEach(_declareVariableWithStaticType);
+
+    _visitWithoutResult(node.body!);
+
+    _currentCondition = savedCondition;
+    _variableValues = savedVariableValues;
+    _returnValue = savedReturn;
+  }
+
   TypeExpr _closureType(LocalFunction node) {
     final Class? concreteClass =
         target.concreteClosureClass(_environment.coreTypes);
@@ -1754,12 +1649,7 @@
 
   @override
   TypeExpr visitFunctionExpression(FunctionExpression node) {
-    final closure = Closure(_enclosingMember!, node);
-    final callMethod = _entryPointsListener.getClosureCallMethod(closure);
-    // In order to keep analysis scalable, targets of function calls are
-    // not calculated when target closure is not inferred.
-    // Raw call is added to account for such approximated function calls.
-    _entryPointsListener.addRawCall(DirectSelector(callMethod));
+    _handleNestedFunctionNode(node.function);
     return _closureType(node);
   }
 
@@ -1951,19 +1841,17 @@
 
   @override
   TypeExpr visitLocalFunctionInvocation(LocalFunctionInvocation node) {
-    final closure = Closure(_enclosingMember!, node.localFunction);
-    final callMethod = _entryPointsListener.getClosureCallMethod(closure);
-    final args = _visitArguments(anyInstanceType, node.arguments);
-    return _makeCall(node, DirectSelector(callMethod), args);
+    _visitArguments(null, node.arguments);
+    return _staticType(node);
   }
 
   @override
   TypeExpr visitFunctionInvocation(FunctionInvocation node) {
     final receiverNode = node.receiver;
     final receiver = _visit(receiverNode);
-    final args = _visitArguments(receiver, node.arguments);
-    final result = _makeCall(node, FunctionSelector(_staticType(node)), args);
-    _updateReceiverAfterCall(receiverNode, receiver, Name.callName);
+    _visitArguments(receiver, node.arguments);
+    final result = _staticType(node);
+    _updateReceiverAfterCall(receiverNode, receiver, Name('call'));
     return result;
   }
 
@@ -2070,7 +1958,8 @@
   @override
   TypeExpr visitSuperMethodInvocation(SuperMethodInvocation node) {
     assert(kPartialMixinResolution);
-    final args = _visitArguments(_readReceiver(), node.arguments);
+    assert(_receiver != null, "Should have receiver. Node: $node");
+    final args = _visitArguments(_receiver, node.arguments);
     // Re-resolve target due to partial mixin resolution.
     final target = _hierarchy.getDispatchTarget(_superclass, node.name);
     if (target == null) {
@@ -2085,7 +1974,7 @@
   @override
   TypeExpr visitSuperPropertyGet(SuperPropertyGet node) {
     assert(kPartialMixinResolution);
-    final args = new Args<TypeExpr>([_readReceiver()]);
+    final args = new Args<TypeExpr>([_receiver!]);
     // Re-resolve target due to partial mixin resolution.
     final target = _hierarchy.getDispatchTarget(_superclass, node.name);
     if (target == null) {
@@ -2100,7 +1989,7 @@
   TypeExpr visitSuperPropertySet(SuperPropertySet node) {
     assert(kPartialMixinResolution);
     final value = _visit(node.value);
-    final args = new Args<TypeExpr>([_readReceiver(), value]);
+    final args = new Args<TypeExpr>([_receiver!, value]);
     // Re-resolve target due to partial mixin resolution.
     final target =
         _hierarchy.getDispatchTarget(_superclass, node.name, setter: true);
@@ -2205,7 +2094,7 @@
 
   @override
   TypeExpr visitThisExpression(ThisExpression node) {
-    return _readReceiver();
+    return _receiver!;
   }
 
   @override
@@ -2360,12 +2249,7 @@
   TypeExpr? visitFunctionDeclaration(FunctionDeclaration node) {
     node.variable.annotations.forEach(_visit);
     _declareVariable(node.variable, _closureType(node));
-    final closure = Closure(_enclosingMember!, node);
-    final callMethod = _entryPointsListener.getClosureCallMethod(closure);
-    // In order to keep analysis scalable, targets of function calls are
-    // not calculated when target closure is not inferred.
-    // Raw call is added to account for such approximated function calls.
-    _entryPointsListener.addRawCall(DirectSelector(callMethod));
+    _handleNestedFunctionNode(node.function);
     return null;
   }
 
@@ -2570,7 +2454,7 @@
   @override
   TypeExpr? visitFieldInitializer(FieldInitializer node) {
     final value = _visit(node.value);
-    final args = new Args<TypeExpr>([_readReceiver(), value]);
+    final args = new Args<TypeExpr>([_receiver!, value]);
     _makeCall(
         node,
         new DirectSelector(node.field,
@@ -2581,14 +2465,14 @@
 
   @override
   TypeExpr? visitRedirectingInitializer(RedirectingInitializer node) {
-    final args = _visitArguments(_readReceiver(), node.arguments);
+    final args = _visitArguments(_receiver, node.arguments);
     _makeCall(node, new DirectSelector(node.target), args);
     return null;
   }
 
   @override
   TypeExpr? visitSuperInitializer(SuperInitializer node) {
-    final args = _visitArguments(_readReceiver(), node.arguments);
+    final args = _visitArguments(_receiver, node.arguments);
 
     Constructor? target = null;
     if (kPartialMixinResolution) {
@@ -2641,12 +2525,12 @@
     implements RuntimeTypeTranslator, DartTypeVisitor<TypeExpr> {
   final CoreTypes coreTypes;
   final Summary? summary;
-  final SummaryCollector? summaryCollector;
   final Map<TypeParameter, TypeExpr>? functionTypeVariables;
   final Map<DartType, TypeExpr> typesCache = <DartType, TypeExpr>{};
+  final TypeExpr? receiver;
   final GenericInterfacesInfo genericInterfacesInfo;
 
-  RuntimeTypeTranslatorImpl(this.coreTypes, this.summary, this.summaryCollector,
+  RuntimeTypeTranslatorImpl(this.coreTypes, this.summary, this.receiver,
       this.functionTypeVariables, this.genericInterfacesInfo) {}
 
   // Create a type translator which can be used only for types with no free type
@@ -2654,8 +2538,8 @@
   RuntimeTypeTranslatorImpl.forClosedTypes(
       this.coreTypes, this.genericInterfacesInfo)
       : summary = null,
-        summaryCollector = null,
-        functionTypeVariables = null {}
+        functionTypeVariables = null,
+        receiver = null {}
 
   TypeExpr instantiateConcreteType(ConcreteType type, List<DartType> typeArgs) {
     if (typeArgs.isEmpty) return type;
@@ -2803,7 +2687,7 @@
     if (nullability == Nullability.undetermined) {
       nullability = Nullability.nonNullable;
     }
-    final extract = Extract(summaryCollector!._readReceiver(), interfaceClass,
+    final extract = new Extract(receiver!, interfaceClass,
         interfaceClass.typeParameters.indexOf(type.parameter), nullability);
     summary!.add(extract);
     return extract;
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index 43e0d1f..2230312 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -7,10 +7,9 @@
 
 import 'dart:core' hide Type;
 
-import 'package:kernel/ast.dart' hide Variance;
+import 'package:kernel/ast.dart';
+
 import 'package:kernel/core_types.dart';
-import 'package:kernel/type_algebra.dart' show getFreshTypeParameters;
-import 'package:kernel/target/targets.dart' show Target;
 
 import 'utils.dart';
 
@@ -57,7 +56,7 @@
             !member.isStatic &&
             !member.isAbstract));
     return _concreteTypeWithAttributes(
-        TypeAttributes._(null, Closure(member, function)));
+        TypeAttributes._(null, Closure._(member, function)));
   }
 
   /// Returns ConeType corresponding to this class.
@@ -66,13 +65,8 @@
   bool get isRecord => recordShape != null;
 
   /// Tests if [this] is a subtype of [other].
-  bool isSubtypeOf(TFClass other) {
-    final result = identical(this, other) || supertypes.contains(other);
-    if (kPrintTrace) {
-      tracePrint("isSubtype sub $this, sup $other = $result");
-    }
-    return result;
-  }
+  bool isSubtypeOf(TFClass other) =>
+      identical(this, other) || supertypes.contains(other);
 
   @override
   int get hashCode => id;
@@ -98,7 +92,7 @@
               target.isStatic &&
               !target.isGetter &&
               !target.isSetter));
-      return Closure(target, null);
+      return Closure._(target, null);
     } else if (c is TypedefTearOffConstant) {
       throw 'Unexpected TypedefTearOffConstant $c';
     }
@@ -191,10 +185,9 @@
 
 abstract class TypesBuilder {
   final CoreTypes coreTypes;
-  final Target target;
   final bool soundNullSafety;
 
-  TypesBuilder(this.coreTypes, this.target, this.soundNullSafety);
+  TypesBuilder(this.coreTypes, this.soundNullSafety);
 
   /// Return [TFClass] corresponding to the given [classNode].
   TFClass getTFClass(Class classNode);
@@ -230,6 +223,7 @@
     } else if (type is NeverType || type is NullType) {
       result = emptyType;
     } else if (type is FunctionType) {
+      // TODO(alexmarkov): support inference of function types
       result = functionType;
     } else if (type is RecordType) {
       result = getRecordType(RecordShape(type), false);
@@ -275,11 +269,14 @@
 /// Abstract interface to type hierarchy information used by types.
 abstract class TypeHierarchy extends TypesBuilder
     implements GenericInterfacesInfo {
-  TypeHierarchy(CoreTypes coreTypes, Target target, bool soundNullSafety)
-      : super(coreTypes, target, soundNullSafety);
+  TypeHierarchy(CoreTypes coreTypes, bool soundNullSafety)
+      : super(coreTypes, soundNullSafety);
 
   /// Test if [sub] is a subtype of [sup].
   bool isSubtype(Class sub, Class sup) {
+    if (kPrintTrace) {
+      tracePrint("isSubtype for sub = $sub, sup = $sup");
+    }
     return identical(sub, sup) || getTFClass(sub).isSubtypeOf(getTFClass(sup));
   }
 
@@ -325,8 +322,6 @@
 
   Class? getConcreteClass(TypeHierarchy typeHierarchy) => null;
 
-  Closure? get closure => null;
-
   bool isSubtypeOf(TFClass cls) => false;
 
   // Returns 'true' if this type will definitely pass a runtime type-check
@@ -595,23 +590,6 @@
   String toString() => "_T ${types}";
 
   @override
-  Class? getConcreteClass(TypeHierarchy typeHierarchy) {
-    Class? result;
-    for (final t in types) {
-      final cls = t.getConcreteClass(typeHierarchy);
-      if (cls == null) {
-        return null;
-      }
-      if (result == null) {
-        result = cls;
-      } else if (result != cls) {
-        return null;
-      }
-    }
-    return result;
-  }
-
-  @override
   bool isSubtypeOf(TFClass cls) =>
       types.every((ConcreteType t) => t.isSubtypeOf(cls));
 
@@ -966,22 +944,7 @@
         return emptyType;
       }
     } else if (other is SetType) {
-      final list = <ConcreteType>[];
-      for (ConcreteType t in other.types) {
-        if (t.cls.isSubtypeOf(this.cls)) {
-          list.add(t);
-        }
-      }
-      final size = list.length;
-      if (size == 0) {
-        return emptyType;
-      } else if (size == 1) {
-        return list.single;
-      } else if (size == other.types.length) {
-        return other;
-      } else {
-        return SetType(list);
-      }
+      return other;
     } else {
       throw 'Unexpected type $other';
     }
@@ -998,45 +961,7 @@
   final Member member;
   final LocalFunction? function;
 
-  Closure(this.member, this.function);
-
-  // Create a synthetic 'call' method.
-  Procedure createCallMethod() {
-    final localFunction = this.function;
-    final functionNode =
-        (localFunction != null) ? localFunction.function : member.function!;
-    final typeParameters = (localFunction == null && member is Constructor)
-        ? member.enclosingClass!.typeParameters
-        : functionNode.typeParameters;
-    final freshTypeParameters = getFreshTypeParameters(typeParameters);
-    List<VariableDeclaration> convertParameters(
-            List<VariableDeclaration> params) =>
-        [
-          for (final p in params)
-            VariableDeclaration(p.name,
-                initializer: (p.initializer != null)
-                    ? ConstantExpression(
-                        (p.initializer as ConstantExpression).constant)
-                    : null,
-                type: freshTypeParameters.substitute(p.type),
-                flags: p.flags)
-        ];
-    return Procedure(
-        Name.callName,
-        ProcedureKind.Method,
-        FunctionNode(null,
-            typeParameters: freshTypeParameters.freshTypeParameters,
-            positionalParameters:
-                convertParameters(functionNode.positionalParameters),
-            namedParameters: convertParameters(functionNode.namedParameters),
-            requiredParameterCount: functionNode.requiredParameterCount,
-            returnType:
-                freshTypeParameters.substitute(functionNode.returnType)),
-        isExternal: true,
-        isSynthetic: true,
-        isStatic: false,
-        fileUri: artificialNodeUri);
-  }
+  Closure._(this.member, this.function);
 
   @override
   int get hashCode => combineHashes(member.hashCode, function.hashCode);
@@ -1054,7 +979,19 @@
     if (function == null) {
       return 'tear-off ${nodeToText(member)}';
     }
-    return localFunctionName(function);
+    switch (function) {
+      case FunctionDeclaration():
+        return function.variable.name!;
+      case FunctionExpression():
+        final location = function.location;
+        return '<anonymous closure' +
+            (location != null
+                ? ' at ${location.file.pathSegments.last}:${location.line}'
+                : '') +
+            '>';
+      default:
+        throw 'Unexpected local function ${function.runtimeType} $function';
+    }
   }
 }
 
@@ -1139,6 +1076,7 @@
         numImmediateTypeArgs =
             typeArgs_ != null ? cls.classNode.typeParameters.length : 0,
         super._() {
+    // TODO(alexmarkov): support closures
     assert(!cls.classNode.isAbstract);
     assert(typeArgs == null || cls.classNode.typeParameters.isNotEmpty);
     assert(typeArgs == null || typeArgs!.any((t) => t is RuntimeType));
@@ -1154,9 +1092,6 @@
       filterArtificialNode(cls.classNode);
 
   @override
-  Closure? get closure => attributes?.closure;
-
-  @override
   bool isSubtypeOf(TFClass other) => cls.isSubtypeOf(other);
 
   bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
diff --git a/pkg/vm/lib/transformations/type_flow/utils.dart b/pkg/vm/lib/transformations/type_flow/utils.dart
index 23e8dbe..2f04c48 100644
--- a/pkg/vm/lib/transformations/type_flow/utils.dart
+++ b/pkg/vm/lib/transformations/type_flow/utils.dart
@@ -440,19 +440,3 @@
 // Returns [node] or null, if node is artificial.
 T? filterArtificialNode<T extends TreeNode>(T? node) =>
     (node == null || isArtificialNode(node)) ? null : node;
-
-String localFunctionName(LocalFunction function) {
-  switch (function) {
-    case FunctionDeclaration():
-      return function.variable.name!;
-    case FunctionExpression():
-      final location = function.location;
-      return '<anonymous closure' +
-          (location != null
-              ? ' at ${location.file.pathSegments.last}:${location.line}'
-              : '') +
-          '>';
-    default:
-      throw 'Unexpected local function ${function.runtimeType} $function';
-  }
-}
diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
index 005ba81..c18e5d6 100644
--- a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
+++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
@@ -21,7 +21,6 @@
 import 'package:vm/transformations/type_flow/summary.dart';
 import 'package:vm/transformations/type_flow/summary_collector.dart';
 import 'package:vm/transformations/type_flow/types.dart';
-import 'package:vm/transformations/type_flow/utils.dart';
 
 import '../../common_test_utils.dart';
 
@@ -31,8 +30,8 @@
   final Map<Class, TFClass> _classes = <Class, TFClass>{};
   int _classIdCounter = 0;
 
-  FakeTypesBuilder(CoreTypes coreTypes, Target target)
-      : super(coreTypes, target, /*soundNullSafety=*/ true);
+  FakeTypesBuilder(CoreTypes coreTypes)
+      : super(coreTypes, /*soundNullSafety=*/ true);
 
   @override
   TFClass getTFClass(Class c) =>
@@ -71,14 +70,11 @@
 
   @override
   void recordTearOff(Member target) {}
-
-  @override
-  Procedure getClosureCallMethod(Closure closure) => closure.createCallMethod();
 }
 
 class FakeSharedVariable implements SharedVariable {
-  final String name;
-  FakeSharedVariable(this.name);
+  final VariableDeclaration decl;
+  FakeSharedVariable(this.decl);
 
   @override
   Type getValue(TypeHierarchy typeHierarchy, CallHandler callHandler) =>
@@ -90,31 +86,24 @@
       throw 'Not implemented';
 
   @override
-  String toString() => name;
+  String toString() => decl.name ?? '__tmp';
 }
 
 class FakeSharedVariableBuilder implements SharedVariableBuilder {
   final Map<VariableDeclaration, SharedVariable> _sharedVariables = {};
-  final Map<Member, SharedVariable> _sharedCapturedThisVariables = {};
 
   @override
   SharedVariable getSharedVariable(VariableDeclaration variable) =>
-      _sharedVariables[variable] ??=
-          FakeSharedVariable(variable.name ?? '__tmp');
-  @override
-  SharedVariable getSharedCapturedThis(Member member) =>
-      _sharedCapturedThisVariables[member] ??=
-          FakeSharedVariable('${nodeToText(member)}::this');
+      _sharedVariables[variable] ??= FakeSharedVariable(variable);
 }
 
 class PrintSummaries extends RecursiveVisitor {
   late SummaryCollector _summaryCollector;
   final StringBuffer _buf = new StringBuffer();
-  Member? _enclosingMember;
 
   PrintSummaries(Target target, TypeEnvironment environment,
       CoreTypes coreTypes, ClosedWorldClassHierarchy hierarchy) {
-    final typesBuilder = FakeTypesBuilder(coreTypes, target);
+    final typesBuilder = FakeTypesBuilder(coreTypes);
     final annotationParser = ConstantPragmaAnnotationParser(coreTypes, target);
     _summaryCollector = SummaryCollector(
         target,
@@ -133,39 +122,15 @@
     return _buf.toString();
   }
 
-  void printSummary(Member member, LocalFunction? localFunction) {
-    String name;
-    if (localFunction != null) {
-      name = localFunctionName(localFunction);
-    } else {
-      name = qualifiedMemberNameToString(member);
-    }
-    _buf.writeln('------------ $name ------------');
-    _buf.writeln(_summaryCollector.createSummary(member, localFunction));
-  }
-
   @override
   defaultMember(Member member) {
     if (!member.isAbstract &&
         !((member is Field) && (member.initializer == null))) {
-      printSummary(member, null);
-      _enclosingMember = member;
-      super.defaultMember(member);
-      _enclosingMember = null;
+      _buf.writeln(
+          "------------ ${qualifiedMemberNameToString(member)} ------------");
+      _buf.writeln(_summaryCollector.createSummary(member));
     }
   }
-
-  @override
-  visitFunctionExpression(FunctionExpression node) {
-    printSummary(_enclosingMember!, node);
-    super.visitFunctionExpression(node);
-  }
-
-  @override
-  visitFunctionDeclaration(FunctionDeclaration node) {
-    printSummary(_enclosingMember!, node);
-    super.visitFunctionDeclaration(node);
-  }
 }
 
 class TestOptions {
diff --git a/pkg/vm/test/transformations/type_flow/types_test.dart b/pkg/vm/test/transformations/type_flow/types_test.dart
index 6c88211..a39a3db 100644
--- a/pkg/vm/test/transformations/type_flow/types_test.dart
+++ b/pkg/vm/test/transformations/type_flow/types_test.dart
@@ -6,10 +6,8 @@
 
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart';
-import 'package:kernel/target/targets.dart' show Target, TargetFlags;
 import 'package:kernel/testing/mock_sdk_component.dart';
 import 'package:test/test.dart';
-import 'package:vm/target/vm.dart';
 import 'package:vm/transformations/type_flow/types.dart';
 
 class TestTypeHierarchy extends TypeHierarchy {
@@ -17,9 +15,8 @@
   final Map<Class, Type> specializations;
   int classIdCounter = 0;
 
-  TestTypeHierarchy(
-      CoreTypes coreTypes, Target target, this.classes, this.specializations)
-      : super(coreTypes, target, /*soundNullSafety=*/ true);
+  TestTypeHierarchy(CoreTypes coreTypes, this.classes, this.specializations)
+      : super(coreTypes, /*soundNullSafety=*/ true);
 
   @override
   Type specializeTypeCone(TFClass base, {bool allowWideCone = false}) {
@@ -43,18 +40,9 @@
       throw "flattenedTypeArgumentsFor is not supported in the types test.";
 }
 
-class TestingTarget extends VmTarget {
-  TestingTarget() : super(TargetFlags());
-
-  // Mock SDK doesn't have _Closure class, use Function.
-  @override
-  Class concreteClosureClass(CoreTypes coreTypes) => coreTypes.functionClass;
-}
-
 main() {
   final Component component = createMockSdkComponent();
-  final CoreTypes coreTypes = CoreTypes(component);
-  final Target target = TestingTarget();
+  final CoreTypes coreTypes = new CoreTypes(component);
 
   test('types-builder', () {
     final Class c1 = new Class(name: 'C1', fileUri: dummyUri);
@@ -63,7 +51,7 @@
         typeParameters: [new TypeParameter('E')],
         fileUri: dummyUri);
 
-    final TypesBuilder tb = new TestTypeHierarchy(coreTypes, target, {}, {});
+    final TypesBuilder tb = new TestTypeHierarchy(coreTypes, {}, {});
     final tfc1 = tb.getTFClass(c1);
     final tfc2 = tb.getTFClass(c2);
     final tfFunction = tb.getTFClass(coreTypes.functionClass);
@@ -259,7 +247,6 @@
 
     final hierarchy = new TestTypeHierarchy(
         coreTypes,
-        target,
         // classes
         {
           c1: tfc1,
diff --git a/pkg/vm/testcases/transformations/ffi/as_function.dart.aot.expect b/pkg/vm/testcases/transformations/ffi/as_function.dart.aot.expect
index a45f3d7..233545a 100644
--- a/pkg/vm/testcases/transformations/ffi/as_function.dart.aot.expect
+++ b/pkg/vm/testcases/transformations/ffi/as_function.dart.aot.expect
@@ -15,7 +15,7 @@
       return ffi::_ffiCall<void>(#ffiTarget0);
     }
   } =>#ffiClosure0;
-  [@vm.inferred-type.metadata=!? (receiver not int)] function(){() → void};
+  function(){() → void};
 }
 [@vm.unboxing-info.metadata=()->i]static method testIntInt() → dynamic {
   final ffi::Pointer<ffi::NativeFunction<(ffi::Int64) → ffi::Int32>> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer] ffi::Pointer::fromAddress<ffi::NativeFunction<(ffi::Int64) → ffi::Int32>>(3735928559);
@@ -24,10 +24,10 @@
     @#C6
     function #ffiClosure1(core::int arg1) → core::int {
       _in::_nativeEffect(arg1);
-      return [@vm.inferred-type.metadata=int] ffi::_ffiCall<core::int>(#ffiTarget1);
+      return ffi::_ffiCall<core::int>(#ffiTarget1);
     }
   } =>#ffiClosure1;
-  return [@vm.inferred-type.metadata=int (receiver not int)] function(42){(core::int) → core::int};
+  return function(42){(core::int) → core::int};
 }
 [@vm.unboxing-info.metadata=()->i]static method testLeaf5Args() → dynamic {
   final ffi::Pointer<ffi::NativeFunction<(ffi::Int32, ffi::Int32, ffi::Int32, ffi::Int32, ffi::Int32) → ffi::Int32>> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer] ffi::Pointer::fromAddress<ffi::NativeFunction<(ffi::Int32, ffi::Int32, ffi::Int32, ffi::Int32, ffi::Int32) → ffi::Int32>>(3735928559);
@@ -40,10 +40,10 @@
       _in::_nativeEffect(arg3);
       _in::_nativeEffect(arg4);
       _in::_nativeEffect(arg5);
-      return [@vm.inferred-type.metadata=int] ffi::_ffiCall<core::int>(#ffiTarget2);
+      return ffi::_ffiCall<core::int>(#ffiTarget2);
     }
   } =>#ffiClosure2;
-  return [@vm.inferred-type.metadata=int (receiver not int)] function(1, 2, 3, 4, 5){(core::int, core::int, core::int, core::int, core::int) → core::int};
+  return function(1, 2, 3, 4, 5){(core::int, core::int, core::int, core::int, core::int) → core::int};
 }
 static method main() → void {
   self::testVoidNoArg();
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_late_initializer.dart.aot.expect b/pkg/vm/testcases/transformations/ffi/finalizable_late_initializer.dart.aot.expect
index 29230b8..cc0cd7c 100644
--- a/pkg/vm/testcases/transformations/ffi/finalizable_late_initializer.dart.aot.expect
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_late_initializer.dart.aot.expect
@@ -15,15 +15,15 @@
   [@vm.inferred-type.metadata=#lib::Foo?] self::Foo? :foo:finalizableValue;
   function #foo#initializer() → self::Foo
     return :foo:finalizableValue = new self::Foo::•();
-  [@vm.inferred-type.metadata=#lib::Foo] late final self::Foo foo = [@vm.inferred-type.metadata=#lib::Foo (receiver not int)] #foo#initializer(){() → self::Foo};
-  [@vm.inferred-type.metadata=!? (receiver not int)](() → Null {
+  [@vm.inferred-type.metadata=#lib::Foo] late final self::Foo foo = #foo#initializer(){() → self::Foo};
+  (() → Null {
     core::print(foo);
     _in::reachabilityFence(:foo:finalizableValue);
   })(){() → Null};
   [@vm.inferred-type.metadata=#lib::Foo?] self::Foo? :foo2:finalizableValue;
   function #foo2#initializer() → self::Foo
     return :foo2:finalizableValue = new self::Foo::•();
-  late final self::Foo foo2 = [@vm.inferred-type.metadata=#lib::Foo (receiver not int)] #foo2#initializer(){() → self::Foo};
+  late final self::Foo foo2 = #foo2#initializer(){() → self::Foo};
   if([@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart.core::_IntegerImplementation.%] [@vm.inferred-type.metadata=int (skip check)] [@vm.direct-call.metadata=dart.core::DateTime.millisecond] [@vm.inferred-type.metadata=int] new core::DateTime::now().{core::DateTime::millisecond}{core::int}.{core::num::%}(2){(core::num) → core::int} =={core::num::==}{(core::Object) → core::bool} 0) {
     core::print(foo2);
   }
diff --git a/pkg/vm/testcases/transformations/ffi/native_callable.dart.aot.expect b/pkg/vm/testcases/transformations/ffi/native_callable.dart.aot.expect
index 5b401ce..93c9361 100644
--- a/pkg/vm/testcases/transformations/ffi/native_callable.dart.aot.expect
+++ b/pkg/vm/testcases/transformations/ffi/native_callable.dart.aot.expect
@@ -21,7 +21,7 @@
 static method testNativeCallableListener() → void {
   final ffi::NativeCallable<(ffi::Int32) → ffi::Void> callback = block {
     final ffi::NativeCallable<(ffi::Int32) → ffi::Void> #t1 = new ffi::_NativeCallableListener::•<(ffi::Int32) → ffi::Void>((final core::List<dynamic> args) → void
-      [@vm.inferred-type.metadata=!? (receiver not int)] #C1(args.{core::List::[]}(0){(core::int) → dynamic}){(ffi::Int32) → ffi::Void};
+      #C1(args.{core::List::[]}(0){(core::int) → dynamic}){(ffi::Int32) → ffi::Void};
 , "NativeCallable(ConstantExpression(printInt))");
     [@vm.call-site-attributes.metadata=receiverType:dart.ffi::NativeCallable<dart.ffi::Void Function(dart.ffi::Int32)>] [@vm.direct-call.metadata=dart.ffi::_NativeCallableBase._pointer] #t1.{ffi::_NativeCallableBase::_pointer} = [@vm.inferred-type.metadata=dart.ffi::Pointer] ffi::_createNativeCallableListener<ffi::NativeFunction<(ffi::Int32) → ffi::Void>>(ffi::_nativeAsyncCallbackFunction<(ffi::Int32) → ffi::Void>(), [@vm.direct-call.metadata=dart.ffi::_NativeCallableListener._port] [@vm.inferred-type.metadata=dart.isolate::_RawReceivePort] #t1.{ffi::_NativeCallableListener::_port}{iso::RawReceivePort});
   } =>#t1;
@@ -31,10 +31,10 @@
 [@vm.closure-id=2]static method testNativeCallableListenerClosure() → void {
   [@vm.inferred-type.metadata=dart.core::_Smi (value: 123)] core::int j = 123;
 [@vm.closure-id=1]  function closure(core::int i) → void
-    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::print([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(j){(core::num) → core::int});
+    return core::print([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(j){(core::num) → core::int});
   final ffi::NativeCallable<(ffi::Int32) → ffi::Void> callback = block {
     final ffi::NativeCallable<(ffi::Int32) → ffi::Void> #t2 = new ffi::_NativeCallableListener::•<(ffi::Int32) → ffi::Void>([@vm.closure-id=2](final core::List<dynamic> args) → void
-      [@vm.inferred-type.metadata=!? (receiver not int)] closure(args.{core::List::[]}(0){(core::int) → dynamic}){(ffi::Int32) → ffi::Void};
+      closure(args.{core::List::[]}(0){(core::int) → dynamic}){(ffi::Int32) → ffi::Void};
 , "NativeCallable(VariableGetImpl(closure))");
     [@vm.call-site-attributes.metadata=receiverType:dart.ffi::NativeCallable<dart.ffi::Void Function(dart.ffi::Int32)>] [@vm.direct-call.metadata=dart.ffi::_NativeCallableBase._pointer] #t2.{ffi::_NativeCallableBase::_pointer} = [@vm.inferred-type.metadata=dart.ffi::Pointer] ffi::_createNativeCallableListener<ffi::NativeFunction<(ffi::Int32) → ffi::Void>>(ffi::_nativeAsyncCallbackFunction<(ffi::Int32) → ffi::Void>(), [@vm.direct-call.metadata=dart.ffi::_NativeCallableListener._port] [@vm.inferred-type.metadata=dart.isolate::_RawReceivePort] #t2.{ffi::_NativeCallableListener::_port}{iso::RawReceivePort});
   } =>#t2;
@@ -49,7 +49,7 @@
 static method testNativeCallableIsolateLocalVoidClosure() → void {
   [@vm.inferred-type.metadata=dart.core::_Smi (value: 123)] core::int j = 123;
   function closure(core::int i) → void
-    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::print([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(j){(core::num) → core::int});
+    return core::print([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(j){(core::num) → core::int});
   final ffi::NativeCallable<(ffi::Int32) → ffi::Void> callback = new ffi::_NativeCallableIsolateLocal::•<(ffi::Int32) → ffi::Void>([@vm.inferred-type.metadata=dart.ffi::Pointer] ffi::_createNativeCallableIsolateLocal<ffi::NativeFunction<(ffi::Int32) → ffi::Void>>(ffi::_nativeIsolateLocalCallbackFunction<(ffi::Int32) → ffi::Void>(null), closure, true));
   core::print([@vm.direct-call.metadata=dart.ffi::_NativeCallableBase.nativeFunction] [@vm.inferred-type.metadata=dart.ffi::Pointer] callback.{ffi::NativeCallable::nativeFunction}{ffi::Pointer<ffi::NativeFunction<(ffi::Int32) → ffi::Void>>});
   [@vm.direct-call.metadata=dart.ffi::_NativeCallableBase.close] [@vm.inferred-type.metadata=!? (skip check)] callback.{ffi::NativeCallable::close}(){() → void};
@@ -64,7 +64,7 @@
 static method testNativeCallableIsolateLocalPointerClosure() → void {
   [@vm.inferred-type.metadata=dart.core::_Smi (value: 123)] core::int j = 123;
   function closure(core::int i) → ffi::Pointer<ffi::NativeType>
-    return [@vm.inferred-type.metadata=dart.ffi::Pointer] ffi::Pointer::fromAddress<ffi::NativeType>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(j){(core::num) → core::int});
+    return ffi::Pointer::fromAddress<ffi::NativeType>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(j){(core::num) → core::int});
   final ffi::NativeCallable<(ffi::Int32) → ffi::Pointer<ffi::NativeType>> callback = new ffi::_NativeCallableIsolateLocal::•<(ffi::Int32) → ffi::Pointer<ffi::NativeType>>([@vm.inferred-type.metadata=dart.ffi::Pointer] ffi::_createNativeCallableIsolateLocal<ffi::NativeFunction<(ffi::Int32) → ffi::Pointer<ffi::NativeType>>>(ffi::_nativeIsolateLocalCallbackFunction<(ffi::Int32) → ffi::Pointer<ffi::NativeType>>(null), closure, true));
   core::print([@vm.direct-call.metadata=dart.ffi::_NativeCallableBase.nativeFunction] [@vm.inferred-type.metadata=dart.ffi::Pointer] callback.{ffi::NativeCallable::nativeFunction}{ffi::Pointer<ffi::NativeFunction<(ffi::Int32) → ffi::Pointer<ffi::NativeType>>>});
   [@vm.direct-call.metadata=dart.ffi::_NativeCallableBase.close] [@vm.inferred-type.metadata=!? (skip check)] callback.{ffi::NativeCallable::close}(){() → void};
@@ -79,7 +79,7 @@
 static method testNativeCallableIsolateLocalIntClosure() → void {
   [@vm.inferred-type.metadata=dart.core::_Smi (value: 123)] core::int j = 123;
   function closure(core::int i) → core::int
-    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(j){(core::num) → core::int};
+    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=!? (skip check)] i.{core::num::+}(j){(core::num) → core::int};
   final ffi::NativeCallable<(ffi::Int32) → ffi::Int> callback = new ffi::_NativeCallableIsolateLocal::•<(ffi::Int32) → ffi::Int>([@vm.inferred-type.metadata=dart.ffi::Pointer] ffi::_createNativeCallableIsolateLocal<ffi::NativeFunction<(ffi::Int32) → ffi::Int>>(ffi::_nativeIsolateLocalCallbackFunction<(ffi::Int32) → ffi::Int>(123), closure, true));
   core::print([@vm.direct-call.metadata=dart.ffi::_NativeCallableBase.nativeFunction] [@vm.inferred-type.metadata=dart.ffi::Pointer] callback.{ffi::NativeCallable::nativeFunction}{ffi::Pointer<ffi::NativeFunction<(ffi::Int32) → ffi::Int>>});
   [@vm.direct-call.metadata=dart.ffi::_NativeCallableBase.close] [@vm.inferred-type.metadata=!? (skip check)] callback.{ffi::NativeCallable::close}(){() → void};
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
index fa61e57..8b1072d 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
@@ -286,27 +286,20 @@
 write x = t0
 t2 = read x
 t3 = _Call direct [#lib::foo] (t2)
-t4 = _Call direct [#lib::foo] (_T (dart.core::_Closure, <anonymous closure at control_flow.dart:268>))
-t5* = _Call direct [#lib::C2.] (_T (#lib::C2))
-write x = t5
-RESULT: _T {}?
------------- <anonymous closure at control_flow.dart:268> ------------
-%#closure = _Parameter #0 [_T ANY?]
-t1 = read x
-t2 = _Call direct [#lib::bar] (t1)
+t4 = _Call direct [#lib::bar] (t2)
+t5 = _Call direct [#lib::foo] (_T (dart.core::_Closure, <anonymous closure at control_flow.dart:268>))
+t6* = _Call direct [#lib::C2.] (_T (#lib::C2))
+write x = t6
 RESULT: _T {}?
 ------------ closure2 ------------
 t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
 write x = t0
 t2 = read x
 t3 = _Call direct [#lib::foo] (t2)
-t4 = _Call direct [#lib::foo] (_T (dart.core::_Closure, <anonymous closure at control_flow.dart:277>))
+t4* = _Call direct [#lib::C2.] (_T (#lib::C2))
+write x = t4
+t6 = _Call direct [#lib::foo] (_T (dart.core::_Closure, <anonymous closure at control_flow.dart:277>))
 RESULT: t2
------------- <anonymous closure at control_flow.dart:277> ------------
-%#closure = _Parameter #0 [_T ANY?]
-t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
-write x = t1
-RESULT: _T {}?
 ------------ switch1 ------------
 %selector = _Parameter #0 [_T (dart.core::int)+]
 t1* = _Call direct [#lib::C1.] (_T (#lib::C1))
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/closures.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/closures.dart.expect
index c29fb80..ff0026d 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/closures.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/closures.dart.expect
@@ -20,7 +20,7 @@
     : self::UseClosure31::func = func, super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  method use() → void {
-    let final core::int #t1 = 42 in [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::UseClosure31.func] [@vm.inferred-type.metadata=dart.core::_Closure (closure 1 in #lib::createClosure1)] this.{self::UseClosure31::func}{(dynamic) → void}(#t1){(dynamic) → void};
+    let final core::int #t1 = 42 in [@vm.direct-call.metadata=#lib::UseClosure31.func] this.{self::UseClosure31::func}{(dynamic) → void}(#t1){(dynamic) → void};
   }
 }
 class UseClosure32 extends core::Object {
@@ -29,7 +29,7 @@
     : self::UseClosure32::func = func, super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method use() → void {
-    let final core::int #t2 = 42 in [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::UseClosure32.func] [@vm.inferred-type.metadata=dart.core::_Closure (closure 1 in #lib::createClosure2)] this.{self::UseClosure32::func}{(dynamic) → void}(#t2){(dynamic) → void};
+    let final core::int #t2 = 42 in [@vm.direct-call.metadata=#lib::UseClosure32.func] this.{self::UseClosure32::func}{(dynamic) → void}(#t2){(dynamic) → void};
   }
 }
 class UseClosure33 extends core::Object {
@@ -38,7 +38,7 @@
     : self::UseClosure33::func = func, super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10,getterSelectorId:11]  method use() → void {
-    let final core::int #t3 = 42 in [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::UseClosure33.func] [@vm.inferred-type.metadata=dart.core::_Closure (closure 0 in #lib::C.instanceMethod)] this.{self::UseClosure33::func}{(dynamic) → void}(#t3){(dynamic) → void};
+    let final core::int #t3 = 42 in [@vm.direct-call.metadata=#lib::UseClosure33.func] this.{self::UseClosure33::func}{(dynamic) → void}(#t3){(dynamic) → void};
   }
 }
 class UseClosure34 extends core::Object {
@@ -47,7 +47,7 @@
     : self::UseClosure34::func = #C1, super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method use() → void {
-    let final core::int #t4 = 42 in [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::UseClosure34.func] [@vm.inferred-type.metadata=dart.core::_Closure (value: #lib::C.staticMethod) (closure 0 in #lib::C.staticMethod)] this.{self::UseClosure34::func}{(dynamic) → void}(#t4){(dynamic) → void};
+    let final core::int #t4 = 42 in [@vm.direct-call.metadata=#lib::UseClosure34.func] this.{self::UseClosure34::func}{(dynamic) → void}(#t4){(dynamic) → void};
   }
 }
 class UseClosure35 extends core::Object {
@@ -56,11 +56,11 @@
     : self::UseClosure35::func = #C2, super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:16,getterSelectorId:17]  method use() → void {
-    let final core::int #t5 = 42 in [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::UseClosure35.func] [@vm.inferred-type.metadata=dart.core::_Closure (value: #lib::C.) (closure 0 in #lib::C.)] this.{self::UseClosure35::func}{(dynamic) → void}(#t5){(dynamic) → void};
+    let final core::int #t5 = 42 in [@vm.direct-call.metadata=#lib::UseClosure35.func] this.{self::UseClosure35::func}{(dynamic) → void}(#t5){(dynamic) → void};
   }
 }
 [@vm.closure-id=1]static method createClosure1() → dynamic
-  return [@vm.closure-id=1](dynamic arg) → void => [@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::print(arg);
+  return [@vm.closure-id=1](dynamic arg) → void => core::print(arg);
 [@vm.closure-id=1]static method createClosure2() → dynamic {
 [@vm.closure-id=1]  function inner(dynamic arg) → void {
     core::print(arg);
@@ -74,19 +74,19 @@
 static method createClosure5() → dynamic
   return #C2;
 static method useClosure11([@vm.inferred-arg-type.metadata=dart.core::_Closure (closure 1 in #lib::createClosure1)] (dynamic) → void func) → void {
-  [@vm.inferred-type.metadata=!? (receiver not int)] func(42){(dynamic) → void};
+  func(42){(dynamic) → void};
 }
 static method useClosure12([@vm.inferred-arg-type.metadata=dart.core::_Closure (closure 1 in #lib::createClosure2)] (dynamic) → void func) → void {
-  [@vm.inferred-type.metadata=!? (receiver not int)] func(42){(dynamic) → void};
+  func(42){(dynamic) → void};
 }
 static method useClosure13([@vm.inferred-arg-type.metadata=dart.core::_Closure (closure 0 in #lib::C.instanceMethod)] (dynamic) → void func) → void {
-  [@vm.inferred-type.metadata=!? (receiver not int)] func(42){(dynamic) → void};
+  func(42){(dynamic) → void};
 }
 static method useClosure14() → void {
-  [@vm.inferred-type.metadata=!? (receiver not int)] #C1(42){(dynamic) → void};
+  #C1(42){(dynamic) → void};
 }
 static method useClosure15() → void {
-  [@vm.inferred-type.metadata=!? (receiver not int)] #C2(42){(dynamic) → void};
+  #C2(42){(dynamic) → void};
 }
 static method useClosure21([@vm.inferred-arg-type.metadata=dart.core::_Closure (closure 1 in #lib::createClosure1)] dynamic func) → void {
   [@vm.inferred-type.metadata=!? (receiver not int)] func{dynamic}.call(42);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/extension_type.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/extension_type.dart.expect
index be27bcf..4ab2f92 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/extension_type.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/extension_type.dart.expect
@@ -43,7 +43,7 @@
   return #this;
 }
 static method testTypeCheckRemoval() → void {
-  final core::List<self::SomeExtensionType% /* = core::int */> list = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::generate<self::SomeExtensionType% /* = core::int */>(10, (final core::int a) → self::SomeExtensionType /* = core::int */ => [@vm.inferred-type.metadata=int] self::SomeExtensionType|constructor#(a));
+  final core::List<self::SomeExtensionType% /* = core::int */> list = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::generate<self::SomeExtensionType% /* = core::int */>(10, (final core::int a) → self::SomeExtensionType /* = core::int */ => self::SomeExtensionType|constructor#(a));
   final self::Run<self::SomeExtensionType% /* = core::int */> obj = new self::Run::•<self::SomeExtensionType /* = core::int */>();
   [@vm.call-site-attributes.metadata=receiverType:#lib::Run<#lib::SomeExtensionType%>] [@vm.direct-call.metadata=#lib::Run.execute] [@vm.inferred-type.metadata=!? (skip check)] obj.{self::Run::execute}(list){(core::List<self::SomeExtensionType% /* = core::int */>) → void};
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect
index 14b6961..3f41441 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect
@@ -71,10 +71,10 @@
     [@vm.inferred-type.metadata=dart.ffi::Pointer] synthesized ffi::Pointer<ffi::NativeFunction<() → self::Struct1>> #ffiTarget0 = [@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup] [@vm.inferred-type.metadata=dart.ffi::Pointer (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<() → self::Struct1>>("function1"){(core::String) → ffi::Pointer<ffi::NativeFunction<() → self::Struct1>>};
     @#C22
     function #ffiClosure0() → self::Struct1 {
-      return [@vm.inferred-type.metadata=#lib::Struct1] ffi::_ffiCall<self::Struct1>(#ffiTarget0);
+      return ffi::_ffiCall<self::Struct1>(#ffiTarget0);
     }
   } =>#ffiClosure0;
-  final self::Struct1 struct1 = [@vm.inferred-type.metadata=#lib::Struct1 (receiver not int)] function1(){() → self::Struct1};
+  final self::Struct1 struct1 = function1(){() → self::Struct1};
   core::print(struct1);
 }
 static method testAsFunctionReturn() → void {
@@ -85,10 +85,10 @@
     [@vm.inferred-type.metadata=dart.ffi::Pointer] synthesized ffi::Pointer<ffi::NativeFunction<() → self::Struct2>> #ffiTarget1 = pointer;
     @#C24
     function #ffiClosure1() → self::Struct2 {
-      return [@vm.inferred-type.metadata=#lib::Struct2] ffi::_ffiCall<self::Struct2>(#ffiTarget1);
+      return ffi::_ffiCall<self::Struct2>(#ffiTarget1);
     }
   } =>#ffiClosure1;
-  final self::Struct2 struct2 = [@vm.inferred-type.metadata=#lib::Struct2 (receiver not int)] function2(){() → self::Struct2};
+  final self::Struct2 struct2 = function2(){() → self::Struct2};
   core::print(struct2);
 }
 [@vm.unboxing-info.metadata=(b)->i]static method useStruct3(self::Struct3 struct3) → core::int {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
index f06d2d5..be538ac 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
@@ -2,7 +2,6 @@
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
-import "dart:_internal" as _in;
 
 import "dart:async";
 
@@ -18,7 +17,7 @@
 }
 static field dynamic usedObject;
 [@vm.inferred-type.metadata=!]late static field core::Function unknown;
-static method use([@vm.inferred-arg-type.metadata=!] dynamic object) → void {
+static method use(dynamic object) → void {
   self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
 static method foo1_a1([@vm.inferred-arg-type.metadata=dart.async::_Future<#lib::B>] dynamic x) → void {
@@ -39,16 +38,27 @@
   self::foo1_a3(a3);
   self::foo1_a4(a4);
 }
+static method foo2_a1([@vm.inferred-arg-type.metadata=dart.async::_Future?] dynamic x) → void {
+  self::use(x);
+}
+static method foo2_a2([@vm.inferred-arg-type.metadata=#lib::B?] dynamic x) → void {
+  self::use(x);
+}
+static method foo2_a3(dynamic x) → void {
+  self::use(x);
+}
+static method foo2_a4(dynamic x) → void {
+  self::use(x);
+}
+static method foo2([@vm.inferred-arg-type.metadata=dart.async::_Future?] asy::Future<self::A>? a1, [@vm.inferred-arg-type.metadata=#lib::B?] self::A? a2, FutureOr<self::A>? a3, FutureOr<self::A>? a4) → void {
+  self::foo2_a1(a1);
+  self::foo2_a2(a2);
+  self::foo2_a3(a3);
+  self::foo2_a4(a4);
+}
 static method getDynamic() → dynamic
-  return block {
-    [@vm.inferred-type.metadata=!] self::unknown;
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  return self::unknown();
 static method main(core::List<core::String> args) → dynamic {
   self::foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] asy::Future::value<self::B>(new self::B::•()), new self::B::•(), [@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] asy::Future::value<self::B>(new self::B::•()), new self::B::•());
-  block {
-    _in::unsafeCast<asy::Future<self::A>?>([@vm.inferred-type.metadata=!] self::getDynamic());
-    _in::unsafeCast<self::A?>([@vm.inferred-type.metadata=!] self::getDynamic());
-    _in::unsafeCast<FutureOr<self::A>?>([@vm.inferred-type.metadata=!] self::getDynamic());
-    _in::unsafeCast<FutureOr<self::A>?>([@vm.inferred-type.metadata=!] self::getDynamic());
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::foo2(self::getDynamic() as{TypeError,ForDynamic} asy::Future<self::A>?, self::getDynamic() as{TypeError,ForDynamic} self::A?, self::getDynamic() as{TypeError,ForDynamic} FutureOr<self::A>?, self::getDynamic() as{TypeError,ForDynamic} FutureOr<self::A>?);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
index f69240c..77f3fee 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
@@ -1,67 +1,73 @@
 library #lib;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class T1 extends core::Object {
+  synthetic constructor •() → self::T1
+    : super core::Object::•()
+    ;
 }
 class T2 extends core::Object {
+  synthetic constructor •() → self::T2
+    : super core::Object::•()
+    ;
 }
 abstract class A extends core::Object {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → core::Object;
 }
 class B extends core::Object implements self::A {
   synthetic constructor •() → self::B
     : super core::Object::•()
     ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → core::Object
+    return new self::T1::•();
 }
 class C extends core::Object implements self::A {
   synthetic constructor •() → self::C
     : super core::Object::•()
     ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → core::Object
+    return new self::T2::•();
 }
 class DeepCaller1 extends core::Object {
   synthetic constructor •() → self::DeepCaller1
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method barL1() → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method barL1() → dynamic
     return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller1::barL2}(){() → dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method barL2() → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method barL2() → dynamic
     return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller1::barL3}(){() → dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method barL3() → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method barL3() → dynamic
     return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller1::barL4}(){() → dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method barL4() → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method barL4() → dynamic
     return [@vm.inferred-type.metadata=!] self::field1;
 }
 class D extends core::Object {
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  field core::Object field2;
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  field core::Object field2;
   synthetic constructor •() → self::D
-    : dynamic #t1 = block {
-      [@vm.inferred-type.metadata=!] self::getValue();
-    } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)", super core::Object::•()
+    : self::D::field2 = [@vm.inferred-type.metadata=!] self::getValue(), super core::Object::•()
     ;
 }
 class DeepCaller2 extends core::Object {
   synthetic constructor •() → self::DeepCaller2
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method barL1([@vm.inferred-arg-type.metadata=#lib::D] self::D dd) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method barL1([@vm.inferred-arg-type.metadata=#lib::D] self::D dd) → dynamic
     return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(dd){(self::D) → dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method barL2([@vm.inferred-arg-type.metadata=#lib::D] self::D dd) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method barL2([@vm.inferred-arg-type.metadata=#lib::D] self::D dd) → dynamic
     return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(dd){(self::D) → dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method barL3([@vm.inferred-arg-type.metadata=#lib::D] self::D dd) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method barL3([@vm.inferred-arg-type.metadata=#lib::D] self::D dd) → dynamic
     return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(dd){(self::D) → dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method barL4([@vm.inferred-arg-type.metadata=#lib::D] self::D dd) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method barL4([@vm.inferred-arg-type.metadata=#lib::D] self::D dd) → dynamic
     return [@vm.direct-call.metadata=#lib::D.field2] [@vm.inferred-type.metadata=!] dd.{self::D::field2}{core::Object};
 }
 [@vm.inferred-type.metadata=!]late static field core::Function unknown;
 [@vm.inferred-type.metadata=!]static field core::Object field1 = [@vm.inferred-type.metadata=!] self::getValue();
 static method getDynamic() → dynamic
-  return block {
-    [@vm.inferred-type.metadata=!] self::unknown;
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  return self::unknown();
 static method getValue() → core::Object {
-  self::A aa = _in::unsafeCast<self::A>([@vm.inferred-type.metadata=!] self::getDynamic());
-  return throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::A aa = self::getDynamic() as{TypeError,ForDynamic} self::A;
+  return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() → core::Object};
 }
 static method use1([@vm.inferred-arg-type.metadata=#lib::DeepCaller1] self::DeepCaller1 x) → dynamic
   return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller1::barL1}(){() → dynamic};
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
index f24f63e..63f534e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
@@ -1,41 +1,44 @@
 library #lib;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class T1 extends core::Object {
+  synthetic constructor •() → self::T1
+    : super core::Object::•()
+    ;
 }
 abstract class A extends core::Object {
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → dynamic;
 }
 class B extends self::A {
   synthetic constructor •() → self::B
     : super self::A::•()
     ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
+    return new self::T1::•();
 }
 class Intermediate extends core::Object {
   synthetic constructor •() → self::Intermediate
     : super core::Object::•()
     ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method bar([@vm.inferred-arg-type.metadata=#lib::B] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=#lib::T1 (skip check)] aa.{self::A::foo}(){() → dynamic};
 }
 [@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use1([@vm.inferred-arg-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-arg-type.metadata=#lib::B] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
+static method use2([@vm.inferred-arg-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-arg-type.metadata=#lib::B] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
 static method getDynamic() → dynamic
-  return block {
-    [@vm.inferred-type.metadata=!] self::unknown;
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  return self::unknown();
 static method allocateB() → dynamic {
   new self::B::•();
 }
 static method main(core::List<core::String> args) → dynamic {
-  block {
-    new self::Intermediate::•();
-    _in::unsafeCast<self::A>([@vm.inferred-type.metadata=!] self::getDynamic());
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A);
   self::allocateB();
-  block {
-    new self::Intermediate::•();
-    _in::unsafeCast<self::A>([@vm.inferred-type.metadata=!] self::getDynamic());
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
index 00c744c..99934ba 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
@@ -1,21 +1,29 @@
 library #lib;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class T1 extends core::Object {
+  synthetic constructor •() → self::T1
+    : super core::Object::•()
+    ;
 }
 class T2 extends core::Object {
+  synthetic constructor •() → self::T2
+    : super core::Object::•()
+    ;
 }
 abstract class A extends core::Object {
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → dynamic;
 }
 class B extends self::A {
   synthetic constructor •() → self::B
     : super self::A::•()
     ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
+    return new self::T1::•();
 }
 abstract class C extends core::Object implements self::B /*isMixinDeclaration*/  {
 }
@@ -33,17 +41,25 @@
   synthetic constructor •() → self::E
     : super self::_E&D&C::•()
     ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
+    return new self::T2::•();
 }
 class Intermediate extends core::Object {
   synthetic constructor •() → self::Intermediate
     : super core::Object::•()
     ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method bar([@vm.inferred-arg-type.metadata=!] self::A aa) → dynamic
+    return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() → dynamic};
 }
 [@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use1([@vm.inferred-arg-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-arg-type.metadata=!] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
+static method use2([@vm.inferred-arg-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-arg-type.metadata=!] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
+static method use3([@vm.inferred-arg-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-arg-type.metadata=!] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
 static method getDynamic() → dynamic
-  return block {
-    [@vm.inferred-type.metadata=!] self::unknown;
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  return self::unknown();
 static method allocateB() → dynamic {
   new self::B::•();
 }
@@ -51,18 +67,9 @@
   new self::E::•();
 }
 static method main(core::List<core::String> args) → dynamic {
-  block {
-    new self::Intermediate::•();
-    _in::unsafeCast<self::A>([@vm.inferred-type.metadata=!] self::getDynamic());
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A);
   self::allocateB();
-  block {
-    new self::Intermediate::•();
-    _in::unsafeCast<self::A>([@vm.inferred-type.metadata=!] self::getDynamic());
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A);
   self::allocateE();
-  block {
-    new self::Intermediate::•();
-    _in::unsafeCast<self::A>([@vm.inferred-type.metadata=!] self::getDynamic());
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::use3(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
index 91ba46c..dacc785 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
@@ -3,26 +3,53 @@
 import "dart:core" as core;
 
 class T1 extends core::Object {
+  synthetic constructor •() → self::T1
+    : super core::Object::•()
+    ;
 }
 class T2 extends core::Object {
+  synthetic constructor •() → self::T2
+    : super core::Object::•()
+    ;
 }
 class T3 extends core::Object {
+  synthetic constructor •() → self::T3
+    : super core::Object::•()
+    ;
 }
 class A extends core::Object {
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
+    return new self::T1::•();
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method bar() → dynamic
+    return new self::T2::•();
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method bazz() → dynamic
+    return new self::T3::•();
 }
 class B extends core::Object {
   synthetic constructor •() → self::B
     : super core::Object::•()
     ;
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method foo() → dynamic
+    return new self::T1::•();
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method bar() → dynamic
+    return new self::T2::•();
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method bazz() → dynamic
+    return new self::T3::•();
 }
 [@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use_foo1(dynamic x) → dynamic
+  return [@vm.inferred-type.metadata=#lib::T1] x{dynamic}.foo();
+static method use_foo2(dynamic x) → dynamic
+  return [@vm.inferred-type.metadata=#lib::T1] x{dynamic}.foo();
+static method use_bar(dynamic x) → dynamic
+  return [@vm.inferred-type.metadata=#lib::T2] x{dynamic}.bar();
+static method use_bazz(dynamic x) → dynamic
+  return [@vm.inferred-type.metadata=#lib::T3] x{dynamic}.bazz();
 static method getDynamic() → dynamic
-  return block {
-    [@vm.inferred-type.metadata=!] self::unknown;
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  return self::unknown();
 static method allocateA() → dynamic {
   new self::A::•();
 }
@@ -30,18 +57,10 @@
   new self::B::•();
 }
 static method main(core::List<core::String> args) → dynamic {
-  block {
-    [@vm.inferred-type.metadata=!] self::getDynamic();
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::use_foo1(self::getDynamic());
   self::allocateA();
-  block {
-    [@vm.inferred-type.metadata=!] self::getDynamic();
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
-  block {
-    [@vm.inferred-type.metadata=!] self::getDynamic();
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::use_foo2(self::getDynamic());
+  self::use_bar(self::getDynamic());
   self::allocateB();
-  block {
-    [@vm.inferred-type.metadata=!] self::getDynamic();
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::use_bazz(self::getDynamic());
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
index 3f139da..cbce7e6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
@@ -1,7 +1,6 @@
 library #lib;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class T1 extends core::Object {
   synthetic constructor •() → self::T1
@@ -14,26 +13,45 @@
     ;
 }
 class A extends core::Object {
+[@vm.inferred-type.metadata=#lib::T1] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  field dynamic field1;
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field dynamic field2;
   synthetic constructor •() → self::A
-    : dynamic #t1 = new self::T1::•(), dynamic #t2 = new self::T1::•(), super core::Object::•()
+    : self::A::field1 = new self::T1::•(), self::A::field2 = new self::T1::•(), super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  set /*isLegacy*/ field2(synthesized dynamic value) → void;
 }
 class DeepCaller1 extends core::Object {
   synthetic constructor •() → self::DeepCaller1
     : super core::Object::•()
     ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method barL1([@vm.inferred-arg-type.metadata=#lib::A] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL2}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method barL2([@vm.inferred-arg-type.metadata=#lib::A] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL3}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method barL3([@vm.inferred-arg-type.metadata=#lib::A] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL4}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method barL4([@vm.inferred-arg-type.metadata=#lib::A] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::A.field1] [@vm.inferred-type.metadata=#lib::T1] aa.{self::A::field1}{dynamic};
 }
 class DeepCaller2 extends core::Object {
   synthetic constructor •() → self::DeepCaller2
     : super core::Object::•()
     ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method barL1([@vm.inferred-arg-type.metadata=#lib::A] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method barL2([@vm.inferred-arg-type.metadata=#lib::A] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method barL3([@vm.inferred-arg-type.metadata=#lib::A] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method barL4([@vm.inferred-arg-type.metadata=#lib::A] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::A.field2] [@vm.inferred-type.metadata=!] aa.{self::A::field2}{dynamic};
 }
 [@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use1([@vm.inferred-arg-type.metadata=#lib::DeepCaller1] self::DeepCaller1 x, [@vm.inferred-arg-type.metadata=#lib::A] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=#lib::T1 (skip check)] x.{self::DeepCaller1::barL1}(aa){(self::A) → dynamic};
+static method use2([@vm.inferred-arg-type.metadata=#lib::DeepCaller2] self::DeepCaller2 x, [@vm.inferred-arg-type.metadata=#lib::A] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(aa){(self::A) → dynamic};
 static method getDynamic() → dynamic
-  return block {
-    [@vm.inferred-type.metadata=!] self::unknown;
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  return self::unknown();
 static method setField2([@vm.inferred-arg-type.metadata=#lib::A] self::A aa, [@vm.inferred-arg-type.metadata=#lib::T2] dynamic value) → void {
   [@vm.direct-call.metadata=#lib::A.field2] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::field2} = value;
 }
@@ -41,13 +59,7 @@
   new self::A::•();
   new self::T1::•();
   new self::T2::•();
-  block {
-    new self::DeepCaller1::•();
-    _in::unsafeCast<self::A>([@vm.inferred-type.metadata=!] self::getDynamic());
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
-  block {
-    new self::DeepCaller2::•();
-    _in::unsafeCast<self::A>([@vm.inferred-type.metadata=!] self::getDynamic());
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::use1(new self::DeepCaller1::•(), self::getDynamic() as{TypeError,ForDynamic} self::A);
+  self::use2(new self::DeepCaller2::•(), self::getDynamic() as{TypeError,ForDynamic} self::A);
   self::setField2(new self::A::•(), new self::T2::•());
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect
index e4ea918..f7daf42 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect
@@ -26,7 +26,7 @@
 [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:20]  final field core::List<core::int> generateFactory6;
 [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:21]  final field core::List<core::int> generateFactory7;
 [@vm.closure-id=7]  synthetic constructor •() → self::A
-    : self::A::literal1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::•<core::int>(0), self::A::literal2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::_literal3<core::int>(1, 2, 3), self::A::filledFactory1 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::filled<core::int>(2, 0), self::A::filledFactory2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::filled<core::int>(2, 0), self::A::filledFactory3 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::filled<core::int>(2, 0), self::A::filledFactory4 = let final core::bool #t1 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::filled<core::int>(2, 0, #t1), self::A::filledFactory5 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] core::_List::•<core::int?>(2), self::A::filledFactory6 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int?>] core::_GrowableList::•<core::int?>(2), self::A::filledFactory7 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] core::_List::•<core::int?>(2), self::A::filledFactory8 = let final core::bool #t2 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::filled<core::int?>(2, null, #t2), self::A::filledFactory9 = let final core::int #t3 = 2 in let final core::bool #t4 = true in [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int?>] core::_GrowableList::•<core::int?>(#t3), self::A::filledFactory10 = let final core::int #t5 = 2 in let final core::bool #t6 = false in [@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] core::_List::•<core::int?>(#t5), self::A::generateFactory1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::generate<core::int>(2, [@vm.closure-id=1](core::int i) → core::int => i), self::A::generateFactory2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::generate<core::int>(2, [@vm.closure-id=2](core::int i) → core::int => i), self::A::generateFactory3 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::generate<core::int>([@vm.closure-id=3](core::int i) → core::int => i), self::A::generateFactory4 = let final (core::int) → core::int #t7 = [@vm.closure-id=4](core::int i) → core::int => i in let final core::bool #t8 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::generate<core::int>(#t7, #t8), self::A::generateFactory5 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int>>] core::_GrowableList::generate<core::List<core::int>>(2, [@vm.closure-id=5](core::int _) → core::List<core::int> => [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::•<core::int>(0)), self::A::generateFactory6 = let final core::int #t9 = 2 in let final core::bool #t10 = true in [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::generate<core::int>(#t9, [@vm.closure-id=6](core::int i) → core::int => i), self::A::generateFactory7 = let final core::int #t11 = 2 in let final core::bool #t12 = false in [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::generate<core::int>([@vm.closure-id=7](core::int i) → core::int => i), super core::Object::•()
+    : self::A::literal1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::•<core::int>(0), self::A::literal2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::_literal3<core::int>(1, 2, 3), self::A::filledFactory1 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::filled<core::int>(2, 0), self::A::filledFactory2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::filled<core::int>(2, 0), self::A::filledFactory3 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::filled<core::int>(2, 0), self::A::filledFactory4 = let final core::bool #t1 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::filled<core::int>(2, 0, #t1), self::A::filledFactory5 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] core::_List::•<core::int?>(2), self::A::filledFactory6 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int?>] core::_GrowableList::•<core::int?>(2), self::A::filledFactory7 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] core::_List::•<core::int?>(2), self::A::filledFactory8 = let final core::bool #t2 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::filled<core::int?>(2, null, #t2), self::A::filledFactory9 = let final core::int #t3 = 2 in let final core::bool #t4 = true in [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int?>] core::_GrowableList::•<core::int?>(#t3), self::A::filledFactory10 = let final core::int #t5 = 2 in let final core::bool #t6 = false in [@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] core::_List::•<core::int?>(#t5), self::A::generateFactory1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::generate<core::int>(2, [@vm.closure-id=1](core::int i) → core::int => i), self::A::generateFactory2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::generate<core::int>(2, [@vm.closure-id=2](core::int i) → core::int => i), self::A::generateFactory3 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::generate<core::int>([@vm.closure-id=3](core::int i) → core::int => i), self::A::generateFactory4 = let final (core::int) → core::int #t7 = [@vm.closure-id=4](core::int i) → core::int => i in let final core::bool #t8 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::generate<core::int>(#t7, #t8), self::A::generateFactory5 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int>>] core::_GrowableList::generate<core::List<core::int>>(2, [@vm.closure-id=5](core::int _) → core::List<core::int> => core::_GrowableList::•<core::int>(0)), self::A::generateFactory6 = let final core::int #t9 = 2 in let final core::bool #t10 = true in [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::generate<core::int>(#t9, [@vm.closure-id=6](core::int i) → core::int => i), self::A::generateFactory7 = let final core::int #t11 = 2 in let final core::bool #t12 = false in [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::generate<core::int>([@vm.closure-id=7](core::int i) → core::int => i), super core::Object::•()
     ;
 }
 static method nonConstant() → dynamic
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/mixin_with_field_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/mixin_with_field_test.dart.expect
index 5df4917..a4de748 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/mixin_with_field_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/mixin_with_field_test.dart.expect
@@ -5,9 +5,9 @@
 abstract class M extends core::Object /*isMixinDeclaration*/  {
 }
 abstract class _C&Object&M extends core::Object implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 7)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i]  field core::int x;
+[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i]  field core::int x;
   synthetic constructor •() → self::_C&Object&M
-    : self::_C&Object&M::x = [@vm.inferred-type.metadata=dart.core::_Smi (value: 7) (receiver not int)](() → core::int => 7)(){() → core::int}, super core::Object::•()
+    : self::_C&Object&M::x = (() → core::int => 7)(){() → core::int}, super core::Object::•()
     ;
 }
 class C extends self::_C&Object&M {
@@ -16,5 +16,5 @@
     ;
 }
 static method main() → dynamic {
-  core::print([@vm.direct-call.metadata=#lib::_C&Object&M.x] [@vm.inferred-type.metadata=dart.core::_Smi (value: 7)] new self::C::•().{self::_C&Object&M::x}{core::int});
+  core::print([@vm.direct-call.metadata=#lib::_C&Object&M.x] [@vm.inferred-type.metadata=int] new self::C::•().{self::_C&Object&M::x}{core::int});
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
index bede843..5c01f13 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
@@ -80,9 +80,11 @@
   synthetic constructor •() → self::E
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T4::•();
   }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  no-such-method-forwarder get bar() → dynamic
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::E.noSuchMethod] [@vm.inferred-type.metadata=#lib::T4 (skip check)] this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 }
 class F extends core::Object {
   synthetic constructor •() → self::F
@@ -114,9 +116,7 @@
 [@vm.inferred-type.metadata=#lib::D]static field self::A dd = new self::D::•();
 [@vm.inferred-type.metadata=!]late static field core::Function unknown;
 static method getDynamic() → dynamic
-  return block {
-    [@vm.inferred-type.metadata=!] self::unknown;
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  return self::unknown();
 static method main(core::List<core::String> args) → dynamic {
   core::print([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B] self::bb.{self::A::foo}(){() → dynamic});
   core::print([@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=#lib::T1] [@vm.inferred-type.metadata=#lib::B] self::bb.{self::A::bar}{dynamic});
@@ -125,10 +125,10 @@
   core::print([@vm.direct-call.metadata=#lib::D.bar] [@vm.inferred-type.metadata=#lib::T2] [@vm.inferred-type.metadata=#lib::D] self::dd.{self::A::bar}{dynamic});
   core::print([@vm.direct-call.metadata=#lib::D.bazz] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D] self::dd.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) → dynamic});
   new self::E::•();
-  self::A xx = _in::unsafeCast<self::A>([@vm.inferred-type.metadata=!] self::getDynamic());
-  throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
-  dynamic yy = [@vm.inferred-type.metadata=!] self::getDynamic();
-  throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::A xx = self::getDynamic() as{TypeError,ForDynamic} self::A;
+  core::print([@vm.inferred-type.metadata=!] xx.{self::A::bar}{dynamic});
+  dynamic yy = self::getDynamic();
+  core::print([@vm.inferred-type.metadata=!] yy{dynamic}.twoArg(1, 2, 3));
   new self::F::•();
   dynamic gg = new self::G::•();
   core::print([@vm.inferred-type.metadata=#lib::T5 (receiver not int)] gg{dynamic}.noSuchMethod(null, null));
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination2.dart.expect
index dde262a..fb6ac8e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination2.dart.expect
@@ -6,7 +6,7 @@
 static method _defaultCheck([dynamic _ = #C1]) → core::bool
   return true;
 static method testStaticTypeOfConditional<T extends core::Object? = dynamic>([@vm.inferred-arg-type.metadata=dart.core::_Closure (closure 1 in #lib::main)] (self::testStaticTypeOfConditional::T%) →? core::bool check) → void {
-  if(#C2 is self::testStaticTypeOfConditional::T% && _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool (value: true) (receiver not int)](let final (self::testStaticTypeOfConditional::T%) →? core::bool #t1 = check in _in::unsafeCast<core::Function>(#t1{(self::testStaticTypeOfConditional::T%) → core::bool}))(#C2))) {
+  if(#C2 is self::testStaticTypeOfConditional::T% && (let final (self::testStaticTypeOfConditional::T%) →? core::bool #t1 = check in _in::unsafeCast<core::Function>(#t1{(self::testStaticTypeOfConditional::T%) → core::bool}))(#C2) as{TypeError,ForDynamic} core::bool) {
     core::print("ok");
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
index 6eff4ab..7bd31a1 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
@@ -1,7 +1,6 @@
 library #lib;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 abstract class T0 extends core::Object {
   synthetic constructor •() → self::T0
@@ -24,45 +23,47 @@
   }
 }
 abstract class B extends core::Object {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  abstract method method2(covariant-by-declaration dynamic arg) → void;
 }
 class C extends core::Object implements self::B {
   synthetic constructor •() → self::C
     : super core::Object::•()
     ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method method2(covariant-by-declaration self::T0 t0) → void {
+    [@vm.direct-call.metadata=#lib::T2.foo] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
+  }
 }
 class D extends core::Object {
   synthetic constructor •() → self::D
     : super core::Object::•()
     ;
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method method3(self::T0 t0) → void {
+    [@vm.direct-call.metadata=#lib::T2.foo] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
+  }
 }
 [@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method func1([@vm.inferred-arg-type.metadata=#lib::T2] self::T0 t0) → void {
+  [@vm.direct-call.metadata=#lib::T2.foo] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
+}
 static method func2(self::T0 t0) → void {
   [@vm.direct-call.metadata=#lib::T2.foo] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
 }
 static method getDynamic() → dynamic
-  return block {
-    [@vm.inferred-type.metadata=!] self::unknown;
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
-static method use() → dynamic
-  return block {
-    [@vm.inferred-type.metadata=!] self::unknown;
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  return self::unknown();
+static method use([@vm.inferred-arg-type.metadata=dart.core::_Closure] dynamic x) → dynamic
+  return self::unknown(x);
 static method main(core::List<core::String> args) → dynamic {
-  block {
-    _in::unsafeCast<self::T0>([@vm.inferred-type.metadata=!] self::getDynamic());
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
-  self::use();
-  let final (self::T0) → void #t1 = [@vm.inferred-type.metadata=dart.core::_Closure (closure 0 in #lib::A.method1)] new self::A::•().{self::A::method1}{(self::T0) → void} in self::use();
-  self::B bb = _in::unsafeCast<self::B>([@vm.inferred-type.metadata=!] self::getDynamic());
-  block {
-    [@vm.inferred-type.metadata=!] self::getDynamic();
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
-  block {
-    [@vm.inferred-type.metadata=!] self::getDynamic();
-    [@vm.inferred-type.metadata=!] self::getDynamic();
-  } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+  self::func1(self::getDynamic() as{TypeError,ForDynamic} self::T0);
+  self::use(#C1);
+  self::use([@vm.inferred-type.metadata=dart.core::_Closure (closure 0 in #lib::A.method1)] new self::A::•().{self::A::method1}{(self::T0) → void});
+  self::B bb = self::getDynamic() as{TypeError,ForDynamic} self::B;
+  [@vm.direct-call.metadata=#lib::C.method2] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B::method2}(self::getDynamic()){(dynamic) → void};
+  self::getDynamic(){dynamic}.method3(self::getDynamic());
   new self::T2::•();
   new self::A::•();
   new self::C::•();
   new self::D::•();
 }
+constants  {
+  #C1 = static-tearoff self::func2
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart.expect
index b51a3f0..ca00923 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart.expect
@@ -20,7 +20,7 @@
   method bar() → void {
     @#C16
     function bazz() → void {}
-    [@vm.inferred-type.metadata=!? (receiver not int)] bazz(){() → void};
+    bazz(){() → void};
   }
 }
 static method main() → dynamic {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
index 8fe1a38..49bee5c 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
@@ -60,7 +60,7 @@
     exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library package:protobuf/protobuf.dart::PbMap.[]] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep? (skip check)] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=library package:protobuf/protobuf.dart::PbMap] foo.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]}("foo"){(core::Object?) → pb::BarKeep?}!.{pb::BarKeep::aKeep}{core::int}, 2);
     exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() → core::bool}, false);
     exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int}, 43);
-    exp::expect([@vm.closure-id=2]() → void => [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] foo.{pb::FooKeep::clearClearKeep}(){() → void}, [@vm.inferred-type.metadata=library package:matcher/src/expect/throws_matcher.dart::Throws] thr::throwsA());
+    exp::expect([@vm.closure-id=2]() → void => [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() → void}, [@vm.inferred-type.metadata=library package:matcher/src/expect/throws_matcher.dart::Throws] thr::throwsA());
   });
 }
 library foo.pb.dart;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_54163.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_54163.dart.expect
index 6b39f48..8212007 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_54163.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_54163.dart.expect
@@ -28,5 +28,5 @@
   self::foo<core::double>(new self::C::•(), new self::C::•());
   [@vm.inferred-type.metadata=#lib::B] self::A<core::num> a1 = new self::B::•();
   [@vm.inferred-type.metadata=#lib::C] self::A<core::num> a2 = new self::C::•();
-  exp::Expect::throws<core::TypeError>([@vm.closure-id=1]() → void => [@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::foo<core::num>(a1, a2));
+  exp::Expect::throws<core::TypeError>([@vm.closure-id=1]() → void => self::foo<core::num>(a1, a2));
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
index 9a4440c..07dffe4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
@@ -19,7 +19,7 @@
   synthetic constructor •() → self::A1
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method call([@vm.inferred-arg-type.metadata=#lib::T1] dynamic a5) → void {
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method call([[@vm.inferred-arg-type.metadata=dart.core::_Smi (value: 1)] dynamic a1 = #C1, [@vm.inferred-arg-type.metadata=dart.core::_Smi (value: 2)] dynamic a2 = #C1, [@vm.inferred-arg-type.metadata=dart.core::_Smi (value: 3)] dynamic a3 = #C1, [@vm.inferred-arg-type.metadata=dart.core::_Smi (value: 4)] dynamic a4 = #C1, [@vm.inferred-arg-type.metadata=#lib::T1] dynamic a5 = #C1]) → void {
     [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A1::foo} = _in::unsafeCast<self::T1?>(a5);
   }
 }
@@ -112,12 +112,12 @@
 }
 [@vm.inferred-type.metadata=dart.core::bool?]static field core::bool? ok;
 [@vm.inferred-type.metadata=#lib::B3?]static field dynamic bb3 = new self::B3::•();
-[@vm.inferred-type.metadata=dart.core::_Closure (closure 1 in #lib::unknown3)] [@vm.closure-id=1]static field core::Function unknown3 = [@vm.closure-id=1]() → dynamic => [@vm.inferred-type.metadata=#lib::B3?] self::bb3;
+[@vm.inferred-type.metadata=dart.core::_Closure (closure 1 in #lib::unknown3)] [@vm.closure-id=1]static field core::Function unknown3 = [@vm.closure-id=1]() → dynamic => self::bb3;
 [@vm.inferred-type.metadata=#lib::B4?]static field dynamic bb4 = new self::B4::•();
-[@vm.inferred-type.metadata=dart.core::_Closure (closure 1 in #lib::unknown4)] [@vm.closure-id=1]static field core::Function unknown4 = [@vm.closure-id=1]() → dynamic => [@vm.inferred-type.metadata=#lib::B4?] self::bb4;
+[@vm.inferred-type.metadata=dart.core::_Closure (closure 1 in #lib::unknown4)] [@vm.closure-id=1]static field core::Function unknown4 = [@vm.closure-id=1]() → dynamic => self::bb4;
 static method test1() → void {
   self::B1 bb = new self::B1::•();
-  let final self::B1 #t1 = bb in let final core::int #t2 = 1 in let final core::int #t3 = 2 in let final core::int #t4 = 3 in let final core::int #t5 = 4 in let final self::T1 #t6 = new self::T1::•() in [@vm.direct-call.metadata=#lib::A1.call] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] #t1.{self::B1::aa1}{self::A1}.{self::A1::call}(#t6){([dynamic, dynamic, dynamic, dynamic, dynamic]) → void};
+  let final self::B1 #t1 = bb in let final core::int #t2 = 1 in let final core::int #t3 = 2 in let final core::int #t4 = 3 in let final core::int #t5 = 4 in let final self::T1 #t6 = new self::T1::•() in [@vm.direct-call.metadata=#lib::A1.call] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] #t1.{self::B1::aa1}{self::A1}.{self::A1::call}(#t2, #t3, #t4, #t5, #t6){([dynamic, dynamic, dynamic, dynamic, dynamic]) → void};
   self::ok = false;
   [@vm.direct-call.metadata=#lib::T1.doTest1] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=#lib::T1?] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] bb.{self::B1::aa1}{self::A1}.{self::A1::foo}{self::T1?}!.{self::T1::doTest1}(){() → void};
   exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
@@ -130,19 +130,19 @@
   exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
 }
 static method getDynamic3() → dynamic
-  return [@vm.inferred-type.metadata=#lib::B3? (receiver not int)] [@vm.inferred-type.metadata=dart.core::_Closure (closure 1 in #lib::unknown3)] self::unknown3();
+  return self::unknown3();
 static method test3() → void {
-  [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=#lib::B3?] self::getDynamic3(){dynamic}.aa3(1, 2, 3, 4, 5, 6, new self::T3::•());
+  self::getDynamic3(){dynamic}.aa3(1, 2, 3, 4, 5, 6, new self::T3::•());
   self::ok = false;
   [@vm.direct-call.metadata=#lib::T3.doTest3??] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::A3.foo] [@vm.inferred-type.metadata=#lib::T3? (receiver not int)] [@vm.direct-call.metadata=#lib::B3.aa3??] [@vm.inferred-type.metadata=#lib::A3 (receiver not int)] [@vm.inferred-type.metadata=#lib::B3?] self::bb3{dynamic}.aa3{dynamic}.foo{dynamic}.doTest3();
   exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
 }
 static method getDynamic4() → dynamic
-  return [@vm.inferred-type.metadata=#lib::B4? (receiver not int)] [@vm.inferred-type.metadata=dart.core::_Closure (closure 1 in #lib::unknown4)] self::unknown4();
+  return self::unknown4();
 static method test4() → void {
-  [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=#lib::B4?] self::getDynamic4(){dynamic}.aa4(1, 2, 3, 4, 5, 6, 7, new self::T4::•());
+  self::getDynamic4(){dynamic}.aa4(1, 2, 3, 4, 5, 6, 7, new self::T4::•());
   self::ok = false;
-  [@vm.direct-call.metadata=#lib::T4.doTest4??] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::A4.foo] [@vm.inferred-type.metadata=#lib::T4? (receiver not int)] [@vm.direct-call.metadata=#lib::B4.aa4??] [@vm.inferred-type.metadata=#lib::A4 (receiver not int)] [@vm.inferred-type.metadata=#lib::B4?] self::getDynamic4(){dynamic}.aa4{dynamic}.foo{dynamic}.doTest4();
+  [@vm.direct-call.metadata=#lib::T4.doTest4??] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::A4.foo] [@vm.inferred-type.metadata=#lib::T4? (receiver not int)] [@vm.inferred-type.metadata=#lib::A4] self::getDynamic4(){dynamic}.aa4{dynamic}.foo{dynamic}.doTest4();
   exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
 }
 static method main() → void {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect
index 69ff30b..de71ed6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect
@@ -10,14 +10,14 @@
 [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet<dynamic>]static field core::Set<dynamic> identitySet = [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet<dynamic>] col::LinkedHashSet::identity<dynamic>();
 [@vm.inferred-type.metadata=dart.collection::_Set<dart.core::String>]static field core::Set<core::String> linkedSet = new col::_Set::•<core::String>();
 [@vm.inferred-type.metadata=!]static field core::Set<core::String> linkedIdentitySet = [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String>(#C1, #C2);
-[@vm.inferred-type.metadata=dart.collection::_CompactLinkedCustomHashSet<dart.core::String>]static field core::Set<core::String> linkedCustomSet = let final (core::String, core::String) → core::bool #t1 = (core::String a, core::String b) → core::bool => [@vm.inferred-type.metadata=dart.core::bool (receiver not int)] a =={core::String::==}{(core::Object) → core::bool} b in let final (core::String) → core::int #t2 = (core::String o) → core::int => [@vm.inferred-type.metadata=dart.core::_Smi] o.{core::String::hashCode}{core::int} in let final (dynamic) → core::bool #t3 = (dynamic o) → core::bool => true in [@vm.inferred-type.metadata=dart.collection::_CompactLinkedCustomHashSet<dart.core::String>] col::LinkedHashSet::•<core::String>(#t1, #t2, isValidKey: #t3);
+[@vm.inferred-type.metadata=dart.collection::_CompactLinkedCustomHashSet<dart.core::String>]static field core::Set<core::String> linkedCustomSet = let final (core::String, core::String) → core::bool #t1 = (core::String a, core::String b) → core::bool => [@vm.inferred-type.metadata=!? (receiver not int)] a =={core::String::==}{(core::Object) → core::bool} b in let final (core::String) → core::int #t2 = (core::String o) → core::int => o.{core::String::hashCode}{core::int} in let final (dynamic) → core::bool #t3 = (dynamic o) → core::bool => true in [@vm.inferred-type.metadata=dart.collection::_CompactLinkedCustomHashSet<dart.core::String>] col::LinkedHashSet::•<core::String>(#t1, #t2, isValidKey: #t3);
 [@vm.inferred-type.metadata=dart.collection::_Map<dynamic, dynamic>]static field core::Map<dynamic, dynamic> globalMap = [@vm.inferred-type.metadata=dart.collection::_Map<dynamic, dynamic>] core::Map::•<dynamic, dynamic>();
 [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap<dynamic, dynamic>]static field core::Map<dynamic, dynamic> identityMap = [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap<dynamic, dynamic>] col::LinkedHashMap::identity<dynamic, dynamic>();
 [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dynamic, dynamic>]static field core::Map<dynamic, dynamic> unmodifiableMap = [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dynamic, dynamic>] core::Map::unmodifiable<dynamic, dynamic>([@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap<dynamic, dynamic>] self::identityMap);
 [@vm.inferred-type.metadata=dart.collection::_Map<dynamic, dynamic>]static field core::Map<dynamic, dynamic> globalMapLiteral = <dynamic, dynamic>{};
 [@vm.inferred-type.metadata=dart.collection::_Map<dart.core::String, dart.core::String>]static field core::Map<core::String, core::String> linkedMap = new col::_Map::•<core::String, core::String>();
 [@vm.inferred-type.metadata=!]static field core::Map<core::String, core::String> linkedIdentityMap = [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String, core::String>(#C1, #C2);
-[@vm.inferred-type.metadata=dart.collection::_CompactLinkedCustomHashMap<dart.core::String, dart.core::String>]static field core::Map<core::String, core::String> linkedCustomMap = let final (core::String, core::String) → core::bool #t4 = (core::String a, core::String b) → core::bool => [@vm.inferred-type.metadata=dart.core::bool (receiver not int)] a =={core::String::==}{(core::Object) → core::bool} b in let final (core::String) → core::int #t5 = (core::String o) → core::int => [@vm.inferred-type.metadata=dart.core::_Smi] o.{core::String::hashCode}{core::int} in let final (dynamic) → core::bool #t6 = (dynamic o) → core::bool => true in [@vm.inferred-type.metadata=dart.collection::_CompactLinkedCustomHashMap<dart.core::String, dart.core::String>] col::LinkedHashMap::•<core::String, core::String>(#t4, #t5, isValidKey: #t6);
+[@vm.inferred-type.metadata=dart.collection::_CompactLinkedCustomHashMap<dart.core::String, dart.core::String>]static field core::Map<core::String, core::String> linkedCustomMap = let final (core::String, core::String) → core::bool #t4 = (core::String a, core::String b) → core::bool => [@vm.inferred-type.metadata=!? (receiver not int)] a =={core::String::==}{(core::Object) → core::bool} b in let final (core::String) → core::int #t5 = (core::String o) → core::int => o.{core::String::hashCode}{core::int} in let final (dynamic) → core::bool #t6 = (dynamic o) → core::bool => true in [@vm.inferred-type.metadata=dart.collection::_CompactLinkedCustomHashMap<dart.core::String, dart.core::String>] col::LinkedHashMap::•<core::String, core::String>(#t4, #t5, isValidKey: #t6);
 static method main() → dynamic {
   core::print([@vm.inferred-type.metadata=dart.collection::_Set<dynamic>] self::globalSet);
   core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet<dynamic>] self::identitySet);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
index 596de28..d1c2fe2 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
@@ -1,7 +1,6 @@
 library #lib;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 abstract class A extends core::Object {
   synthetic constructor •() → self::A
@@ -13,12 +12,12 @@
     : super self::A::•()
     ;
 [@vm.procedure-attributes.metadata=hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
-    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num) → core::num});
+    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=! (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo() as{TypeError,ForDynamic} core::num){(core::num) → core::num} as core::int;
 }
 class TearOffDynamicMethod extends core::Object {
 [@vm.inferred-type.metadata=dart.core::_Closure (closure 0 in #lib::B.foo)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field dynamic bazz;
-  constructor •([@vm.inferred-arg-type.metadata=#lib::B] dynamic arg) → self::TearOffDynamicMethod
-    : self::TearOffDynamicMethod::bazz = [@vm.inferred-type.metadata=dart.core::_Closure (receiver not int) (closure 0 in #lib::B.foo)] arg{dynamic}.foo, super core::Object::•() {
+  constructor •(dynamic arg) → self::TearOffDynamicMethod
+    : self::TearOffDynamicMethod::bazz = [@vm.inferred-type.metadata=dart.core::_Closure (closure 0 in #lib::B.foo)] arg{dynamic}.foo, super core::Object::•() {
     [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::TearOffDynamicMethod.bazz] [@vm.inferred-type.metadata=dart.core::_Closure (closure 0 in #lib::B.foo)] this.{self::TearOffDynamicMethod::bazz}{dynamic}{dynamic}.call();
   }
 }
@@ -26,5 +25,5 @@
   return new self::B::•();
 static method main(core::List<core::String> args) → dynamic {
   core::Function closure = () → self::B => new self::B::•();
-  new self::TearOffDynamicMethod::•([@vm.inferred-type.metadata=#lib::B (receiver not int)] closure());
+  new self::TearOffDynamicMethod::•(closure());
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
index 70b3010..b079063 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
@@ -14,7 +14,7 @@
     : super self::A::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
-    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=! (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo() as{TypeError,ForDynamic} core::num){(core::num) → core::num} as core::int;
+    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num) → core::num});
 }
 class C extends core::Object implements self::A {
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_records.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_records.dart.expect
index fe0af4c..424b4e7 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_records.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_records.dart.expect
@@ -64,8 +64,8 @@
   self::A obj = [@vm.inferred-type.metadata=dart.core::bool] self::condition ?{self::A} new self::B::•() : new self::C::•();
   core::print([@vm.inferred-type.metadata=dart.core::_Record] obj.{self::A::returnUnboxed1}(){() → dynamic});
   core::print([@vm.inferred-type.metadata=dart.core::_Record] obj.{self::A::returnUnboxed2}{dynamic});
-  core::print([@vm.inferred-type.metadata=dart.core::_Record] obj.{self::A::returnBoxed1}(){() → dynamic});
-  core::print([@vm.inferred-type.metadata=dart.core::_Record] obj.{self::A::returnBoxed2}{dynamic});
+  core::print([@vm.inferred-type.metadata=!] obj.{self::A::returnBoxed1}(){() → dynamic});
+  core::print([@vm.inferred-type.metadata=!] obj.{self::A::returnBoxed2}{dynamic});
 }
 constants  {
   #C1 = "vm:entry-point"
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/weak.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/weak.dart.expect
index 7e23db5..624fcc0 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/weak.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/weak.dart.expect
@@ -26,7 +26,7 @@
   return [@vm.direct-call.metadata=dart.core::_Smi.toString] [@vm.inferred-type.metadata=dart.core::_OneByteString (skip check)] 2.{core::int::toString}(){() → core::String};
 static method register([@vm.inferred-arg-type.metadata=dart.core::_Closure?] () →? core::String getAccessor) → void {
   if(!(getAccessor == null)) {
-    core::print([@vm.inferred-type.metadata=! (receiver not int)] getAccessor{() → core::String}(){() → core::String});
+    core::print(getAccessor{() → core::String}(){() → core::String});
   }
 }
 static method main(core::List<core::String> args) → dynamic {
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index ad1f7fb..c2da713 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -2057,15 +2057,13 @@
 CompileType LoadIndexedInstr::ComputeType() const {
   switch (class_id_) {
     case kArrayCid:
-    case kImmutableArrayCid: {
-      CompileType elem_type = ComputeArrayElementType(array());
+    case kImmutableArrayCid:
       if (result_type_ != nullptr &&
           !CompileType::Dynamic().IsEqualTo(result_type_)) {
         // The original call knew something.
-        return *CompileType::ComputeRefinedType(&elem_type, result_type_);
+        return *result_type_;
       }
-      return elem_type;
-    }
+      return ComputeArrayElementType(array());
 
     case kTypeArgumentsCid:
       return CompileType::FromAbstractType(Object::dynamic_type(),
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 86134a9..8b78359 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -8,7 +8,6 @@
 
 #include "vm/compiler/backend/range_analysis.h"  // For Range.
 #include "vm/compiler/frontend/flow_graph_builder.h"  // For InlineExitCollector.
-#include "vm/compiler/frontend/kernel_translation_helper.h"
 #include "vm/compiler/jit/compiler.h"  // For Compiler::IsBackgroundCompilation().
 #include "vm/compiler/runtime_api.h"
 #include "vm/growable_array.h"
@@ -1134,14 +1133,12 @@
   return call_hook;
 }
 
-Fragment BaseFlowGraphBuilder::ClosureCall(
-    const Function& target_function,
-    TokenPosition position,
-    intptr_t type_args_len,
-    intptr_t argument_count,
-    const Array& argument_names,
-    const InferredTypeMetadata* result_type) {
-  Fragment instructions = RecordCoverage(position);
+Fragment BaseFlowGraphBuilder::ClosureCall(const Function& target_function,
+                                           TokenPosition position,
+                                           intptr_t type_args_len,
+                                           intptr_t argument_count,
+                                           const Array& argument_names) {
+  Fragment result = RecordCoverage(position);
   const intptr_t total_count =
       (type_args_len > 0 ? 1 : 0) + argument_count +
       /*closure (bare instructions) or function (otherwise)*/ 1;
@@ -1150,12 +1147,8 @@
       target_function, std::move(arguments), type_args_len, argument_names,
       InstructionSource(position), GetNextDeoptId());
   Push(call);
-  instructions <<= call;
-  if (result_type != nullptr && result_type->IsConstant()) {
-    instructions += Drop();
-    instructions += Constant(result_type->constant_value);
-  }
-  return instructions;
+  result <<= call;
+  return result;
 }
 
 void BaseFlowGraphBuilder::reset_context_depth_for_deopt_id(intptr_t deopt_id) {
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index 77e47d2..e3df988 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -22,7 +22,6 @@
 namespace kernel {
 
 class BaseFlowGraphBuilder;
-struct InferredTypeMetadata;
 class TryCatchBlock;
 
 class Fragment {
@@ -456,8 +455,7 @@
                        TokenPosition position,
                        intptr_t type_args_len,
                        intptr_t argument_count,
-                       const Array& argument_names,
-                       const InferredTypeMetadata* result_type = nullptr);
+                       const Array& argument_names);
 
   // Pops function type arguments, instantiator type arguments, dst_type, and
   // value; and type checks value against the type arguments.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 4c2f464..fc13c48 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -2964,13 +2964,8 @@
 
 Fragment StreamingFlowGraphBuilder::BuildLocalFunctionInvocation(
     TokenPosition* p) {
-  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
   const TokenPosition position = ReadPosition();
   if (p != nullptr) *p = position;
-
-  const InferredTypeMetadata result_type =
-      inferred_type_metadata_helper_.GetInferredType(offset);
-
   // read variable kernel position.
   const intptr_t variable_kernel_position = ReadUInt();
   ReadUInt();  // read relative variable index.
@@ -3032,7 +3027,7 @@
     instructions += DebugStepCheck(position);
   }
   instructions += B->ClosureCall(target_function, position, type_args_len,
-                                 argument_count, argument_names, &result_type);
+                                 argument_count, argument_names);
   return instructions;
 }
 
@@ -3095,7 +3090,7 @@
     }
     instructions +=
         B->ClosureCall(Function::null_function(), position, type_args_len,
-                       argument_count, argument_names, &result_type);
+                       argument_count, argument_names);
   } else {
     instructions += InstanceCall(
         position, Symbols::DynamicCall(), Token::kILLEGAL, type_args_len,