Version 2.14.0-365.0.dev

Merge commit 'b08d3ee537a0970512abf516aa707e46c4e2ef7f' into 'dev'
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index e29a156..12ee6bb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -20,6 +20,7 @@
 
 import 'dart:io' as io;
 
+import 'package:front_end/src/fasta/kernel/constructor_tearoff_lowering.dart';
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/clone.dart';
@@ -736,6 +737,23 @@
                   constant.tearOffConstant.getType(_staticTypeContext!))
                 ..fileOffset = expression.fileOffset,
               constant.types.map(substitution.substituteType).toList());
+        } else {
+          LoweredTypedefTearOff? loweredTypedefTearOff =
+              LoweredTypedefTearOff.fromConstant(constant);
+          if (loweredTypedefTearOff != null) {
+            Constant tearOffConstant = constantEvaluator
+                .canonicalize(loweredTypedefTearOff.targetTearOffConstant);
+            Substitution substitution = Substitution.fromPairs(
+                loweredTypedefTearOff.typedefTearOff.function.typeParameters,
+                node.typeArguments);
+            return new Instantiation(
+                new ConstantExpression(tearOffConstant,
+                    tearOffConstant.getType(_staticTypeContext!))
+                  ..fileOffset = expression.fileOffset,
+                loweredTypedefTearOff.typeArguments
+                    .map(substitution.substituteType)
+                    .toList());
+          }
         }
       }
     }
@@ -3307,6 +3325,19 @@
           typeArguments =
               constant.types.map(substitution.substituteType).toList();
           constant = constant.tearOffConstant;
+        } else {
+          LoweredTypedefTearOff? loweredTypedefTearOff =
+              LoweredTypedefTearOff.fromConstant(constant);
+          if (loweredTypedefTearOff != null) {
+            constant =
+                canonicalize(loweredTypedefTearOff.targetTearOffConstant);
+            Substitution substitution = Substitution.fromPairs(
+                loweredTypedefTearOff.typedefTearOff.function.typeParameters,
+                node.typeArguments);
+            typeArguments = loweredTypedefTearOff.typeArguments
+                .map(substitution.substituteType)
+                .toList();
+          }
         }
         return canonicalize(new InstantiationConstant(constant, typeArguments));
       } else {
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 ae3a7d3..ada23ac 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
@@ -76,6 +76,11 @@
   return null;
 }
 
+/// Returns `true` if [procedure] is a lowered typedef tear off.
+bool isTypedefTearOffLowering(Procedure procedure) {
+  return extractTypedefNameFromTearOff(procedure.name) != null;
+}
+
 /// Creates the [Procedure] for the lowering of a generative constructor of
 /// the given [name] in [compilationUnit].
 ///
@@ -370,3 +375,57 @@
     ..fileOffset = tearOff.fileOffset
     ..parent = tearOff.function;
 }
+
+/// Reverse engineered typedef tear off information.
+class LoweredTypedefTearOff {
+  Procedure typedefTearOff;
+  Constant targetTearOffConstant;
+  List<DartType> typeArguments;
+
+  LoweredTypedefTearOff(
+      this.typedefTearOff, this.targetTearOffConstant, this.typeArguments);
+
+  /// Reverse engineers [constant] to a [LoweredTypedefTearOff] if [constant] is
+  /// the encoding of a lowered typedef tear off.
+  // TODO(johnniwinther): Check that this works with outlines.
+  static LoweredTypedefTearOff? fromConstant(Constant constant) {
+    if (constant is StaticTearOffConstant &&
+        isTypedefTearOffLowering(constant.target)) {
+      Procedure typedefTearOff = constant.target;
+      Statement? body = typedefTearOff.function.body;
+      if (body is ReturnStatement) {
+        Expression? constructorInvocation = body.expression;
+        Member? target;
+        List<DartType>? typeArguments;
+        if (constructorInvocation is ConstructorInvocation) {
+          target = constructorInvocation.target;
+          typeArguments = constructorInvocation.arguments.types;
+        } else if (constructorInvocation is StaticInvocation) {
+          target = constructorInvocation.target;
+          typeArguments = constructorInvocation.arguments.types;
+        }
+        if (target != null) {
+          Class cls = target.enclosingClass!;
+          Name tearOffName =
+              constructorTearOffName(target.name.text, cls.enclosingLibrary);
+          for (Procedure procedure in cls.procedures) {
+            if (procedure.name == tearOffName) {
+              target = procedure;
+              break;
+            }
+          }
+          Constant tearOffConstant;
+          if (target is Constructor ||
+              target is Procedure && target.isFactory) {
+            tearOffConstant = new ConstructorTearOffConstant(target!);
+          } else {
+            tearOffConstant = new StaticTearOffConstant(target as Procedure);
+          }
+          return new LoweredTypedefTearOff(
+              typedefTearOff, tearOffConstant, typeArguments!);
+        }
+      }
+    }
+    return null;
+  }
+}
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index ae9d883..f8df10f 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -386,6 +386,7 @@
 enforced
 enforces
 enforcing
+engineered
 enumerates
 env
 eof
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 217f03c..ad13d98 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -343,12 +343,22 @@
 f1a
 f1b
 f1c
+f1d
+f1e
+f1f
+f1g
+f1h
+f1i
 f2
 f2a
 f2b
 f2c
 f2d
 f2e
+f2f
+f2g
+f2h
+f2i
 f3
 f3a
 f3b
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart
index 4291871..601da2a 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart
@@ -2,6 +2,8 @@
 // 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.
 
+final bool inSoundMode = <int?>[] is! List<int>;
+
 class A<T> {}
 
 typedef F<X extends num> = A<X>;
@@ -46,17 +48,24 @@
   var h2b = H<T, String>.new;
   A<T> Function() h2c = H.new;
 
-  expect(f1a, f2a);
+  // TODO(johnniwinther): Enable these if structural equality is supported at
+  // runtime.
+  /*expect(f1a, f2a);
   expect(f2a, f2b);
-  expect(f2a, f2c);
+  expect(f2a, f2c);*/
 
   expect(g1a, g2a);
   expect(g2a, g2b);
-  expect(g2a, g2c);
+  if (inSoundMode) {
+    // In weak mode type arguments of constants are weakened.
+    expect(g2a, g2c);
+  }
 
-  expect(h1a, h2a);
+  // TODO(johnniwinther): Enable these if structural equality is supported at
+  // runtime.
+  /*expect(h1a, h2a);
   expect(h2a, h2b);
-  expect(h2a, h2c);
+  expect(h2a, h2c);*/
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.expect
index 8309676..ce055a4 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.expect
@@ -10,6 +10,7 @@
     : super core::Object::•()
     ;
 }
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
 static const field () → self::A<core::int> f1a = #C2;
 static const field () → self::A<core::int> f1b = #C2;
 static const field () → self::A<core::int> f1c = #C2;
@@ -38,15 +39,11 @@
   () → self::A<self::test::T> h2a = #C1<self::test::T>;
   () → self::A<self::test::T> h2b = #C1<self::test::T>;
   () → self::A<self::test::T> h2c = #C1<self::test::T>;
-  self::expect(#C2, f2a);
-  self::expect(f2a, f2b);
-  self::expect(f2a, f2c);
   self::expect(#C2, g2a);
   self::expect(g2a, g2b);
-  self::expect(g2a, g2c);
-  self::expect(#C2, h2a);
-  self::expect(h2a, h2b);
-  self::expect(h2a, h2c);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.transformed.expect
index 52278d0..0f0953f 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.transformed.expect
@@ -10,6 +10,7 @@
     : super core::Object::•()
     ;
 }
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
 static const field () → self::A<core::int> f1a = #C2;
 static const field () → self::A<core::int> f1b = #C2;
 static const field () → self::A<core::int> f1c = #C2;
@@ -38,15 +39,11 @@
   () → self::A<self::test::T> h2a = #C1<self::test::T>;
   () → self::A<self::test::T> h2b = #C1<self::test::T>;
   () → self::A<self::test::T> h2c = #C1<self::test::T>;
-  self::expect(#C2, f2a);
-  self::expect(f2a, f2b);
-  self::expect(f2a, f2c);
   self::expect(#C2, g2a);
   self::expect(g2a, g2b);
-  self::expect(g2a, g2c);
-  self::expect(#C2, h2a);
-  self::expect(h2a, h2b);
-  self::expect(h2a, h2c);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
@@ -59,10 +56,10 @@
 }
 
 Extra constant evaluation status:
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:26:3 -> BoolConstant(true)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:27:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:28:3 -> BoolConstant(true)
 Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:29:3 -> BoolConstant(true)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:30:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:31:3 -> BoolConstant(true)
 Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:32:3 -> BoolConstant(true)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:33:3 -> BoolConstant(true)
-Extra constant evaluation: evaluated: 45, effectively constant: 6
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:34:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:35:3 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 33, effectively constant: 6
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.textual_outline.expect
index 36311c1..71dbef8 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.textual_outline.expect
@@ -1,3 +1,4 @@
+final bool inSoundMode = <int?>[] is! List<int>;
 class A<T> {}
 typedef F<X extends num> = A<X>;
 typedef G<Y> = A<int>;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.expect
index 2dc0e88..7f08054 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.expect
@@ -10,6 +10,7 @@
     : super core::Object::•()
     ;
 }
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
 static const field () → self::A<core::int> f1a = #C2;
 static const field () → self::A<core::int> f1b = #C2;
 static const field () → self::A<core::int> f1c = #C2;
@@ -38,15 +39,11 @@
   () → self::A<self::test::T> h2a = #C1<self::test::T>;
   () → self::A<self::test::T> h2b = #C1<self::test::T>;
   () → self::A<self::test::T> h2c = #C1<self::test::T>;
-  self::expect(#C2, f2a);
-  self::expect(f2a, f2b);
-  self::expect(f2a, f2c);
   self::expect(#C2, g2a);
   self::expect(g2a, g2b);
-  self::expect(g2a, g2c);
-  self::expect(#C2, h2a);
-  self::expect(h2a, h2b);
-  self::expect(h2a, h2c);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.outline.expect
index 0ce38f00..54daed1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.outline.expect
@@ -9,6 +9,7 @@
   synthetic constructor •() → self::A<self::A::T%>
     ;
 }
+static final field core::bool inSoundMode;
 static const field () → self::A<core::int> f1a = self::A::•<core::int>;
 static const field () → self::A<core::int> f1b = self::A::•<core::int>;
 static const field () → self::A<core::int> f1c = <X extends core::num>.(self::A::•<X>)<core::int>;
@@ -27,13 +28,13 @@
 
 
 Extra constant evaluation status:
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:11:13 -> InstantiationConstant(A.<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:12:13 -> InstantiationConstant(A.<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:13:31 -> InstantiationConstant(A.<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:15:13 -> InstantiationConstant(A.<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:16:13 -> InstantiationConstant(A.<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:17:31 -> InstantiationConstant(A.<int>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:19:13 -> InstantiationConstant(A.<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:20:13 -> InstantiationConstant(A.<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:21:31 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:13:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:14:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:15:31 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:17:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:18:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:19:31 -> InstantiationConstant(A.<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:21:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:22:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:23:31 -> InstantiationConstant(A.<int*>)
 Extra constant evaluation: evaluated: 9, effectively constant: 9
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.transformed.expect
index 9c78714..4b8f00e 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.transformed.expect
@@ -10,6 +10,7 @@
     : super core::Object::•()
     ;
 }
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
 static const field () → self::A<core::int> f1a = #C2;
 static const field () → self::A<core::int> f1b = #C2;
 static const field () → self::A<core::int> f1c = #C2;
@@ -38,15 +39,11 @@
   () → self::A<self::test::T> h2a = #C1<self::test::T>;
   () → self::A<self::test::T> h2b = #C1<self::test::T>;
   () → self::A<self::test::T> h2c = #C1<self::test::T>;
-  self::expect(#C2, f2a);
-  self::expect(f2a, f2b);
-  self::expect(f2a, f2c);
   self::expect(#C2, g2a);
   self::expect(g2a, g2b);
-  self::expect(g2a, g2c);
-  self::expect(#C2, h2a);
-  self::expect(h2a, h2b);
-  self::expect(h2a, h2c);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
@@ -60,10 +57,10 @@
 }
 
 Extra constant evaluation status:
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:26:3 -> BoolConstant(true)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:27:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:28:3 -> BoolConstant(true)
 Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:29:3 -> BoolConstant(true)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:30:3 -> BoolConstant(false)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:32:3 -> BoolConstant(true)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:33:3 -> BoolConstant(true)
-Extra constant evaluation: evaluated: 45, effectively constant: 6
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:31:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:32:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:34:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:35:3 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 33, effectively constant: 6
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart
index 4291871..36599bd 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart
@@ -2,7 +2,13 @@
 // 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.
 
-class A<T> {}
+final bool inSoundMode = <int?>[] is! List<int>;
+
+class A<T> {
+  A();
+  factory A.fact() => new A<T>();
+  factory A.redirect() = A<T>;
+}
 
 typedef F<X extends num> = A<X>;
 typedef G<Y> = A<int>;
@@ -11,6 +17,12 @@
 const f1a = A<int>.new;
 const f1b = F<int>.new;
 const A<int> Function() f1c = F.new;
+const f1d = A<int>.fact;
+const f1e = F<int>.fact;
+const A<int> Function() f1f = F.fact;
+const f1g = A<int>.redirect;
+const f1h = F<int>.redirect;
+const A<int> Function() f1i = F.redirect;
 
 const g1a = A<int>.new;
 const g1b = G<String>.new;
@@ -26,6 +38,12 @@
   identical(f1a, f1b);
   identical(f1a, f1c);
 
+  identical(f1d, f1e);
+  identical(f1d, f1f);
+
+  identical(f1g, f1h);
+  identical(f1g, f1i);
+
   identical(g1a, g1b);
   identical(g1a, g1c);
 
@@ -37,6 +55,12 @@
   var f2a = A<T>.new;
   var f2b = F<T>.new;
   A<T> Function() f2c = F.new;
+  var f2d = A<T>.fact;
+  var f2e = F<T>.fact;
+  A<T> Function() f2f = F.fact;
+  var f2g = A<T>.redirect;
+  var f2h = F<T>.redirect;
+  A<T> Function() f2i = F.redirect;
 
   var g2a = A<int>.new;
   var g2b = G<T>.new;
@@ -46,17 +70,32 @@
   var h2b = H<T, String>.new;
   A<T> Function() h2c = H.new;
 
-  expect(f1a, f2a);
+  // TODO(johnniwinther): Enable these if structural equality is supported at
+  // runtime.
+  /*expect(f1a, f2a);
   expect(f2a, f2b);
   expect(f2a, f2c);
 
+  expect(f1d, f2d);
+  expect(f2d, f2e);
+  expect(f2d, f2f);
+
+  expect(f1g, f2g);
+  expect(f2g, f2h);
+  expect(f2g, f2i);*/
+
   expect(g1a, g2a);
   expect(g2a, g2b);
-  expect(g2a, g2c);
+  if (inSoundMode) {
+    // In weak mode type arguments of constants are weakened.
+    expect(g2a, g2c);
+  }
 
-  expect(h1a, h2a);
+  // TODO(johnniwinther): Enable these if structural equality is supported at
+  // runtime.
+  /*expect(h1a, h2a);
   expect(h2a, h2b);
-  expect(h2a, h2c);
+  expect(h2a, h2c);*/
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.expect
index 56ac791..9277874 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.expect
@@ -6,49 +6,71 @@
 typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
 typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
 class A<T extends core::Object? = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T%>
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
     : super core::Object::•()
     ;
   static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
     return new self::A::•<self::A::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+    return self::A::fact<self::A::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+    return new self::A::•<self::A::_#redirect#tearOff::T%>();
 }
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
 static const field () → self::A<core::int> f1a = #C2;
 static const field () → self::A<core::int> f1b = #C2;
-static const field () → self::A<core::int> f1c = #C4;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> f1d = #C4;
+static const field () → self::A<core::int> f1e = #C4;
+static const field () → self::A<core::int> f1f = #C4;
+static const field () → self::A<core::int> f1g = #C6;
+static const field () → self::A<core::int> f1h = #C6;
+static const field () → self::A<core::int> f1i = #C6;
 static const field () → self::A<core::int> g1a = #C2;
 static const field () → self::A<core::int> g1b = #C2;
-static const field () → self::A<core::int> g1c = #C6;
+static const field () → self::A<core::int> g1c = #C2;
 static const field () → self::A<core::int> h1a = #C2;
 static const field () → self::A<core::int> h1b = #C2;
-static const field () → self::A<core::int> h1c = #C8;
+static const field () → self::A<core::int> h1c = #C2;
 static method main() → dynamic {
   self::test<core::int>();
   core::identical(#C2, #C2);
-  core::identical(#C2, #C4);
   core::identical(#C2, #C2);
-  core::identical(#C2, #C6);
+  core::identical(#C4, #C4);
+  core::identical(#C4, #C4);
+  core::identical(#C6, #C6);
+  core::identical(#C6, #C6);
   core::identical(#C2, #C2);
-  core::identical(#C2, #C8);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
 }
 static method test<T extends core::num>() → dynamic {
   () → self::A<self::test::T> f2a = #C1<self::test::T>;
   () → self::A<self::test::T> f2b = #C1<self::test::T>;
-  () → self::A<self::test::T> f2c = #C3<self::test::T>;
+  () → self::A<self::test::T> f2c = #C1<self::test::T>;
+  () → self::A<self::test::T> f2d = #C3<self::test::T>;
+  () → self::A<self::test::T> f2e = #C3<self::test::T>;
+  () → self::A<self::test::T> f2f = #C3<self::test::T>;
+  () → self::A<self::test::T> f2g = #C5<self::test::T>;
+  () → self::A<self::test::T> f2h = #C5<self::test::T>;
+  () → self::A<self::test::T> f2i = #C5<self::test::T>;
   () → self::A<core::int> g2a = #C2;
   () → self::A<core::int> g2b = #C2;
-  () → self::A<core::int> g2c = #C6;
+  () → self::A<core::int> g2c = #C2;
   () → self::A<self::test::T> h2a = #C1<self::test::T>;
   () → self::A<self::test::T> h2b = #C1<self::test::T>;
-  () → self::A<self::test::T> h2c = #C7<self::test::T, dynamic>;
-  self::expect(#C2, f2a);
-  self::expect(f2a, f2b);
-  self::expect(f2a, f2c);
+  () → self::A<self::test::T> h2c = #C1<self::test::T>;
   self::expect(#C2, g2a);
   self::expect(g2a, g2b);
-  self::expect(g2a, g2c);
-  self::expect(#C2, h2a);
-  self::expect(h2a, h2b);
-  self::expect(h2a, h2c);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
@@ -56,18 +78,28 @@
 }
 static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
   return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+  return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+  return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
 static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
   return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::_#redirect#tearOff<core::int>();
 static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
   return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+  return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+  return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
 
 constants  {
   #C1 = static-tearoff self::A::_#new#tearOff
   #C2 = instantiation self::A::_#new#tearOff <core::int>
-  #C3 = static-tearoff self::_#F#new#tearOff
-  #C4 = instantiation self::_#F#new#tearOff <core::int>
-  #C5 = static-tearoff self::_#G#new#tearOff
-  #C6 = instantiation self::_#G#new#tearOff <dynamic>
-  #C7 = static-tearoff self::_#H#new#tearOff
-  #C8 = instantiation self::_#H#new#tearOff <core::int, dynamic>
+  #C3 = static-tearoff self::A::_#fact#tearOff
+  #C4 = instantiation self::A::_#fact#tearOff <core::int>
+  #C5 = static-tearoff self::A::_#redirect#tearOff
+  #C6 = instantiation self::A::_#redirect#tearOff <core::int>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.transformed.expect
index 320d6db..bfa45c0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.transformed.expect
@@ -6,49 +6,71 @@
 typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
 typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
 class A<T extends core::Object? = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T%>
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
     : super core::Object::•()
     ;
   static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
     return new self::A::•<self::A::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+    return self::A::fact<self::A::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let Never #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+    return new self::A::•<self::A::_#redirect#tearOff::T%>();
 }
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
 static const field () → self::A<core::int> f1a = #C2;
 static const field () → self::A<core::int> f1b = #C2;
-static const field () → self::A<core::int> f1c = #C4;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> f1d = #C4;
+static const field () → self::A<core::int> f1e = #C4;
+static const field () → self::A<core::int> f1f = #C4;
+static const field () → self::A<core::int> f1g = #C6;
+static const field () → self::A<core::int> f1h = #C6;
+static const field () → self::A<core::int> f1i = #C6;
 static const field () → self::A<core::int> g1a = #C2;
 static const field () → self::A<core::int> g1b = #C2;
-static const field () → self::A<core::int> g1c = #C6;
+static const field () → self::A<core::int> g1c = #C2;
 static const field () → self::A<core::int> h1a = #C2;
 static const field () → self::A<core::int> h1b = #C2;
-static const field () → self::A<core::int> h1c = #C8;
+static const field () → self::A<core::int> h1c = #C2;
 static method main() → dynamic {
   self::test<core::int>();
   core::identical(#C2, #C2);
-  core::identical(#C2, #C4);
   core::identical(#C2, #C2);
-  core::identical(#C2, #C6);
+  core::identical(#C4, #C4);
+  core::identical(#C4, #C4);
+  core::identical(#C6, #C6);
+  core::identical(#C6, #C6);
   core::identical(#C2, #C2);
-  core::identical(#C2, #C8);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
 }
 static method test<T extends core::num>() → dynamic {
   () → self::A<self::test::T> f2a = #C1<self::test::T>;
   () → self::A<self::test::T> f2b = #C1<self::test::T>;
-  () → self::A<self::test::T> f2c = #C3<self::test::T>;
+  () → self::A<self::test::T> f2c = #C1<self::test::T>;
+  () → self::A<self::test::T> f2d = #C3<self::test::T>;
+  () → self::A<self::test::T> f2e = #C3<self::test::T>;
+  () → self::A<self::test::T> f2f = #C3<self::test::T>;
+  () → self::A<self::test::T> f2g = #C5<self::test::T>;
+  () → self::A<self::test::T> f2h = #C5<self::test::T>;
+  () → self::A<self::test::T> f2i = #C5<self::test::T>;
   () → self::A<core::int> g2a = #C2;
   () → self::A<core::int> g2b = #C2;
-  () → self::A<core::int> g2c = #C6;
+  () → self::A<core::int> g2c = #C2;
   () → self::A<self::test::T> h2a = #C1<self::test::T>;
   () → self::A<self::test::T> h2b = #C1<self::test::T>;
-  () → self::A<self::test::T> h2c = #C7<self::test::T, dynamic>;
-  self::expect(#C2, f2a);
-  self::expect(f2a, f2b);
-  self::expect(f2a, f2c);
+  () → self::A<self::test::T> h2c = #C1<self::test::T>;
   self::expect(#C2, g2a);
   self::expect(g2a, g2b);
-  self::expect(g2a, g2c);
-  self::expect(#C2, h2a);
-  self::expect(h2a, h2b);
-  self::expect(h2a, h2c);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
@@ -56,27 +78,41 @@
 }
 static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
   return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+  return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+  return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
 static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
   return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::_#redirect#tearOff<core::int>();
 static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
   return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+  return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+  return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
 
 constants  {
   #C1 = static-tearoff self::A::_#new#tearOff
   #C2 = instantiation self::A::_#new#tearOff <core::int>
-  #C3 = static-tearoff self::_#F#new#tearOff
-  #C4 = instantiation self::_#F#new#tearOff <core::int>
-  #C5 = static-tearoff self::_#G#new#tearOff
-  #C6 = instantiation self::_#G#new#tearOff <dynamic>
-  #C7 = static-tearoff self::_#H#new#tearOff
-  #C8 = instantiation self::_#H#new#tearOff <core::int, dynamic>
+  #C3 = static-tearoff self::A::_#fact#tearOff
+  #C4 = instantiation self::A::_#fact#tearOff <core::int>
+  #C5 = static-tearoff self::A::_#redirect#tearOff
+  #C6 = instantiation self::A::_#redirect#tearOff <core::int>
 }
 
 Extra constant evaluation status:
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:26:3 -> BoolConstant(true)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:27:3 -> BoolConstant(false)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:29:3 -> BoolConstant(true)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:30:3 -> BoolConstant(false)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:32:3 -> BoolConstant(true)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:33:3 -> BoolConstant(false)
-Extra constant evaluation: evaluated: 49, effectively constant: 6
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:38:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:39:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:41:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:42:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:44:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:45:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:47:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:48:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:50:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:51:3 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 61, effectively constant: 10
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.textual_outline.expect
index 36311c1..8731bf4 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.textual_outline.expect
@@ -1,10 +1,21 @@
-class A<T> {}
+final bool inSoundMode = <int?>[] is! List<int>;
+class A<T> {
+  A();
+  factory A.fact() => new A<T>();
+  factory A.redirect() = A<T>;
+}
 typedef F<X extends num> = A<X>;
 typedef G<Y> = A<int>;
 typedef H<X, Y> = A<X>;
 const f1a = A<int>.new;
 const f1b = F<int>.new;
 const A<int> Function() f1c = F.new;
+const f1d = A<int>.fact;
+const f1e = F<int>.fact;
+const A<int> Function() f1f = F.fact;
+const f1g = A<int>.redirect;
+const f1h = F<int>.redirect;
+const A<int> Function() f1i = F.redirect;
 const g1a = A<int>.new;
 const g1b = G<String>.new;
 const A<int> Function() g1c = G.new;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.expect
index c37338f..8e0844f 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.expect
@@ -6,49 +6,71 @@
 typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
 typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
 class A<T extends core::Object? = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T%>
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
     : super core::Object::•()
     ;
   static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
     return new self::A::•<self::A::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+    return self::A::fact<self::A::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+    return new self::A::•<self::A::_#redirect#tearOff::T%>();
 }
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
 static const field () → self::A<core::int> f1a = #C2;
 static const field () → self::A<core::int> f1b = #C2;
-static const field () → self::A<core::int> f1c = #C4;
+static const field () → self::A<core::int> f1c = #C3;
+static const field () → self::A<core::int> f1d = #C5;
+static const field () → self::A<core::int> f1e = #C5;
+static const field () → self::A<core::int> f1f = #C6;
+static const field () → self::A<core::int> f1g = #C8;
+static const field () → self::A<core::int> f1h = #C8;
+static const field () → self::A<core::int> f1i = #C9;
 static const field () → self::A<core::int> g1a = #C2;
 static const field () → self::A<core::int> g1b = #C2;
-static const field () → self::A<core::int> g1c = #C6;
+static const field () → self::A<core::int> g1c = #C3;
 static const field () → self::A<core::int> h1a = #C2;
 static const field () → self::A<core::int> h1b = #C2;
-static const field () → self::A<core::int> h1c = #C8;
+static const field () → self::A<core::int> h1c = #C3;
 static method main() → dynamic {
   self::test<core::int>();
   core::identical(#C2, #C2);
-  core::identical(#C2, #C4);
+  core::identical(#C2, #C3);
+  core::identical(#C5, #C5);
+  core::identical(#C5, #C6);
+  core::identical(#C8, #C8);
+  core::identical(#C8, #C9);
   core::identical(#C2, #C2);
-  core::identical(#C2, #C6);
+  core::identical(#C2, #C3);
   core::identical(#C2, #C2);
-  core::identical(#C2, #C8);
+  core::identical(#C2, #C3);
 }
 static method test<T extends core::num>() → dynamic {
   () → self::A<self::test::T> f2a = #C1<self::test::T>;
   () → self::A<self::test::T> f2b = #C1<self::test::T>;
-  () → self::A<self::test::T> f2c = #C3<self::test::T>;
+  () → self::A<self::test::T> f2c = #C1<self::test::T>;
+  () → self::A<self::test::T> f2d = #C4<self::test::T>;
+  () → self::A<self::test::T> f2e = #C4<self::test::T>;
+  () → self::A<self::test::T> f2f = #C4<self::test::T>;
+  () → self::A<self::test::T> f2g = #C7<self::test::T>;
+  () → self::A<self::test::T> f2h = #C7<self::test::T>;
+  () → self::A<self::test::T> f2i = #C7<self::test::T>;
   () → self::A<core::int> g2a = #C2;
   () → self::A<core::int> g2b = #C2;
-  () → self::A<core::int> g2c = #C6;
+  () → self::A<core::int> g2c = #C3;
   () → self::A<self::test::T> h2a = #C1<self::test::T>;
   () → self::A<self::test::T> h2b = #C1<self::test::T>;
-  () → self::A<self::test::T> h2c = #C7<self::test::T, dynamic>;
-  self::expect(#C2, f2a);
-  self::expect(f2a, f2b);
-  self::expect(f2a, f2c);
+  () → self::A<self::test::T> h2c = #C1<self::test::T>;
   self::expect(#C2, g2a);
   self::expect(g2a, g2b);
-  self::expect(g2a, g2c);
-  self::expect(#C2, h2a);
-  self::expect(h2a, h2b);
-  self::expect(h2a, h2c);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
@@ -56,18 +78,31 @@
 }
 static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
   return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+  return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+  return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
 static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
   return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::_#redirect#tearOff<core::int>();
 static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
   return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+  return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+  return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
 
 constants  {
   #C1 = static-tearoff self::A::_#new#tearOff
   #C2 = instantiation self::A::_#new#tearOff <core::int*>
-  #C3 = static-tearoff self::_#F#new#tearOff
-  #C4 = instantiation self::_#F#new#tearOff <core::int*>
-  #C5 = static-tearoff self::_#G#new#tearOff
-  #C6 = instantiation self::_#G#new#tearOff <dynamic>
-  #C7 = static-tearoff self::_#H#new#tearOff
-  #C8 = instantiation self::_#H#new#tearOff <core::int*, dynamic>
+  #C3 = instantiation self::A::_#new#tearOff <core::int>
+  #C4 = static-tearoff self::A::_#fact#tearOff
+  #C5 = instantiation self::A::_#fact#tearOff <core::int*>
+  #C6 = instantiation self::A::_#fact#tearOff <core::int>
+  #C7 = static-tearoff self::A::_#redirect#tearOff
+  #C8 = instantiation self::A::_#redirect#tearOff <core::int*>
+  #C9 = instantiation self::A::_#redirect#tearOff <core::int>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.outline.expect
index f0dde1a..e433d37 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.outline.expect
@@ -6,14 +6,30 @@
 typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
 typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
 class A<T extends core::Object? = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T%>
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
     ;
   static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
     return new self::A::•<self::A::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    ;
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+    return self::A::fact<self::A::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+    return new self::A::•<self::A::_#redirect#tearOff::T%>();
 }
+static final field core::bool inSoundMode;
 static const field () → self::A<core::int> f1a = self::A::_#new#tearOff<core::int>;
 static const field () → self::A<core::int> f1b = self::A::_#new#tearOff<core::int>;
 static const field () → self::A<core::int> f1c = self::_#F#new#tearOff<core::int>;
+static const field () → self::A<core::int> f1d = self::A::_#fact#tearOff<core::int>;
+static const field () → self::A<core::int> f1e = self::A::_#fact#tearOff<core::int>;
+static const field () → self::A<core::int> f1f = self::_#F#fact#tearOff<core::int>;
+static const field () → self::A<core::int> f1g = self::A::_#redirect#tearOff<core::int>;
+static const field () → self::A<core::int> f1h = self::A::_#redirect#tearOff<core::int>;
+static const field () → self::A<core::int> f1i = self::_#F#redirect#tearOff<core::int>;
 static const field () → self::A<core::int> g1a = self::A::_#new#tearOff<core::int>;
 static const field () → self::A<core::int> g1b = self::A::_#new#tearOff<core::int>;
 static const field () → self::A<core::int> g1c = self::_#G#new#tearOff<dynamic>;
@@ -28,20 +44,38 @@
   ;
 static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
   return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+  return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+  return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
 static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
   return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::_#redirect#tearOff<core::int>();
 static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
   return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+  return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+  return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
 
 
 Extra constant evaluation status:
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:11:13 -> InstantiationConstant(A._#new#tearOff<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:12:13 -> InstantiationConstant(A._#new#tearOff<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:13:31 -> InstantiationConstant(_#F#new#tearOff<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:15:13 -> InstantiationConstant(A._#new#tearOff<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:16:13 -> InstantiationConstant(A._#new#tearOff<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:17:31 -> InstantiationConstant(_#G#new#tearOff<dynamic>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:19:13 -> InstantiationConstant(A._#new#tearOff<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:20:13 -> InstantiationConstant(A._#new#tearOff<int*>)
-Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:21:31 -> InstantiationConstant(_#H#new#tearOff<int*, dynamic>)
-Extra constant evaluation: evaluated: 13, effectively constant: 9
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:17:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:18:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:19:31 -> InstantiationConstant(A._#new#tearOff<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:20:13 -> InstantiationConstant(A._#fact#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:21:13 -> InstantiationConstant(A._#fact#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:22:31 -> InstantiationConstant(A._#fact#tearOff<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:23:13 -> InstantiationConstant(A._#redirect#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:24:13 -> InstantiationConstant(A._#redirect#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:25:31 -> InstantiationConstant(A._#redirect#tearOff<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:27:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:28:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:29:31 -> InstantiationConstant(A._#new#tearOff<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:31:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:32:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:33:31 -> InstantiationConstant(A._#new#tearOff<int>)
+Extra constant evaluation: evaluated: 32, effectively constant: 15
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.transformed.expect
index ee7cfa6..0b3ac45 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.transformed.expect
@@ -6,49 +6,71 @@
 typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
 typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
 class A<T extends core::Object? = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T%>
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
     : super core::Object::•()
     ;
   static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
     return new self::A::•<self::A::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+    return self::A::fact<self::A::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let Never #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+    return new self::A::•<self::A::_#redirect#tearOff::T%>();
 }
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
 static const field () → self::A<core::int> f1a = #C2;
 static const field () → self::A<core::int> f1b = #C2;
-static const field () → self::A<core::int> f1c = #C4;
+static const field () → self::A<core::int> f1c = #C3;
+static const field () → self::A<core::int> f1d = #C5;
+static const field () → self::A<core::int> f1e = #C5;
+static const field () → self::A<core::int> f1f = #C6;
+static const field () → self::A<core::int> f1g = #C8;
+static const field () → self::A<core::int> f1h = #C8;
+static const field () → self::A<core::int> f1i = #C9;
 static const field () → self::A<core::int> g1a = #C2;
 static const field () → self::A<core::int> g1b = #C2;
-static const field () → self::A<core::int> g1c = #C6;
+static const field () → self::A<core::int> g1c = #C3;
 static const field () → self::A<core::int> h1a = #C2;
 static const field () → self::A<core::int> h1b = #C2;
-static const field () → self::A<core::int> h1c = #C8;
+static const field () → self::A<core::int> h1c = #C3;
 static method main() → dynamic {
   self::test<core::int>();
   core::identical(#C2, #C2);
-  core::identical(#C2, #C4);
+  core::identical(#C2, #C3);
+  core::identical(#C5, #C5);
+  core::identical(#C5, #C6);
+  core::identical(#C8, #C8);
+  core::identical(#C8, #C9);
   core::identical(#C2, #C2);
-  core::identical(#C2, #C6);
+  core::identical(#C2, #C3);
   core::identical(#C2, #C2);
-  core::identical(#C2, #C8);
+  core::identical(#C2, #C3);
 }
 static method test<T extends core::num>() → dynamic {
   () → self::A<self::test::T> f2a = #C1<self::test::T>;
   () → self::A<self::test::T> f2b = #C1<self::test::T>;
-  () → self::A<self::test::T> f2c = #C3<self::test::T>;
+  () → self::A<self::test::T> f2c = #C1<self::test::T>;
+  () → self::A<self::test::T> f2d = #C4<self::test::T>;
+  () → self::A<self::test::T> f2e = #C4<self::test::T>;
+  () → self::A<self::test::T> f2f = #C4<self::test::T>;
+  () → self::A<self::test::T> f2g = #C7<self::test::T>;
+  () → self::A<self::test::T> f2h = #C7<self::test::T>;
+  () → self::A<self::test::T> f2i = #C7<self::test::T>;
   () → self::A<core::int> g2a = #C2;
   () → self::A<core::int> g2b = #C2;
-  () → self::A<core::int> g2c = #C6;
+  () → self::A<core::int> g2c = #C3;
   () → self::A<self::test::T> h2a = #C1<self::test::T>;
   () → self::A<self::test::T> h2b = #C1<self::test::T>;
-  () → self::A<self::test::T> h2c = #C7<self::test::T, dynamic>;
-  self::expect(#C2, f2a);
-  self::expect(f2a, f2b);
-  self::expect(f2a, f2c);
+  () → self::A<self::test::T> h2c = #C1<self::test::T>;
   self::expect(#C2, g2a);
   self::expect(g2a, g2b);
-  self::expect(g2a, g2c);
-  self::expect(#C2, h2a);
-  self::expect(h2a, h2b);
-  self::expect(h2a, h2c);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
@@ -56,27 +78,44 @@
 }
 static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
   return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+  return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+  return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
 static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
   return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::_#redirect#tearOff<core::int>();
 static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
   return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+  return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+  return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
 
 constants  {
   #C1 = static-tearoff self::A::_#new#tearOff
   #C2 = instantiation self::A::_#new#tearOff <core::int*>
-  #C3 = static-tearoff self::_#F#new#tearOff
-  #C4 = instantiation self::_#F#new#tearOff <core::int*>
-  #C5 = static-tearoff self::_#G#new#tearOff
-  #C6 = instantiation self::_#G#new#tearOff <dynamic>
-  #C7 = static-tearoff self::_#H#new#tearOff
-  #C8 = instantiation self::_#H#new#tearOff <core::int*, dynamic>
+  #C3 = instantiation self::A::_#new#tearOff <core::int>
+  #C4 = static-tearoff self::A::_#fact#tearOff
+  #C5 = instantiation self::A::_#fact#tearOff <core::int*>
+  #C6 = instantiation self::A::_#fact#tearOff <core::int>
+  #C7 = static-tearoff self::A::_#redirect#tearOff
+  #C8 = instantiation self::A::_#redirect#tearOff <core::int*>
+  #C9 = instantiation self::A::_#redirect#tearOff <core::int>
 }
 
 Extra constant evaluation status:
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:26:3 -> BoolConstant(true)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:27:3 -> BoolConstant(false)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:29:3 -> BoolConstant(true)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:30:3 -> BoolConstant(false)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:32:3 -> BoolConstant(true)
-Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:33:3 -> BoolConstant(false)
-Extra constant evaluation: evaluated: 49, effectively constant: 6
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:38:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:39:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:41:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:42:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:44:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:45:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:47:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:48:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:50:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:51:3 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 61, effectively constant: 10
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index e12207e..face729 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -11,7 +11,6 @@
 constructor_tearoffs/const_tear_off: RuntimeError
 constructor_tearoffs/inferred_constructor_tear_off: RuntimeError
 constructor_tearoffs/inferred_non_proper_rename: RuntimeError
-constructor_tearoffs/lowering/inferred_non_proper_rename: RuntimeError
 constructor_tearoffs/redirecting_constructors: RuntimeError
 constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 7b53eef..f52deaa 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -9,7 +9,6 @@
 constructor_tearoffs/const_tear_off: RuntimeError
 constructor_tearoffs/inferred_constructor_tear_off: RuntimeError
 constructor_tearoffs/inferred_non_proper_rename: RuntimeError
-constructor_tearoffs/lowering/inferred_non_proper_rename: RuntimeError
 constructor_tearoffs/redirecting_constructors: RuntimeError
 constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 0dfa849..d45056d 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -14,7 +14,6 @@
 constructor_tearoffs/const_tear_off: RuntimeError
 constructor_tearoffs/inferred_constructor_tear_off: RuntimeError
 constructor_tearoffs/inferred_non_proper_rename: RuntimeError
-constructor_tearoffs/lowering/inferred_non_proper_rename: RuntimeError
 constructor_tearoffs/redirecting_constructors: RuntimeError
 constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
diff --git a/tools/VERSION b/tools/VERSION
index 7b703bc..ea36d5e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 364
+PRERELEASE 365
 PRERELEASE_PATCH 0
\ No newline at end of file