Version 2.14.0-349.0.dev

Merge commit '8a0aeb678631252ece307d4dbd804329818d3524' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 1a0cb9e..e05af29 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -142,7 +142,7 @@
       "name": "browser_launcher",
       "rootUri": "../third_party/pkg/browser_launcher",
       "packageUri": "lib/",
-      "languageVersion": "2.2"
+      "languageVersion": "2.12"
     },
     {
       "name": "build_integration",
@@ -800,4 +800,4 @@
       "languageVersion": "2.12"
     }
   ]
-}
+}
\ No newline at end of file
diff --git a/DEPS b/DEPS
index d1df738..f31a4bf 100644
--- a/DEPS
+++ b/DEPS
@@ -72,7 +72,7 @@
   "gperftools_revision": "180bfa10d7cb38e8b3784d60943d50e8fcef0dcb",
 
   # Revisions of /third_party/* dependencies.
-  "args_rev": "0329844afcf3efa9e92a1dc55d7d10226b0fa932",
+  "args_rev": "bf4c8796881b62fd5d3f6d86ab43014f9651eb20",
   "async_rev": "25a7e2ec39c03622b86918cb9ce3e7d00dd283d1",
   "bazel_worker_rev": "0885637b037979afbf5bcd05fd748b309fd669c0",
   "benchmark_harness_rev": "c546dbd9f639f75cd2f75de8df2eb9f8ea15e8e7",
@@ -80,13 +80,13 @@
   "boringssl_gen_rev": "7322fc15cc065d8d2957fccce6b62a509dc4d641",
   "boringssl_rev" : "1607f54fed72c6589d560254626909a64124f091",
   "browser-compat-data_tag": "v1.0.22",
-  "browser_launcher_rev": "12ab9f351a44ac803de9bc17bb2180bb312a9dd7",
+  "browser_launcher_rev": "c6cc1025d6901926cf022e144ba109677e3548f1",
   "charcode_rev": "84ea427711e24abf3b832923959caa7dd9a8514b",
   "chrome_rev" : "19997",
   "cli_util_rev" : "8c504de5deb08fe32ecf51f9662bb37d8c708e57",
   "clock_rev" : "a494269254ba978e7ef8f192c5f7fec3fc05b9d3",
   "collection_rev": "75a7a5510979a3cd70143af85bcc1667ee233674",
-  "convert_rev": "413f591577419d8a8b95d445094a82c926650bd1",
+  "convert_rev": "e063fdca4bebffecbb5e6aa5525995120982d9ce",
   "crypto_rev": "b5024e4de2b1c474dd558bef593ddbf0bfade152",
   "csslib_rev": "e411d862fd8cc50415c1badf2632e017373b3f47",
   "dart2js_info_rev" : "e0acfeb5affdf94c53067e68bd836adf589628fd",
@@ -125,10 +125,10 @@
   "json_rpc_2_rev": "7e00f893440a72de0637970325e4ea44bd1e8c8e",
   "linter_tag": "422981ffb2fbd4010aa52381676cf745e2844dd9",
   "lints_tag": "f9670df2a66e0ec12eb51554e70c1cbf56c8f5d0",
-  "logging_rev": "e2f633b543ef89c54688554b15ca3d7e425b86a2",
+  "logging_rev": "575781ef196e4fed4fb737e38fb4b73d62727187",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
   "markdown_rev": "9c4beaac96d8f008078e00b027915f81b665d2de",
-  "matcher_rev": "1f7b6f0cb15eb6659a1de0513571575a5c8a51d0",
+  "matcher_rev": "b411b22ec2437ba206c7a3006bbaeb519bd343d1",
   "mime_rev": "c931f4bed87221beaece356494b43731445ce7b8",
   "mockito_rev": "d39ac507483b9891165e422ec98d9fb480037c8b",
   "oauth2_rev": "7cd3284049fe5badbec9f2bea2afc41d14c01057",
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 7c40e38..017468a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -80,7 +80,7 @@
 /// TODO(scheglov) Clean up the list of implicitly analyzed files.
 class AnalysisDriver implements AnalysisDriverGeneric {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 163;
+  static const int DATA_VERSION = 164;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 41a201a..d466919 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -2715,6 +2715,17 @@
   }
 }
 
+/// Information about a macro-produced [Element].
+class ElementMacro {
+  /// The sequential id of this macro-produced element.
+  final int id;
+
+  /// The code that for produced by the macro.
+  final String code;
+
+  ElementMacro(this.id, this.code);
+}
+
 /// An [AbstractClassElementImpl] which is an enum.
 class EnumElementImpl extends AbstractClassElementImpl {
   ElementLinkedData? linkedData;
@@ -3480,6 +3491,13 @@
   }
 }
 
+/// This interface is implemented by [Element]s that can be added by macros.
+abstract class HasElementMacro {
+  /// If this element was added by a macro, the code of a declaration that
+  /// was produced by the macro.
+  ElementMacro? macro;
+}
+
 /// A concrete implementation of a [HideElementCombinator].
 class HideElementCombinatorImpl implements HideElementCombinator {
   @override
@@ -4912,11 +4930,14 @@
 
 /// A concrete implementation of a [PropertyAccessorElement].
 class PropertyAccessorElementImpl extends ExecutableElementImpl
-    implements PropertyAccessorElement {
+    implements PropertyAccessorElement, HasElementMacro {
   /// The variable associated with this accessor.
   @override
   late PropertyInducingElement variable;
 
+  @override
+  ElementMacro? macro;
+
   /// Initialize a newly created property accessor element to have the given
   /// [name] and [offset].
   PropertyAccessorElementImpl(String name, int offset) : super(name, offset);
diff --git a/pkg/analyzer/lib/src/macro/impl/macro.dart b/pkg/analyzer/lib/src/macro/impl/macro.dart
index 6459a6c..85f0223 100644
--- a/pkg/analyzer/lib/src/macro/impl/macro.dart
+++ b/pkg/analyzer/lib/src/macro/impl/macro.dart
@@ -6,14 +6,16 @@
 import 'package:analyzer/dart/ast/ast.dart' as ast;
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/ast.dart' as ast;
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/macro/api/code.dart';
 import 'package:analyzer/src/macro/api/macro.dart';
 
 class ClassDeclarationBuilderImpl extends DeclarationBuilderImpl
     implements ClassDeclarationBuilder {
+  final DeclarationCollector _collector;
   final ast.ClassDeclarationImpl node;
 
-  ClassDeclarationBuilderImpl(this.node);
+  ClassDeclarationBuilderImpl(this._collector, this.node);
 
   @override
   void addToClass(Declaration declaration) {
@@ -28,6 +30,7 @@
     _resetOffsets(parsedMember);
 
     node.members.add(parsedMember);
+    _collector._add(parsedMember, declaration);
   }
 
   /// We parsed [node] in the context of some synthetic code string, its
@@ -52,3 +55,36 @@
     return Fragment(node.toSource());
   }
 }
+
+class DeclarationCollector {
+  final Map<ast.AstNode, _CollectedDeclaration> _declarations = {};
+  int _nextId = 0;
+
+  /// Elements for nodes in [_declarations] were built.
+  /// Move information from [_CollectedDeclaration] into elements.
+  void updateElements() {
+    for (var entry in _declarations.entries) {
+      var node = entry.key;
+      if (node is ast.Declaration) {
+        var element = node.declaredElement;
+        if (element is HasElementMacro) {
+          (element as HasElementMacro).macro = ElementMacro(
+            entry.value.id,
+            entry.value.declaration.code,
+          );
+        }
+      }
+    }
+  }
+
+  void _add(ast.AstNode node, Declaration declaration) {
+    _declarations[node] = _CollectedDeclaration(_nextId++, declaration);
+  }
+}
+
+class _CollectedDeclaration {
+  final int id;
+  final Declaration declaration;
+
+  _CollectedDeclaration(this.id, this.declaration);
+}
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 4448606..94e46ae 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -850,6 +850,15 @@
     return LibraryLanguageVersion(package: package, override: override);
   }
 
+  ElementMacro? _readMacro() {
+    var hasData = _reader.readBool();
+    if (hasData) {
+      var id = _reader.readUInt30();
+      var code = _reader.readStringUtf8();
+      return ElementMacro(id, code);
+    }
+  }
+
   List<MethodElementImpl> _readMethods(
     CompilationUnitElementImpl unitElement,
     ElementImpl enclosingElement,
@@ -986,6 +995,7 @@
 
     var element = PropertyAccessorElementImpl(name, -1);
     PropertyAccessorElementFlags.read(_reader, element);
+    element.macro = _readMacro();
 
     var reference = classReference
         .getChild(element.isGetter ? '@getter' : '@setter')
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index a88940b..a112b46 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -280,6 +280,14 @@
     }
   }
 
+  void _writeMacro(ElementMacro? macro) {
+    _sink.writeBool(macro != null);
+    if (macro != null) {
+      _sink.writeUInt30(macro.id);
+      _sink.writeStringUtf8(macro.code);
+    }
+  }
+
   void _writeMethodElement(MethodElement element) {
     element as MethodElementImpl;
     _sink.writeUInt30(_resolutionSink.offset);
@@ -364,6 +372,7 @@
     _sink.writeUInt30(_resolutionSink.offset);
     _sink._writeStringReference(element.displayName);
     PropertyAccessorElementFlags.write(_sink, element);
+    _writeMacro(element.macro);
 
     _resolutionSink._writeAnnotationList(element.metadata);
     _resolutionSink.writeType(element.returnType);
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 9548d6e..8e1064e 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -198,16 +198,21 @@
       TypesBuilder(linker).build(nodesToBuildType);
     }
 
+    var collector = macro.DeclarationCollector();
     for (var linkingUnit in units) {
       for (var declaration in linkingUnit.node.declarations) {
         if (declaration is ast.ClassDeclarationImpl) {
           var members = declaration.members.toList();
+          var classBuilder = macro.ClassDeclarationBuilderImpl(
+            collector,
+            declaration,
+          );
           for (var member in members) {
             if (member is ast.FieldDeclarationImpl) {
               if (hasMacroAnnotation(member, 'observable')) {
                 macro.ObservableMacro().visitFieldDeclaration(
                   member,
-                  macro.ClassDeclarationBuilderImpl(declaration),
+                  classBuilder,
                 );
               }
             }
@@ -227,6 +232,7 @@
         }
       }
     }
+    collector.updateElements();
   }
 
   void storeExportScope() {
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index e7884a5..8e2ebe9 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -402,10 +402,7 @@
   void _writeDocumentation(Element element) {
     var documentation = element.documentationComment;
     if (documentation != null) {
-      var str = documentation;
-      str = str.replaceAll('\n', r'\n');
-      str = str.replaceAll('\r', r'\r');
-      _writelnWithIndent('documentationComment: $str');
+      _writelnMultiLineWithIndent('documentationComment: $documentation');
     }
   }
 
@@ -521,11 +518,30 @@
     buffer.writeln();
   }
 
+  void _writelnMultiLineWithIndent(String str) {
+    str = str.replaceAll('\n', r'\n');
+    str = str.replaceAll('\r', r'\r');
+    _writelnWithIndent(str);
+  }
+
   void _writelnWithIndent(String line) {
     buffer.write(indent);
     buffer.writeln(line);
   }
 
+  void _writeMacro(Element e) {
+    if (e is HasElementMacro) {
+      var macro = (e as HasElementMacro).macro;
+      if (macro != null) {
+        _writelnWithIndent('macro');
+        _withIndent(() {
+          _writelnWithIndent('id: ${macro.id}');
+          _writelnMultiLineWithIndent('code: ${macro.code}');
+        });
+      }
+    }
+  }
+
   void _writeMetadata(Element element) {
     var annotations = element.metadata;
     if (annotations.isNotEmpty) {
@@ -693,6 +709,7 @@
     });
 
     _withIndent(() {
+      _writeMacro(e);
       _writeDocumentation(e);
       _writeMetadata(e);
       _writeCodeRange(e);
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 814a92b..7c789a4f 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -21289,8 +21289,14 @@
                 type: int
             returnType: void
           get f @-1
+            macro
+              id: 0
+              code: int get f => _f;
             returnType: int
           set f @-1
+            macro
+              id: 1
+              code: set f(int val) {\n  print('Setting f to ${val}');\n  _f = val;\n}
             parameters
               requiredPositional val @-1
                 type: int
@@ -21344,8 +21350,14 @@
                 type: T
             returnType: void
           get f @-1
+            macro
+              id: 0
+              code: T get f => _f;
             returnType: T
           set f @-1
+            macro
+              id: 1
+              code: set f(T val) {\n  print('Setting f to ${val}');\n  _f = val;\n}
             parameters
               requiredPositional val @-1
                 type: T
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 4495763..6f7e3fd 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -360,6 +360,8 @@
       flavor.write(', lax runtime type');
     }
     if (_options.useContentSecurityPolicy) flavor.write(', CSP');
+    var featureString = _options.features.flavorString();
+    if (featureString.isNotEmpty) flavor.write(', $featureString');
     return js.Comment(generatedBy(_options, flavor: '$flavor'));
   }
 
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index a710db6..3598ad3 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -81,6 +81,21 @@
     }
   }
 
+  /// Returns a list of enabled features as a comma separated string.
+  String flavorString() {
+    bool _shouldPrint(FeatureOption feature) {
+      return feature.isNegativeFlag ? feature.isDisabled : feature.isEnabled;
+    }
+    String _toString(FeatureOption feature) {
+      return feature.isNegativeFlag ? 'no-${feature.flag}' : feature.flag;
+    }
+    Iterable<String> _listToString(List<FeatureOption> options) {
+      return options.where(_shouldPrint).map(_toString);
+    }
+    return _listToString(shipping).followedBy(_listToString(canary)).join(', ');
+  }
+
+  /// Parses a [List<String>] and enables / disables features as necessary.
   void parse(List<String> options) {
     _extractFeatures(options, shipping, FeatureStatus.shipping);
     _extractFeatures(options, canary, FeatureStatus.canary);
diff --git a/pkg/compiler/test/end_to_end/feature_options_test.dart b/pkg/compiler/test/end_to_end/feature_options_test.dart
index 3481941..d4f3908 100644
--- a/pkg/compiler/test/end_to_end/feature_options_test.dart
+++ b/pkg/compiler/test/end_to_end/feature_options_test.dart
@@ -128,7 +128,26 @@
   Expect.throwsArgumentError(() => test(['--cf1', '--no-cf1']));
 }
 
+void flavorStringTest(List<String> options, String expectedFlavorString) {
+  var tfo = test(options);
+  Expect.equals(expectedFlavorString, tfo.flavorString());
+}
+
+void flavorStringTests() {
+  flavorStringTest([], 'sf1, sf2, no-sf3, no-sf4');
+  flavorStringTest(['--no-sf1', '--no-sf2', '--sf3', '--sf4'], '');
+  flavorStringTest(['--no-sf1', '--no-sf2', '--sf3'], 'no-sf4');
+  flavorStringTest(['--no-sf1', '--sf3', '--sf4'], 'sf2');
+  flavorStringTest(['--no-sf1', '--no-sf2', '--sf3', '--sf4', '--cf1'], 'cf1');
+  flavorStringTest(['--cf1'], 'sf1, sf2, no-sf3, no-sf4, cf1');
+  flavorStringTest(['--no-sf1', '--no-sf2', '--sf3', '--sf4', '--no-cf3'], 'no-cf3');
+  flavorStringTest(['--no-cf3'], 'sf1, sf2, no-sf3, no-sf4, no-cf3');
+  flavorStringTest(['--no-sf1', '--no-sf2', '--sf3', '--sf4', '--cf1',
+      '--no-cf3'], 'cf1, no-cf3');
+}
+
 void main() {
+  // Test feature options functionality.
   testShipping();
   testNoShipping();
   testCanary();
@@ -138,4 +157,7 @@
   testNoCanaryEnabled();
   testNoShippingEnabled();
   testFlagCollision();
+
+  // Supplemental tests.
+  flavorStringTests();
 }
diff --git a/pkg/dev_compiler/pubspec.yaml b/pkg/dev_compiler/pubspec.yaml
index 2c8bf7f..41826b5 100644
--- a/pkg/dev_compiler/pubspec.yaml
+++ b/pkg/dev_compiler/pubspec.yaml
@@ -28,7 +28,7 @@
   source_span: any
 
 dev_dependencies:
-  browser_launcher: ^0.1.9
+  browser_launcher: ^1.0.0
   expect:
     path: ../expect
   http_multi_server:
@@ -48,5 +48,5 @@
     path: ../testing
   vm:
     path: ../vm
-  webkit_inspection_protocol: ^0.7.4
+  webkit_inspection_protocol: ^1.0.0
 
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 716a5a2..4de08b9 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -42,7 +42,7 @@
 
 import '../fasta_codes.dart';
 
-import '../kernel/kernel_target.dart';
+import '../kernel/kernel_helper.dart';
 
 import '../loader.dart';
 
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
index e49c0c7..98068cb 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -20,7 +20,7 @@
     show ExpressionGeneratorHelper;
 import '../kernel/kernel_builder.dart'
     show isRedirectingGenerativeConstructorImplementation;
-import '../kernel/kernel_target.dart' show SynthesizedFunctionNode;
+import '../kernel/kernel_helper.dart' show SynthesizedFunctionNode;
 
 import '../loader.dart' show Loader;
 
@@ -229,8 +229,8 @@
             library == libraryBuilder,
             "Unexpected library builder ${libraryBuilder} for"
             " constructor $this in ${library}.");
-        libraryBuilder.loader.typeInferenceEngine.toBeInferred[_constructor] =
-            this;
+        libraryBuilder.loader
+            .registerConstructorToBeInferred(_constructor, this);
       }
     }
     return _constructor;
@@ -266,10 +266,6 @@
       bodyBuilder.parseInitializers(beginInitializers!);
       bodyBuilder.resolveRedirectingFactoryTargets();
     }
-    if (_constructorTearOff != null) {
-      buildConstructorTearOffOutline(
-          _constructorTearOff!, constructor, classBuilder!.cls);
-    }
     beginInitializers = null;
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
index 463174c..a9a0b74 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -42,7 +42,7 @@
         templateDuplicatedDeclarationSyntheticCause,
         templateEnumConstantSameNameAsEnclosing;
 
-import '../kernel/kernel_target.dart';
+import '../kernel/kernel_helper.dart';
 
 import '../util/helpers.dart';
 
diff --git a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
index 9435193..d0250bf 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -7,7 +7,7 @@
 
 import '../fasta_codes.dart'
     show templateInternalProblemNotFoundIn, templateTypeArgumentMismatch;
-import '../kernel/kernel_target.dart';
+import '../kernel/kernel_helper.dart';
 import '../scope.dart';
 import '../source/source_library_builder.dart';
 import '../problems.dart';
diff --git a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
index 2725aac..8b6c13e 100644
--- a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
@@ -12,7 +12,7 @@
 import '../kernel/forest.dart';
 import '../kernel/internal_ast.dart';
 import '../kernel/kernel_api.dart';
-import '../kernel/kernel_target.dart';
+import '../kernel/kernel_helper.dart';
 import '../kernel/redirecting_factory_body.dart'
     show getRedirectingFactoryBody, RedirectingFactoryBody;
 
@@ -342,7 +342,7 @@
     if (_factoryTearOff != null) {
       _tearOffTypeParameters =
           buildRedirectingFactoryTearOffProcedureParameters(
-              _factoryTearOff!, _procedure, library);
+              _factoryTearOff!, _procedureInternal, libraryBuilder);
     }
     return _procedureInternal;
   }
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 4fd424a..1a7c9bc 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -17,7 +17,7 @@
 import '../kernel/body_builder.dart' show BodyBuilder;
 import '../kernel/class_hierarchy_builder.dart';
 import '../kernel/kernel_builder.dart' show ImplicitFieldType;
-import '../kernel/kernel_target.dart';
+import '../kernel/kernel_helper.dart';
 import '../kernel/late_lowering.dart' as late_lowering;
 import '../kernel/member_covariance.dart';
 
diff --git a/pkg/front_end/lib/src/fasta/builder/function_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
index e4cab78..71dc58a 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
@@ -13,7 +13,7 @@
 import '../scope.dart';
 
 import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
-import '../kernel/kernel_target.dart';
+import '../kernel/kernel_helper.dart';
 
 import '../loader.dart' show Loader;
 
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 87167ef..bae23b9 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -10,7 +10,7 @@
 import '../../base/common.dart';
 
 import '../kernel/class_hierarchy_builder.dart';
-import '../kernel/kernel_target.dart';
+import '../kernel/kernel_helper.dart';
 import '../modifier.dart';
 import '../problems.dart' show unsupported;
 import '../source/source_library_builder.dart';
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart
index c9aba98..1a1857b 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart
@@ -11,7 +11,7 @@
 import '../builder/type_builder.dart';
 import '../builder/type_variable_builder.dart';
 
-import '../kernel/kernel_target.dart';
+import '../kernel/kernel_helper.dart';
 
 import '../scope.dart';
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
index 6cf584a..ae3a7d3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
@@ -4,11 +4,10 @@
 
 import 'package:kernel/ast.dart';
 import 'package:kernel/type_algebra.dart';
-import '../builder/library_builder.dart';
 import '../builder/member_builder.dart';
 import '../source/source_library_builder.dart';
 import 'kernel_api.dart';
-import 'kernel_target.dart';
+import 'kernel_helper.dart';
 
 const String _tearOffNamePrefix = '_#';
 const String _tearOffNameSuffix = '#tearOff';
@@ -155,7 +154,7 @@
 
   List<DartType> typeArguments = freshTypeParameters.freshTypeArguments;
   Substitution substitution = freshTypeParameters.substitution;
-  _createParameters(tearOff, function, substitution);
+  _createParameters(tearOff, constructor, substitution, libraryBuilder);
   Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
   _createTearOffBody(tearOff, constructor, arguments);
   tearOff.function.fileOffset = tearOff.fileOffset;
@@ -206,8 +205,11 @@
           (int index) => substitution.substituteType(typeArguments[index]));
     }
   }
-  _createParameters(tearOff, function,
-      Substitution.fromPairs(classTypeParameters, typeArguments));
+  _createParameters(
+      tearOff,
+      constructor,
+      Substitution.fromPairs(classTypeParameters, typeArguments),
+      libraryBuilder);
   Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
   _createTearOffBody(tearOff, constructor, arguments);
   tearOff.function.fileOffset = tearOff.fileOffset;
@@ -215,52 +217,19 @@
   updatePrivateMemberName(tearOff, libraryBuilder);
 }
 
-/// Copies the parameter types from [constructor] to [tearOff].
-///
-/// These might have been inferred and therefore not available when the
-/// parameters were created.
-// TODO(johnniwinther): Avoid doing this when parameter types are not inferred.
-void buildConstructorTearOffOutline(
-    Procedure tearOff, Constructor constructor, Class enclosingClass) {
-  List<TypeParameter> classTypeParameters = enclosingClass.typeParameters;
-  Substitution substitution = Substitution.empty;
-  if (classTypeParameters.isNotEmpty) {
-    List<DartType> typeArguments = [];
-    for (TypeParameter typeParameter in tearOff.function.typeParameters) {
-      typeArguments.add(new TypeParameterType(typeParameter,
-          TypeParameterType.computeNullabilityFromBound(typeParameter)));
-    }
-    substitution = Substitution.fromPairs(classTypeParameters, typeArguments);
-  }
-  for (int i = 0; i < constructor.function.positionalParameters.length; i++) {
-    VariableDeclaration tearOffParameter =
-        tearOff.function.positionalParameters[i];
-    VariableDeclaration constructorParameter =
-        constructor.function.positionalParameters[i];
-    tearOffParameter.type =
-        substitution.substituteType(constructorParameter.type);
-  }
-  for (int i = 0; i < constructor.function.namedParameters.length; i++) {
-    VariableDeclaration tearOffParameter = tearOff.function.namedParameters[i];
-    VariableDeclaration constructorParameter =
-        constructor.function.namedParameters[i];
-    tearOffParameter.type =
-        substitution.substituteType(constructorParameter.type);
-  }
-}
-
 /// Creates the parameters for the redirecting factory [tearOff] based on the
 /// [redirectingConstructor] declaration.
 FreshTypeParameters buildRedirectingFactoryTearOffProcedureParameters(
     Procedure tearOff,
     Procedure redirectingConstructor,
-    LibraryBuilder libraryBuilder) {
+    SourceLibraryBuilder libraryBuilder) {
   assert(redirectingConstructor.isRedirectingFactory);
   FunctionNode function = redirectingConstructor.function;
   FreshTypeParameters freshTypeParameters =
       _createFreshTypeParameters(function.typeParameters, tearOff.function);
   Substitution substitution = freshTypeParameters.substitution;
-  _createParameters(tearOff, function, substitution);
+  _createParameters(
+      tearOff, redirectingConstructor, substitution, libraryBuilder);
   tearOff.function.fileOffset = tearOff.fileOffset;
   tearOff.function.fileEndOffset = tearOff.fileOffset;
   updatePrivateMemberName(tearOff, libraryBuilder);
@@ -330,10 +299,11 @@
 }
 
 /// Creates the parameters for the [tearOff] lowering based of the parameters
-/// in [function] and using the [substitution] to compute the parameter and
+/// in [constructor] and using the [substitution] to compute the parameter and
 /// return types.
-void _createParameters(
-    Procedure tearOff, FunctionNode function, Substitution substitution) {
+void _createParameters(Procedure tearOff, Member constructor,
+    Substitution substitution, SourceLibraryBuilder libraryBuilder) {
+  FunctionNode function = constructor.function!;
   for (VariableDeclaration constructorParameter
       in function.positionalParameters) {
     VariableDeclaration tearOffParameter = new VariableDeclaration(
@@ -355,6 +325,8 @@
   tearOff.function.returnType =
       substitution.substituteType(function.returnType);
   tearOff.function.requiredParameterCount = function.requiredParameterCount;
+  libraryBuilder.loader.registerTypeDependency(
+      tearOff, new TypeDependency(tearOff, constructor, substitution));
 }
 
 /// Creates the [Arguments] for passing the parameters from [tearOff] to its
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 104b239..e08aaf2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -191,6 +191,7 @@
   @override
   ExpressionInferenceResult visitStaticTearOff(
       StaticTearOff node, DartType typeContext) {
+    inferrer.ensureMemberType(node.target);
     DartType type =
         node.target.function.computeFunctionType(inferrer.library.nonNullable);
     return inferrer.instantiateTearOff(type, typeContext, node);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
new file mode 100644
index 0000000..71176e5
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
@@ -0,0 +1,120 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library fasta.kernel_target;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
+import 'package:kernel/type_algebra.dart' show Substitution;
+
+/// Data for clone default values for synthesized function nodes once the
+/// original default values have been computed.
+///
+/// This is used for constructors in unnamed mixin application, which are
+/// created from the constructors in the superclass, and for tear off lowerings
+/// for redirecting factories, which are created from the effective target
+/// constructor.
+class SynthesizedFunctionNode {
+  /// Type parameter map from type parameters in scope [_original] to types
+  /// in scope of [_synthesized].
+  // TODO(johnniwinther): Is this ever needed? Should occurrence of type
+  //  variable types in default values be a compile time error?
+  final Map<TypeParameter, DartType> _typeSubstitution;
+
+  /// The original function node.
+  final FunctionNode _original;
+
+  /// The synthesized function node.
+  final FunctionNode _synthesized;
+
+  /// If `true`, the [_synthesized] is guaranteed to have the same parameters in
+  /// the same order as [_original]. Otherwise [_original] is only guaranteed to
+  /// be callable from [_synthesized], meaning that is has at most the same
+  /// number of positional parameters and a, possibly reordered, subset of the
+  /// named parameters.
+  final bool identicalSignatures;
+
+  SynthesizedFunctionNode(
+      this._typeSubstitution, this._original, this._synthesized,
+      {this.identicalSignatures: true});
+
+  void cloneDefaultValues() {
+    // TODO(ahe): It is unclear if it is legal to use type variables in
+    // default values, but Fasta is currently allowing it, and the VM
+    // accepts it. If it isn't legal, the we can speed this up by using a
+    // single cloner without substitution.
+    CloneVisitorNotMembers? cloner;
+
+    void cloneInitializer(VariableDeclaration originalParameter,
+        VariableDeclaration clonedParameter) {
+      if (originalParameter.initializer != null) {
+        cloner ??=
+            new CloneVisitorNotMembers(typeSubstitution: _typeSubstitution);
+        clonedParameter.initializer = cloner!
+            .clone(originalParameter.initializer!)
+              ..parent = clonedParameter;
+      }
+    }
+
+    // For mixin application constructors, the argument count is the same, but
+    // for redirecting tear off lowerings, the argument count of the tear off
+    // can be less than that of the redirection target.
+
+    assert(_synthesized.positionalParameters.length <=
+        _original.positionalParameters.length);
+    for (int i = 0; i < _synthesized.positionalParameters.length; i++) {
+      cloneInitializer(_original.positionalParameters[i],
+          _synthesized.positionalParameters[i]);
+    }
+
+    if (identicalSignatures) {
+      assert(_synthesized.namedParameters.length ==
+          _original.namedParameters.length);
+      for (int i = 0; i < _synthesized.namedParameters.length; i++) {
+        cloneInitializer(
+            _original.namedParameters[i], _synthesized.namedParameters[i]);
+      }
+    } else if (_synthesized.namedParameters.isNotEmpty) {
+      Map<String, VariableDeclaration> originalParameters = {};
+      for (int i = 0; i < _original.namedParameters.length; i++) {
+        originalParameters[_original.namedParameters[i].name!] =
+            _original.namedParameters[i];
+      }
+      for (int i = 0; i < _synthesized.namedParameters.length; i++) {
+        cloneInitializer(
+            originalParameters[_synthesized.namedParameters[i].name!]!,
+            _synthesized.namedParameters[i]);
+      }
+    }
+  }
+}
+
+class TypeDependency {
+  final Member synthesized;
+  final Member original;
+  final Substitution substitution;
+
+  TypeDependency(this.synthesized, this.original, this.substitution);
+
+  void copyInferred() {
+    for (int i = 0; i < original.function!.positionalParameters.length; i++) {
+      VariableDeclaration synthesizedParameter =
+          synthesized.function!.positionalParameters[i];
+      VariableDeclaration constructorParameter =
+          original.function!.positionalParameters[i];
+      synthesizedParameter.type =
+          substitution.substituteType(constructorParameter.type);
+    }
+    for (int i = 0; i < original.function!.namedParameters.length; i++) {
+      VariableDeclaration synthesizedParameter =
+          synthesized.function!.namedParameters[i];
+      VariableDeclaration originalParameter =
+          original.function!.namedParameters[i];
+      synthesizedParameter.type =
+          substitution.substituteType(originalParameter.type);
+    }
+    synthesized.function!.returnType =
+        substitution.substituteType(original.function!.returnType);
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 00e445c..0d35d0f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -6,7 +6,6 @@
 
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
 import 'package:kernel/core_types.dart';
 import 'package:kernel/reference_from_index.dart' show IndexedClass;
 import 'package:kernel/target/changed_structure_notifier.dart'
@@ -82,6 +81,7 @@
         transformProcedure,
         ConstantCoverage;
 import 'kernel_constants.dart' show KernelConstantErrorReporter;
+import 'kernel_helper.dart';
 import 'verifier.dart' show verifyComponent, verifyGetStaticType;
 
 class KernelTarget extends TargetImplementation {
@@ -364,7 +364,7 @@
     return withCrashReporting<Component?>(() async {
       ticker.logMs("Building component");
       await loader.buildBodies();
-      finishClonedParameters();
+      finishSynthesizedParameters();
       loader.finishDeferredLoadTearoffs();
       loader.finishNoSuchMethodForwarders();
       List<SourceClassBuilder> myClasses = collectMyClasses();
@@ -792,7 +792,7 @@
         synthesizedFunctionNode: isConst ? synthesizedFunctionNode : null);
   }
 
-  void finishClonedParameters() {
+  void finishSynthesizedParameters() {
     for (SynthesizedFunctionNode synthesizedFunctionNode
         in synthesizedFunctionNodes) {
       synthesizedFunctionNode.cloneDefaultValues();
@@ -1428,85 +1428,3 @@
     target.type = substitute(source.type, substitutionMap);
   }
 }
-
-/// Data for clone default values for synthesized function nodes once the
-/// original default values have been computed.
-///
-/// This is used for constructors in unnamed mixin application, which are
-/// created from the constructors in the superclass, and for tear off lowerings
-/// for redirecting factories, which are created from the effective target
-/// constructor.
-class SynthesizedFunctionNode {
-  /// Type parameter map from type parameters in scope [_original] to types
-  /// in scope of [_synthesized].
-  // TODO(johnniwinther): Is this ever needed? Should occurrence of type
-  //  variable types in default values be a compile time error?
-  final Map<TypeParameter, DartType> _typeSubstitution;
-
-  /// The original function node.
-  final FunctionNode _original;
-
-  /// The synthesized function node.
-  final FunctionNode _synthesized;
-
-  /// If `true`, the [_synthesized] is guaranteed to have the same parameters in
-  /// the same order as [_original]. Otherwise [_original] is only guaranteed to
-  /// be callable from [_synthesized], meaning that is has at most the same
-  /// number of positional parameters and a, possibly reordered, subset of the
-  /// named parameters.
-  final bool identicalSignatures;
-
-  SynthesizedFunctionNode(
-      this._typeSubstitution, this._original, this._synthesized,
-      {this.identicalSignatures: true});
-
-  void cloneDefaultValues() {
-    // TODO(ahe): It is unclear if it is legal to use type variables in
-    // default values, but Fasta is currently allowing it, and the VM
-    // accepts it. If it isn't legal, the we can speed this up by using a
-    // single cloner without substitution.
-    CloneVisitorNotMembers? cloner;
-
-    void cloneInitializer(VariableDeclaration originalParameter,
-        VariableDeclaration clonedParameter) {
-      if (originalParameter.initializer != null) {
-        cloner ??=
-            new CloneVisitorNotMembers(typeSubstitution: _typeSubstitution);
-        clonedParameter.initializer = cloner!
-            .clone(originalParameter.initializer!)
-              ..parent = clonedParameter;
-      }
-    }
-
-    // For mixin application constructors, the argument count is the same, but
-    // for redirecting tear off lowerings, the argument count of the tear off
-    // can be less than that of the redirection target.
-
-    assert(_synthesized.positionalParameters.length <=
-        _original.positionalParameters.length);
-    for (int i = 0; i < _synthesized.positionalParameters.length; i++) {
-      cloneInitializer(_original.positionalParameters[i],
-          _synthesized.positionalParameters[i]);
-    }
-
-    if (identicalSignatures) {
-      assert(_synthesized.namedParameters.length ==
-          _original.namedParameters.length);
-      for (int i = 0; i < _synthesized.namedParameters.length; i++) {
-        cloneInitializer(
-            _original.namedParameters[i], _synthesized.namedParameters[i]);
-      }
-    } else if (_synthesized.namedParameters.isNotEmpty) {
-      Map<String, VariableDeclaration> originalParameters = {};
-      for (int i = 0; i < _original.namedParameters.length; i++) {
-        originalParameters[_original.namedParameters[i].name!] =
-            _original.namedParameters[i];
-      }
-      for (int i = 0; i < _synthesized.namedParameters.length; i++) {
-        cloneInitializer(
-            originalParameters[_synthesized.namedParameters[i].name!]!,
-            _synthesized.namedParameters[i]);
-      }
-    }
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index 4027001..34849e8 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -15,7 +15,7 @@
 import 'builder/type_variable_builder.dart';
 import 'kernel/body_builder.dart' show JumpTarget;
 import 'kernel/class_hierarchy_builder.dart' show ClassMember;
-import 'kernel/kernel_target.dart';
+import 'kernel/kernel_helper.dart';
 import 'util/helpers.dart' show DelayedActionPerformer;
 
 import 'fasta_codes.dart'
diff --git a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
index d6a21ef..5ffcb20 100644
--- a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
@@ -26,7 +26,7 @@
         noLength,
         templateExtensionMemberConflictsWithObjectMember;
 
-import '../kernel/kernel_target.dart';
+import '../kernel/kernel_helper.dart';
 
 import '../problems.dart';
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index ed43189..538d6cc 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -30,12 +30,14 @@
         AsyncMarker,
         Class,
         Component,
+        Constructor,
         DartType,
         Expression,
         FunctionNode,
         InterfaceType,
         Library,
         LibraryDependency,
+        Member,
         NeverType,
         Nullability,
         Procedure,
@@ -70,6 +72,7 @@
 
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
+import '../builder/constructor_builder.dart';
 import '../builder/dynamic_type_declaration_builder.dart';
 import '../builder/enum_builder.dart';
 import '../builder/extension_builder.dart';
@@ -89,18 +92,14 @@
 
 import '../fasta_codes.dart';
 
+import '../kernel/body_builder.dart' show BodyBuilder;
 import '../kernel/kernel_builder.dart'
     show ClassHierarchyBuilder, ClassMember, DelayedCheck;
-
-import '../kernel/kernel_target.dart'
-    show SynthesizedFunctionNode, KernelTarget;
-
-import '../kernel/body_builder.dart' show BodyBuilder;
-
+import '../kernel/kernel_helper.dart'
+    show SynthesizedFunctionNode, TypeDependency;
+import '../kernel/kernel_target.dart' show KernelTarget;
 import '../kernel/transform_collections.dart' show CollectionTransformer;
-
 import '../kernel/transform_set_literals.dart' show SetLiteralTransformer;
-
 import '../kernel/type_builder_computer.dart' show TypeBuilderComputer;
 
 import '../loader.dart' show Loader, untranslatableUriScheme;
@@ -110,19 +109,14 @@
 import '../source/stack_listener_impl.dart' show offsetForToken;
 
 import '../type_inference/type_inference_engine.dart';
-
 import '../type_inference/type_inferrer.dart';
 
 import '../util/helpers.dart';
 
 import 'diet_listener.dart' show DietListener;
-
 import 'diet_parser.dart' show DietParser;
-
 import 'outline_builder.dart' show OutlineBuilder;
-
 import 'source_class_builder.dart' show SourceClassBuilder;
-
 import 'source_library_builder.dart' show SourceLibraryBuilder;
 import 'source_type_alias_builder.dart';
 
@@ -368,6 +362,15 @@
     hasInvalidNnbdModeLibrary = true;
   }
 
+  void registerConstructorToBeInferred(
+      Constructor constructor, ConstructorBuilder builder) {
+    _typeInferenceEngine!.toBeInferred[constructor] = builder;
+  }
+
+  void registerTypeDependency(Member member, TypeDependency typeDependency) {
+    _typeInferenceEngine!.typeDependencies[member] = typeDependency;
+  }
+
   @override
   Future<Null> buildOutlines() async {
     await super.buildOutlines();
diff --git a/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
index 9961217..ed04394 100644
--- a/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
@@ -32,7 +32,7 @@
 import '../builder/type_variable_builder.dart';
 
 import '../kernel/constructor_tearoff_lowering.dart';
-import '../kernel/kernel_target.dart';
+import '../kernel/kernel_helper.dart';
 
 import '../util/helpers.dart';
 
@@ -264,8 +264,6 @@
     }
     _tearOffDependencies?.forEach((Procedure tearOff, Member target) {
       InterfaceType targetType = typedef.type as InterfaceType;
-      buildTypedefTearOffProcedure(tearOff, target, target.enclosingClass!,
-          typedef.typeParameters, targetType.typeArguments, library);
       synthesizedFunctionNodes.add(new SynthesizedFunctionNode(
           new Map<TypeParameter, DartType>.fromIterables(
               target.enclosingClass!.typeParameters, targetType.typeArguments),
@@ -295,6 +293,9 @@
               createTypedefTearOffProcedure(
                   name, constructorName, library, fileUri, charOffset);
           _tearOffDependencies![tearOff] = target;
+          InterfaceType targetType = typedef.type as InterfaceType;
+          buildTypedefTearOffProcedure(tearOff, target, declaration.cls,
+              typedef.typeParameters, targetType.typeArguments, library);
           f(tearOff);
         }
       });
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index 407fbfb..5ba0cfa 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE.md file.
 
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
-import 'package:front_end/src/fasta/kernel/internal_ast.dart';
 
 import 'package:kernel/ast.dart';
 
@@ -18,9 +17,10 @@
 import '../builder/constructor_builder.dart';
 
 import '../kernel/forest.dart';
-
+import '../kernel/internal_ast.dart';
 import '../kernel/kernel_builder.dart'
     show ClassHierarchyBuilder, ImplicitFieldType;
+import '../kernel/kernel_helper.dart';
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
@@ -128,6 +128,8 @@
   /// is used to report errors.
   final Map<Constructor, ConstructorBuilder> beingInferred = {};
 
+  final Map<Member, TypeDependency> typeDependencies = {};
+
   final Instrumentation? instrumentation;
 
   TypeInferenceEngine(this.instrumentation);
@@ -152,6 +154,10 @@
       builder.inferFormalTypes();
     }
     toBeInferred.clear();
+    for (TypeDependency typeDependency in typeDependencies.values) {
+      typeDependency.copyInferred();
+    }
+    typeDependencies.clear();
   }
 
   /// Gets ready to do top level type inference for the component having the
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index a0be20e..db042b3 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -37,6 +37,7 @@
 import '../fasta_codes.dart';
 
 import '../kernel/class_hierarchy_builder.dart' show ClassMember;
+import '../kernel/kernel_helper.dart';
 import '../kernel/inference_visitor.dart';
 import '../kernel/internal_ast.dart';
 import '../kernel/invalid_type.dart';
@@ -210,14 +211,8 @@
   /// inside a closure.
   ClosureContext? closureContext;
 
-  TypeInferrerImpl(
-      this.engine,
-      this.uriForInstrumentation,
-      bool topLevel,
-      this.thisType,
-      this.library,
-      this.assignedVariables,
-      this.dataForTesting)
+  TypeInferrerImpl(this.engine, this.uriForInstrumentation, bool topLevel,
+      this.thisType, this.library, this.assignedVariables, this.dataForTesting)
       // ignore: unnecessary_null_comparison
       : assert(library != null),
         unknownFunction = new FunctionType(
@@ -369,6 +364,11 @@
     if (member is Constructor) {
       inferConstructorParameterTypes(member);
     }
+    TypeDependency? typeDependency = engine.typeDependencies.remove(member);
+    if (typeDependency != null) {
+      ensureMemberType(typeDependency.original);
+      typeDependency.copyInferred();
+    }
   }
 
   @override
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.expect
index 8770854..fa85f71 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.expect
@@ -2,16 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:28:18: Error: A value of type 'Class1 Function(int)' can't be assigned to a variable of type 'Class1 Function(dynamic)'.
-//  - 'Class1' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-// var Class1_new = Class1.new;
-//                  ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:29:18: Error: A value of type 'Class2 Function(int)' can't be assigned to a variable of type 'Class2 Function(dynamic)'.
-//  - 'Class2' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-// var Class2_new = Class2.new;
-//                  ^
-//
 // pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
 //     f1a(''); // error
 //         ^
@@ -46,14 +36,8 @@
     return new self::Class2::•(field);
 }
 static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
-static field (dynamic) → self::Class1 Class1_new = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:28:18: Error: A value of type 'Class1 Function(int)' can't be assigned to a variable of type 'Class1 Function(dynamic)'.
- - 'Class1' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-var Class1_new = Class1.new;
-                 ^" in (#C1) as{TypeError,ForNonNullableByDefault} (dynamic) → self::Class1;
-static field (dynamic) → self::Class2 Class2_new = let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:29:18: Error: A value of type 'Class2 Function(int)' can't be assigned to a variable of type 'Class2 Function(dynamic)'.
- - 'Class2' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-var Class2_new = Class2.new;
-                 ^" in (#C2) as{TypeError,ForNonNullableByDefault} (dynamic) → self::Class2;
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
 static method main() → dynamic {
   core::print("inSoundMode: ${self::inSoundMode}");
   self::testInferred();
@@ -65,7 +49,7 @@
   self::Class1 c1a = f1a(0){(core::int) → self::Class1};
   self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
   () → Null {
-    f1a(let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f1a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
   };
@@ -79,7 +63,7 @@
   self::Class2 c2a = f2a(0){(core::int) → self::Class2};
   self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
   () → Null {
-    f2a(let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f2a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
   };
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.transformed.expect
index 2d658941..2664cf0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.transformed.expect
@@ -2,16 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:28:18: Error: A value of type 'Class1 Function(int)' can't be assigned to a variable of type 'Class1 Function(dynamic)'.
-//  - 'Class1' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-// var Class1_new = Class1.new;
-//                  ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:29:18: Error: A value of type 'Class2 Function(int)' can't be assigned to a variable of type 'Class2 Function(dynamic)'.
-//  - 'Class2' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-// var Class2_new = Class2.new;
-//                  ^
-//
 // pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
 //     f1a(''); // error
 //         ^
@@ -46,14 +36,8 @@
     return new self::Class2::•(field);
 }
 static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
-static field (dynamic) → self::Class1 Class1_new = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:28:18: Error: A value of type 'Class1 Function(int)' can't be assigned to a variable of type 'Class1 Function(dynamic)'.
- - 'Class1' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-var Class1_new = Class1.new;
-                 ^" in (#C1) as{TypeError,ForNonNullableByDefault} (dynamic) → self::Class1;
-static field (dynamic) → self::Class2 Class2_new = let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:29:18: Error: A value of type 'Class2 Function(int)' can't be assigned to a variable of type 'Class2 Function(dynamic)'.
- - 'Class2' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-var Class2_new = Class2.new;
-                 ^" in (#C2) as{TypeError,ForNonNullableByDefault} (dynamic) → self::Class2;
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
 static method main() → dynamic {
   core::print("inSoundMode: ${self::inSoundMode}");
   self::testInferred();
@@ -65,7 +49,7 @@
   self::Class1 c1a = f1a(0){(core::int) → self::Class1};
   self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
   () → Null {
-    f1a(let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f1a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
   };
@@ -79,7 +63,7 @@
   self::Class2 c2a = f2a(0){(core::int) → self::Class2};
   self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
   () → Null {
-    f2a(let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f2a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
   };
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.expect
index 8770854..fa85f71 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.expect
@@ -2,16 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:28:18: Error: A value of type 'Class1 Function(int)' can't be assigned to a variable of type 'Class1 Function(dynamic)'.
-//  - 'Class1' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-// var Class1_new = Class1.new;
-//                  ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:29:18: Error: A value of type 'Class2 Function(int)' can't be assigned to a variable of type 'Class2 Function(dynamic)'.
-//  - 'Class2' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-// var Class2_new = Class2.new;
-//                  ^
-//
 // pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
 //     f1a(''); // error
 //         ^
@@ -46,14 +36,8 @@
     return new self::Class2::•(field);
 }
 static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
-static field (dynamic) → self::Class1 Class1_new = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:28:18: Error: A value of type 'Class1 Function(int)' can't be assigned to a variable of type 'Class1 Function(dynamic)'.
- - 'Class1' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-var Class1_new = Class1.new;
-                 ^" in (#C1) as{TypeError,ForNonNullableByDefault} (dynamic) → self::Class1;
-static field (dynamic) → self::Class2 Class2_new = let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:29:18: Error: A value of type 'Class2 Function(int)' can't be assigned to a variable of type 'Class2 Function(dynamic)'.
- - 'Class2' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-var Class2_new = Class2.new;
-                 ^" in (#C2) as{TypeError,ForNonNullableByDefault} (dynamic) → self::Class2;
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
 static method main() → dynamic {
   core::print("inSoundMode: ${self::inSoundMode}");
   self::testInferred();
@@ -65,7 +49,7 @@
   self::Class1 c1a = f1a(0){(core::int) → self::Class1};
   self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
   () → Null {
-    f1a(let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f1a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
   };
@@ -79,7 +63,7 @@
   self::Class2 c2a = f2a(0){(core::int) → self::Class2};
   self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
   () → Null {
-    f2a(let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f2a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
   };
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.outline.expect
index a9eb8a4..cc60ae4 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.outline.expect
@@ -22,8 +22,8 @@
     return new self::Class2::•(field);
 }
 static final field core::bool inSoundMode;
-static field (dynamic) → self::Class1 Class1_new;
-static field (dynamic) → self::Class2 Class2_new;
+static field (core::int) → self::Class1 Class1_new;
+static field (core::int) → self::Class2 Class2_new;
 static method main() → dynamic
   ;
 static method testInferred() → dynamic
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.transformed.expect
index 2d658941..2664cf0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.transformed.expect
@@ -2,16 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:28:18: Error: A value of type 'Class1 Function(int)' can't be assigned to a variable of type 'Class1 Function(dynamic)'.
-//  - 'Class1' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-// var Class1_new = Class1.new;
-//                  ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:29:18: Error: A value of type 'Class2 Function(int)' can't be assigned to a variable of type 'Class2 Function(dynamic)'.
-//  - 'Class2' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-// var Class2_new = Class2.new;
-//                  ^
-//
 // pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
 //     f1a(''); // error
 //         ^
@@ -46,14 +36,8 @@
     return new self::Class2::•(field);
 }
 static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
-static field (dynamic) → self::Class1 Class1_new = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:28:18: Error: A value of type 'Class1 Function(int)' can't be assigned to a variable of type 'Class1 Function(dynamic)'.
- - 'Class1' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-var Class1_new = Class1.new;
-                 ^" in (#C1) as{TypeError,ForNonNullableByDefault} (dynamic) → self::Class1;
-static field (dynamic) → self::Class2 Class2_new = let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:29:18: Error: A value of type 'Class2 Function(int)' can't be assigned to a variable of type 'Class2 Function(dynamic)'.
- - 'Class2' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart'.
-var Class2_new = Class2.new;
-                 ^" in (#C2) as{TypeError,ForNonNullableByDefault} (dynamic) → self::Class2;
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
 static method main() → dynamic {
   core::print("inSoundMode: ${self::inSoundMode}");
   self::testInferred();
@@ -65,7 +49,7 @@
   self::Class1 c1a = f1a(0){(core::int) → self::Class1};
   self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
   () → Null {
-    f1a(let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f1a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
   };
@@ -79,7 +63,7 @@
   self::Class2 c2a = f2a(0){(core::int) → self::Class2};
   self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
   () → Null {
-    f2a(let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f2a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
   };
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart
new file mode 100644
index 0000000..e923b7a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+var A_new = A.new;
+var B_new = B.new;
+var F_new = F.new;
+var G_new = G.new;
+
+class A {
+  int field1 = 0;
+
+  A(this.field1);
+  A.named(this.field1);
+}
+
+class B<T> implements A {
+  var field1;
+  T field2;
+
+  B(this.field1, this.field2);
+  B.named(this.field1, this.field2);
+}
+
+typedef F<T> = A;
+typedef G<T extends num> = B;
+
+var A_named = A.named;
+var B_named = B<int>.named;
+var F_named = F.named;
+var G_named = G<int>.named;
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.expect
new file mode 100644
index 0000000..d952a09
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+  field core::int field1 = 0;
+  constructor •(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  constructor named(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  static method _#new#tearOff(core::int field1) → self::A
+    return new self::A::•(field1);
+  static method _#named#tearOff(core::int field1) → self::A
+    return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+  field core::int field1;
+  generic-covariant-impl field self::B::T% field2;
+  constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+  static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+    return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new = #C1;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new = #C2;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new = #C3;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new = #C4;
+static field (core::int) → self::A A_named = #C5;
+static field (core::int, core::int) → self::B<core::int> B_named = #C7;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named = #C8;
+static field (core::int, dynamic) → self::B<dynamic> G_named = #C9;
+static method main() → dynamic {}
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::named<dynamic>(field1, field2);
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::B::_#new#tearOff
+  #C3 = static-tearoff self::_#F#new#tearOff
+  #C4 = static-tearoff self::_#G#new#tearOff
+  #C5 = static-tearoff self::A::_#named#tearOff
+  #C6 = static-tearoff self::B::_#named#tearOff
+  #C7 = instantiation self::B::_#named#tearOff <core::int>
+  #C8 = static-tearoff self::_#F#named#tearOff
+  #C9 = instantiation self::B::_#named#tearOff <dynamic>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..d952a09
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+  field core::int field1 = 0;
+  constructor •(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  constructor named(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  static method _#new#tearOff(core::int field1) → self::A
+    return new self::A::•(field1);
+  static method _#named#tearOff(core::int field1) → self::A
+    return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+  field core::int field1;
+  generic-covariant-impl field self::B::T% field2;
+  constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+  static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+    return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new = #C1;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new = #C2;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new = #C3;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new = #C4;
+static field (core::int) → self::A A_named = #C5;
+static field (core::int, core::int) → self::B<core::int> B_named = #C7;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named = #C8;
+static field (core::int, dynamic) → self::B<dynamic> G_named = #C9;
+static method main() → dynamic {}
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::named<dynamic>(field1, field2);
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::B::_#new#tearOff
+  #C3 = static-tearoff self::_#F#new#tearOff
+  #C4 = static-tearoff self::_#G#new#tearOff
+  #C5 = static-tearoff self::A::_#named#tearOff
+  #C6 = static-tearoff self::B::_#named#tearOff
+  #C7 = instantiation self::B::_#named#tearOff <core::int>
+  #C8 = static-tearoff self::_#F#named#tearOff
+  #C9 = instantiation self::B::_#named#tearOff <dynamic>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..12bef00
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+var A_new = A.new;
+var B_new = B.new;
+var F_new = F.new;
+var G_new = G.new;
+class A {
+  int field1 = 0;
+  A(this.field1);
+  A.named(this.field1);
+}
+class B<T> implements A {
+  var field1;
+  T field2;
+  B(this.field1, this.field2);
+  B.named(this.field1, this.field2);
+}
+typedef F<T> = A;
+typedef G<T extends num> = B;
+var A_named = A.named;
+var B_named = B<int>.named;
+var F_named = F.named;
+var G_named = G<int>.named;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.expect
new file mode 100644
index 0000000..9294ac3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+  field core::int field1 = 0;
+  constructor •(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  constructor named(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  static method _#new#tearOff(core::int field1) → self::A
+    return new self::A::•(field1);
+  static method _#named#tearOff(core::int field1) → self::A
+    return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+  field core::int field1;
+  generic-covariant-impl field self::B::T% field2;
+  constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+  static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+    return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new = #C1;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new = #C2;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new = #C3;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new = #C4;
+static field (core::int) → self::A A_named = #C5;
+static field (core::int, core::int) → self::B<core::int> B_named = #C7;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named = #C8;
+static field (core::int, dynamic) → self::B<dynamic> G_named = #C9;
+static method main() → dynamic {}
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::named<dynamic>(field1, field2);
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::B::_#new#tearOff
+  #C3 = static-tearoff self::_#F#new#tearOff
+  #C4 = static-tearoff self::_#G#new#tearOff
+  #C5 = static-tearoff self::A::_#named#tearOff
+  #C6 = static-tearoff self::B::_#named#tearOff
+  #C7 = instantiation self::B::_#named#tearOff <core::int*>
+  #C8 = static-tearoff self::_#F#named#tearOff
+  #C9 = instantiation self::B::_#named#tearOff <dynamic>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..c32ee60
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.outline.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+  field core::int field1;
+  constructor •(core::int field1) → self::A
+    ;
+  constructor named(core::int field1) → self::A
+    ;
+  static method _#new#tearOff(core::int field1) → self::A
+    return new self::A::•(field1);
+  static method _#named#tearOff(core::int field1) → self::A
+    return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+  field core::int field1;
+  generic-covariant-impl field self::B::T% field2;
+  constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    ;
+  constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+  static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+    return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new;
+static field (core::int) → self::A A_named;
+static field (core::int, core::int) → self::B<core::int> B_named;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named;
+static field (core::int, dynamic) → self::B<dynamic> G_named;
+static method main() → dynamic
+  ;
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::named<dynamic>(field1, field2);
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..9294ac3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+  field core::int field1 = 0;
+  constructor •(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  constructor named(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  static method _#new#tearOff(core::int field1) → self::A
+    return new self::A::•(field1);
+  static method _#named#tearOff(core::int field1) → self::A
+    return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+  field core::int field1;
+  generic-covariant-impl field self::B::T% field2;
+  constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+  static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+    return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new = #C1;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new = #C2;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new = #C3;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new = #C4;
+static field (core::int) → self::A A_named = #C5;
+static field (core::int, core::int) → self::B<core::int> B_named = #C7;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named = #C8;
+static field (core::int, dynamic) → self::B<dynamic> G_named = #C9;
+static method main() → dynamic {}
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::named<dynamic>(field1, field2);
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::B::_#new#tearOff
+  #C3 = static-tearoff self::_#F#new#tearOff
+  #C4 = static-tearoff self::_#G#new#tearOff
+  #C5 = static-tearoff self::A::_#named#tearOff
+  #C6 = static-tearoff self::B::_#named#tearOff
+  #C7 = instantiation self::B::_#named#tearOff <core::int*>
+  #C8 = static-tearoff self::_#F#named#tearOff
+  #C9 = instantiation self::B::_#named#tearOff <dynamic>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart
index 8bd470e..33453f6 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart
@@ -6,17 +6,15 @@
 
 typedef H<X, Y> = A<Y>;
 
-// TODO(johnniwinther): Use 'var' here when dependency on inferred parameter
-// types is handled.
-dynamic H_new = H.new;
-dynamic H_named = H.named;
-dynamic H_fact = H.fact;
-dynamic H_redirect = H.redirect;
+var H_new = H.new;
+var H_named = H.named;
+var H_fact = H.fact;
+var H_redirect = H.redirect;
 
-dynamic F_new = F.new;
-dynamic F_named = F.named;
-dynamic F_fact = F.fact;
-dynamic F_redirect = F.redirect;
+var F_new = F.new;
+var F_named = F.named;
+var F_fact = F.fact;
+var F_redirect = F.redirect;
 
 main() {
   expect(true, identical(F_new, F_new_lib));
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect
index 98b8997..3e82a43 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect
@@ -6,14 +6,14 @@
 import "org-dartlang-testcase:///typedef_identical_lib.dart";
 
 typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
-static field dynamic H_new = #C1;
-static field dynamic H_named = #C2;
-static field dynamic H_fact = #C3;
-static field dynamic H_redirect = #C4;
-static field dynamic F_new = #C5;
-static field dynamic F_named = #C6;
-static field dynamic F_fact = #C7;
-static field dynamic F_redirect = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new = #C1;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named = #C2;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact = #C3;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect = #C4;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect = #C8;
 static method main() → dynamic {
   self::expect(true, core::identical(self::F_new, typ::F_new_lib));
   self::expect(false, core::identical(self::F_new, typ::F_named_lib));
@@ -104,14 +104,14 @@
   static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
     return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
 }
-static field dynamic F_new_lib = #C5;
-static field dynamic F_named_lib = #C6;
-static field dynamic F_fact_lib = #C7;
-static field dynamic F_redirect_lib = #C8;
-static field dynamic G_new_lib = #C11;
-static field dynamic G_named_lib = #C12;
-static field dynamic G_fact_lib = #C13;
-static field dynamic G_redirect_lib = #C14;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib = #C11;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib = #C12;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib = #C13;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib = #C14;
 static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
   return new typ::A::•<typ::_#F#new#tearOff::Y%>();
 static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect
index b956c9c..f7eae91 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect
@@ -6,14 +6,14 @@
 import "org-dartlang-testcase:///typedef_identical_lib.dart";
 
 typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
-static field dynamic H_new = #C1;
-static field dynamic H_named = #C2;
-static field dynamic H_fact = #C3;
-static field dynamic H_redirect = #C4;
-static field dynamic F_new = #C5;
-static field dynamic F_named = #C6;
-static field dynamic F_fact = #C7;
-static field dynamic F_redirect = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new = #C1;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named = #C2;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact = #C3;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect = #C4;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect = #C8;
 static method main() → dynamic {
   self::expect(true, core::identical(self::F_new, typ::F_new_lib));
   self::expect(false, core::identical(self::F_new, typ::F_named_lib));
@@ -104,14 +104,14 @@
   static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
     return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
 }
-static field dynamic F_new_lib = #C5;
-static field dynamic F_named_lib = #C6;
-static field dynamic F_fact_lib = #C7;
-static field dynamic F_redirect_lib = #C8;
-static field dynamic G_new_lib = #C11;
-static field dynamic G_named_lib = #C12;
-static field dynamic G_fact_lib = #C13;
-static field dynamic G_redirect_lib = #C14;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib = #C11;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib = #C12;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib = #C13;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib = #C14;
 static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
   return new typ::A::•<typ::_#F#new#tearOff::Y%>();
 static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect
index 0f1bd66..8ca6604 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect
@@ -1,12 +1,12 @@
 import 'typedef_identical_lib.dart';
 typedef H<X, Y> = A<Y>;
-dynamic H_new = H.new;
-dynamic H_named = H.named;
-dynamic H_fact = H.fact;
-dynamic H_redirect = H.redirect;
-dynamic F_new = F.new;
-dynamic F_named = F.named;
-dynamic F_fact = F.fact;
-dynamic F_redirect = F.redirect;
+var H_new = H.new;
+var H_named = H.named;
+var H_fact = H.fact;
+var H_redirect = H.redirect;
+var F_new = F.new;
+var F_named = F.named;
+var F_fact = F.fact;
+var F_redirect = F.redirect;
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect
index 98b8997..3e82a43 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect
@@ -6,14 +6,14 @@
 import "org-dartlang-testcase:///typedef_identical_lib.dart";
 
 typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
-static field dynamic H_new = #C1;
-static field dynamic H_named = #C2;
-static field dynamic H_fact = #C3;
-static field dynamic H_redirect = #C4;
-static field dynamic F_new = #C5;
-static field dynamic F_named = #C6;
-static field dynamic F_fact = #C7;
-static field dynamic F_redirect = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new = #C1;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named = #C2;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact = #C3;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect = #C4;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect = #C8;
 static method main() → dynamic {
   self::expect(true, core::identical(self::F_new, typ::F_new_lib));
   self::expect(false, core::identical(self::F_new, typ::F_named_lib));
@@ -104,14 +104,14 @@
   static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
     return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
 }
-static field dynamic F_new_lib = #C5;
-static field dynamic F_named_lib = #C6;
-static field dynamic F_fact_lib = #C7;
-static field dynamic F_redirect_lib = #C8;
-static field dynamic G_new_lib = #C11;
-static field dynamic G_named_lib = #C12;
-static field dynamic G_fact_lib = #C13;
-static field dynamic G_redirect_lib = #C14;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib = #C11;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib = #C12;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib = #C13;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib = #C14;
 static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
   return new typ::A::•<typ::_#F#new#tearOff::Y%>();
 static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect
index 7f142cf..feafdc3 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect
@@ -6,14 +6,14 @@
 import "org-dartlang-testcase:///typedef_identical_lib.dart";
 
 typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
-static field dynamic H_new;
-static field dynamic H_named;
-static field dynamic H_fact;
-static field dynamic H_redirect;
-static field dynamic F_new;
-static field dynamic F_named;
-static field dynamic F_fact;
-static field dynamic F_redirect;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect;
 static method main() → dynamic
   ;
 static method expect(dynamic expected, dynamic actual) → dynamic
@@ -52,14 +52,14 @@
   static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
     return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
 }
-static field dynamic F_new_lib;
-static field dynamic F_named_lib;
-static field dynamic F_fact_lib;
-static field dynamic F_redirect_lib;
-static field dynamic G_new_lib;
-static field dynamic G_named_lib;
-static field dynamic G_fact_lib;
-static field dynamic G_redirect_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib;
 static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
   return new typ::A::•<typ::_#F#new#tearOff::Y%>();
 static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b]) → typ::A<typ::_#F#named#tearOff::Y%>
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect
index b956c9c..f7eae91 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect
@@ -6,14 +6,14 @@
 import "org-dartlang-testcase:///typedef_identical_lib.dart";
 
 typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
-static field dynamic H_new = #C1;
-static field dynamic H_named = #C2;
-static field dynamic H_fact = #C3;
-static field dynamic H_redirect = #C4;
-static field dynamic F_new = #C5;
-static field dynamic F_named = #C6;
-static field dynamic F_fact = #C7;
-static field dynamic F_redirect = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new = #C1;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named = #C2;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact = #C3;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect = #C4;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect = #C8;
 static method main() → dynamic {
   self::expect(true, core::identical(self::F_new, typ::F_new_lib));
   self::expect(false, core::identical(self::F_new, typ::F_named_lib));
@@ -104,14 +104,14 @@
   static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
     return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
 }
-static field dynamic F_new_lib = #C5;
-static field dynamic F_named_lib = #C6;
-static field dynamic F_fact_lib = #C7;
-static field dynamic F_redirect_lib = #C8;
-static field dynamic G_new_lib = #C11;
-static field dynamic G_named_lib = #C12;
-static field dynamic G_fact_lib = #C13;
-static field dynamic G_redirect_lib = #C14;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib = #C11;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib = #C12;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib = #C13;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib = #C14;
 static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
   return new typ::A::•<typ::_#F#new#tearOff::Y%>();
 static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.dart
index a57b86b..e21df56 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.dart
@@ -12,12 +12,12 @@
 typedef F<X, Y> = A<Y>;
 typedef G<X, Y> = A<Y>;
 
-dynamic F_new_lib = F.new;
-dynamic F_named_lib = F.named;
-dynamic F_fact_lib = F.fact;
-dynamic F_redirect_lib = F.redirect;
+var F_new_lib = F.new;
+var F_named_lib = F.named;
+var F_fact_lib = F.fact;
+var F_redirect_lib = F.redirect;
 
-dynamic G_new_lib = G.new;
-dynamic G_named_lib = G.named;
-dynamic G_fact_lib = G.fact;
-dynamic G_redirect_lib = G.redirect;
\ No newline at end of file
+var G_new_lib = G.new;
+var G_named_lib = G.named;
+var G_fact_lib = G.fact;
+var G_redirect_lib = G.redirect;
\ No newline at end of file
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 8082cff..e8cae1b 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -32,6 +32,7 @@
 constructor_tearoffs/inferred_constructor_tear_off: FormatterCrash
 constructor_tearoffs/instantiation: FormatterCrash
 constructor_tearoffs/lowering/inferred_constructor_tear_off: FormatterCrash
+constructor_tearoffs/lowering/inferred_tear_off: FormatterCrash
 constructor_tearoffs/lowering/typedef_from_dill/main: FormatterCrash
 constructor_tearoffs/lowering/typedef_identical: FormatterCrash
 constructor_tearoffs/nongeneric_tearoff_with_context: FormatterCrash
diff --git a/tools/VERSION b/tools/VERSION
index 778bf10..1633d98 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 348
+PRERELEASE 349
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/flutter/analyze_flutter_plugins.sh b/tools/bots/flutter/analyze_flutter_plugins.sh
index 9696c74..3616faa 100755
--- a/tools/bots/flutter/analyze_flutter_plugins.sh
+++ b/tools/bots/flutter/analyze_flutter_plugins.sh
@@ -36,4 +36,6 @@
 (cd script/tool; dart analyze --fatal-infos)
 
 # Invoke the repo's analysis script.
-./script/tool_runner.sh analyze --analysis-sdk $sdk
+./script/tool_runner.sh analyze \
+  --analysis-sdk $sdk \
+  --custom-analysis=script/configs/custom_analysis.yaml