[dart2js] Enable kernel verification

This enables kernel verification of components loaded from source when
asserts are enabled.

Change-Id: Icf5d42e2c978428138733403f9af35824e97821c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/299641
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/_js_interop_checks/lib/src/transformations/export_creator.dart b/pkg/_js_interop_checks/lib/src/transformations/export_creator.dart
index 5473990..a6f8d6c 100644
--- a/pkg/_js_interop_checks/lib/src/transformations/export_creator.dart
+++ b/pkg/_js_interop_checks/lib/src/transformations/export_creator.dart
@@ -192,7 +192,8 @@
     }
 
     var jsExporter = VariableDeclaration('#jsExporter',
-        initializer: AsExpression(getLiteral(proto), returnType),
+        initializer: AsExpression(getLiteral(proto), returnType)
+          ..fileOffset = node.fileOffset,
         type: returnType,
         isSynthesized: true)
       ..fileOffset = node.fileOffset
diff --git a/pkg/compiler/lib/src/phase/load_kernel.dart b/pkg/compiler/lib/src/phase/load_kernel.dart
index b446993..af36d04 100644
--- a/pkg/compiler/lib/src/phase/load_kernel.dart
+++ b/pkg/compiler/lib/src/phase/load_kernel.dart
@@ -15,6 +15,7 @@
 import 'package:kernel/target/targets.dart' hide DiagnosticReporter;
 
 import 'package:_js_interop_checks/src/transformations/static_interop_class_eraser.dart';
+import 'package:kernel/verifier.dart';
 
 import '../../compiler_api.dart' as api;
 import '../commandline_options.dart';
@@ -302,6 +303,18 @@
       verbosity: verbosity);
   ir.Component? component = await fe.compile(initializedCompilerState, verbose,
       fileSystem, onDiagnostic, sources, isModularCompile);
+
+  assert(() {
+    if (component != null) {
+      // TODO(johnniwinther): Support verification of erroneous programs.
+      if (!reporter.hasReportedError) {
+        verifyComponent(
+            target, VerificationStage.afterModularTransformations, component);
+      }
+    }
+    return true;
+  }());
+
   _doTransformsOnKernelLoad(component);
 
   // We have to compute canonical names on the component here to avoid missing
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 18f74ec..4cd2eae 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -4554,7 +4554,7 @@
           node,
           new StaticInvocation(
               target, unevaluatedArguments(positional, named, arguments.types),
-              isConst: true));
+              isConst: node.isConst));
     }
     if (target.kind == ProcedureKind.Factory) {
       if (target.isConst) {
@@ -4581,7 +4581,7 @@
                 node,
                 new StaticInvocation(target,
                     unevaluatedArguments(positional, named, arguments.types),
-                    isConst: true));
+                    isConst: node.isConst));
           }
         } else if (target.isExternal) {
           return createEvaluationErrorConstant(
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 2162752..93d38a7 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
@@ -264,6 +264,10 @@
           if (target is Procedure && target.isRedirectingFactory) {
             target = builder.readTarget!;
           }
+          Class targetClass = target.enclosingClass!;
+          if (target is Constructor && targetClass.isAbstract) {
+            continue;
+          }
           Name targetName =
               new Name(constructorName, declaration.libraryBuilder.library);
           Reference? tearOffReference;
diff --git a/pkg/front_end/testcases/dart2js/abstract_tear_off.dart b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart
new file mode 100644
index 0000000..e7b8cf9
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2023, 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.
+
+abstract class Class {
+  Class();
+  factory Class.redirect() = ClassImpl;
+}
+
+class ClassImpl implements Class {}
+
+typedef F<T> = Class;
+
+test() {
+  Class.new; // Error
+  Class.redirect; // Ok
+  F.new; // Error
+  F.redirect; // Ok
+}
diff --git a/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.strong.expect b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.strong.expect
new file mode 100644
index 0000000..1c37d16
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.strong.expect
@@ -0,0 +1,51 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+//   Class.new; // Error
+//         ^^^
+//
+// pkg/front_end/testcases/dart2js/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+//   F.new; // Error
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::Class;
+abstract class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static factory redirect() → self::Class
+    return new self::ClassImpl::•();
+  static method _#redirect#tearOff() → self::Class
+    return new self::ClassImpl::•();
+}
+class ClassImpl extends core::Object implements self::Class {
+  synthetic constructor •() → self::ClassImpl
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::ClassImpl
+    return new self::ClassImpl::•();
+}
+static method test() → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+  Class.new; // Error
+        ^^^";
+  #C2;
+  invalid-expression "pkg/front_end/testcases/dart2js/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+  F.new; // Error
+    ^^^";
+  #C3;
+}
+static method _#F#redirect#tearOff<unrelated T extends core::Object? = dynamic>() → self::Class
+  return self::Class::_#redirect#tearOff();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = static-tearoff self::Class::_#redirect#tearOff
+  #C3 = static-tearoff self::_#F#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..1c37d16
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,51 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+//   Class.new; // Error
+//         ^^^
+//
+// pkg/front_end/testcases/dart2js/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+//   F.new; // Error
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::Class;
+abstract class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static factory redirect() → self::Class
+    return new self::ClassImpl::•();
+  static method _#redirect#tearOff() → self::Class
+    return new self::ClassImpl::•();
+}
+class ClassImpl extends core::Object implements self::Class {
+  synthetic constructor •() → self::ClassImpl
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::ClassImpl
+    return new self::ClassImpl::•();
+}
+static method test() → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+  Class.new; // Error
+        ^^^";
+  #C2;
+  invalid-expression "pkg/front_end/testcases/dart2js/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+  F.new; // Error
+    ^^^";
+  #C3;
+}
+static method _#F#redirect#tearOff<unrelated T extends core::Object? = dynamic>() → self::Class
+  return self::Class::_#redirect#tearOff();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = static-tearoff self::Class::_#redirect#tearOff
+  #C3 = static-tearoff self::_#F#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..b8a9891
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+abstract class Class {
+  Class();
+  factory Class.redirect() = ClassImpl;
+}
+
+class ClassImpl implements Class {}
+
+typedef F<T> = Class;
+test() {}
diff --git a/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b97f8ca
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+abstract class Class {
+  Class();
+  factory Class.redirect() = ClassImpl;
+}
+
+class ClassImpl implements Class {}
+
+test() {}
+typedef F<T> = Class;
diff --git a/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.weak.expect b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.weak.expect
new file mode 100644
index 0000000..1c37d16
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.weak.expect
@@ -0,0 +1,51 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+//   Class.new; // Error
+//         ^^^
+//
+// pkg/front_end/testcases/dart2js/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+//   F.new; // Error
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::Class;
+abstract class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static factory redirect() → self::Class
+    return new self::ClassImpl::•();
+  static method _#redirect#tearOff() → self::Class
+    return new self::ClassImpl::•();
+}
+class ClassImpl extends core::Object implements self::Class {
+  synthetic constructor •() → self::ClassImpl
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::ClassImpl
+    return new self::ClassImpl::•();
+}
+static method test() → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+  Class.new; // Error
+        ^^^";
+  #C2;
+  invalid-expression "pkg/front_end/testcases/dart2js/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+  F.new; // Error
+    ^^^";
+  #C3;
+}
+static method _#F#redirect#tearOff<unrelated T extends core::Object? = dynamic>() → self::Class
+  return self::Class::_#redirect#tearOff();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = static-tearoff self::Class::_#redirect#tearOff
+  #C3 = static-tearoff self::_#F#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.weak.modular.expect
new file mode 100644
index 0000000..1c37d16
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.weak.modular.expect
@@ -0,0 +1,51 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+//   Class.new; // Error
+//         ^^^
+//
+// pkg/front_end/testcases/dart2js/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+//   F.new; // Error
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::Class;
+abstract class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static factory redirect() → self::Class
+    return new self::ClassImpl::•();
+  static method _#redirect#tearOff() → self::Class
+    return new self::ClassImpl::•();
+}
+class ClassImpl extends core::Object implements self::Class {
+  synthetic constructor •() → self::ClassImpl
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::ClassImpl
+    return new self::ClassImpl::•();
+}
+static method test() → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+  Class.new; // Error
+        ^^^";
+  #C2;
+  invalid-expression "pkg/front_end/testcases/dart2js/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+  F.new; // Error
+    ^^^";
+  #C3;
+}
+static method _#F#redirect#tearOff<unrelated T extends core::Object? = dynamic>() → self::Class
+  return self::Class::_#redirect#tearOff();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = static-tearoff self::Class::_#redirect#tearOff
+  #C3 = static-tearoff self::_#F#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..ed3a00a
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.weak.outline.expect
@@ -0,0 +1,29 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::Class;
+abstract class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class::redirect]/*isLegacy*/;
+  constructor •() → self::Class
+    ;
+  static factory redirect() → self::Class
+    return new self::ClassImpl::•();
+  static method _#redirect#tearOff() → self::Class
+    return new self::ClassImpl::•();
+}
+class ClassImpl extends core::Object implements self::Class {
+  synthetic constructor •() → self::ClassImpl
+    ;
+  static method _#new#tearOff() → self::ClassImpl
+    return new self::ClassImpl::•();
+}
+static method test() → dynamic
+  ;
+static method _#F#redirect#tearOff<unrelated T extends core::Object? = dynamic>() → self::Class
+  return self::Class::_#redirect#tearOff();
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///abstract_tear_off.dart:5:16 -> ConstructorTearOffConstant(Class.redirect)
+Extra constant evaluation: evaluated: 6, effectively constant: 1
diff --git a/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..1c37d16
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/abstract_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,51 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+//   Class.new; // Error
+//         ^^^
+//
+// pkg/front_end/testcases/dart2js/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+//   F.new; // Error
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::Class;
+abstract class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static factory redirect() → self::Class
+    return new self::ClassImpl::•();
+  static method _#redirect#tearOff() → self::Class
+    return new self::ClassImpl::•();
+}
+class ClassImpl extends core::Object implements self::Class {
+  synthetic constructor •() → self::ClassImpl
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::ClassImpl
+    return new self::ClassImpl::•();
+}
+static method test() → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+  Class.new; // Error
+        ^^^";
+  #C2;
+  invalid-expression "pkg/front_end/testcases/dart2js/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+  F.new; // Error
+    ^^^";
+  #C3;
+}
+static method _#F#redirect#tearOff<unrelated T extends core::Object? = dynamic>() → self::Class
+  return self::Class::_#redirect#tearOff();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = static-tearoff self::Class::_#redirect#tearOff
+  #C3 = static-tearoff self::_#F#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/general/abstract_tear_off.dart b/pkg/front_end/testcases/general/abstract_tear_off.dart
new file mode 100644
index 0000000..e7b8cf9
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_tear_off.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2023, 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.
+
+abstract class Class {
+  Class();
+  factory Class.redirect() = ClassImpl;
+}
+
+class ClassImpl implements Class {}
+
+typedef F<T> = Class;
+
+test() {
+  Class.new; // Error
+  Class.redirect; // Ok
+  F.new; // Error
+  F.redirect; // Ok
+}
diff --git a/pkg/front_end/testcases/general/abstract_tear_off.dart.strong.expect b/pkg/front_end/testcases/general/abstract_tear_off.dart.strong.expect
new file mode 100644
index 0000000..6d6be75cf
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_tear_off.dart.strong.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+//   Class.new; // Error
+//         ^^^
+//
+// pkg/front_end/testcases/general/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+//   F.new; // Error
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::Class;
+abstract class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static factory redirect() → self::Class
+    return new self::ClassImpl::•();
+}
+class ClassImpl extends core::Object implements self::Class {
+  synthetic constructor •() → self::ClassImpl
+    : super core::Object::•()
+    ;
+}
+static method test() → dynamic {
+  invalid-expression "pkg/front_end/testcases/general/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+  Class.new; // Error
+        ^^^";
+  #C2;
+  invalid-expression "pkg/front_end/testcases/general/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+  F.new; // Error
+    ^^^";
+  #C3;
+}
+static method _#F#redirect#tearOff<unrelated T extends core::Object? = dynamic>() → self::Class
+  return self::Class::redirect();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = redirecting-factory-tearoff self::Class::redirect
+  #C3 = static-tearoff self::_#F#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/general/abstract_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/general/abstract_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..6d6be75cf
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+//   Class.new; // Error
+//         ^^^
+//
+// pkg/front_end/testcases/general/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+//   F.new; // Error
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::Class;
+abstract class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static factory redirect() → self::Class
+    return new self::ClassImpl::•();
+}
+class ClassImpl extends core::Object implements self::Class {
+  synthetic constructor •() → self::ClassImpl
+    : super core::Object::•()
+    ;
+}
+static method test() → dynamic {
+  invalid-expression "pkg/front_end/testcases/general/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+  Class.new; // Error
+        ^^^";
+  #C2;
+  invalid-expression "pkg/front_end/testcases/general/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+  F.new; // Error
+    ^^^";
+  #C3;
+}
+static method _#F#redirect#tearOff<unrelated T extends core::Object? = dynamic>() → self::Class
+  return self::Class::redirect();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = redirecting-factory-tearoff self::Class::redirect
+  #C3 = static-tearoff self::_#F#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/general/abstract_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/general/abstract_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..b8a9891
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_tear_off.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+abstract class Class {
+  Class();
+  factory Class.redirect() = ClassImpl;
+}
+
+class ClassImpl implements Class {}
+
+typedef F<T> = Class;
+test() {}
diff --git a/pkg/front_end/testcases/general/abstract_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/abstract_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b97f8ca
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+abstract class Class {
+  Class();
+  factory Class.redirect() = ClassImpl;
+}
+
+class ClassImpl implements Class {}
+
+test() {}
+typedef F<T> = Class;
diff --git a/pkg/front_end/testcases/general/abstract_tear_off.dart.weak.expect b/pkg/front_end/testcases/general/abstract_tear_off.dart.weak.expect
new file mode 100644
index 0000000..6d6be75cf
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_tear_off.dart.weak.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+//   Class.new; // Error
+//         ^^^
+//
+// pkg/front_end/testcases/general/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+//   F.new; // Error
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::Class;
+abstract class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static factory redirect() → self::Class
+    return new self::ClassImpl::•();
+}
+class ClassImpl extends core::Object implements self::Class {
+  synthetic constructor •() → self::ClassImpl
+    : super core::Object::•()
+    ;
+}
+static method test() → dynamic {
+  invalid-expression "pkg/front_end/testcases/general/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+  Class.new; // Error
+        ^^^";
+  #C2;
+  invalid-expression "pkg/front_end/testcases/general/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+  F.new; // Error
+    ^^^";
+  #C3;
+}
+static method _#F#redirect#tearOff<unrelated T extends core::Object? = dynamic>() → self::Class
+  return self::Class::redirect();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = redirecting-factory-tearoff self::Class::redirect
+  #C3 = static-tearoff self::_#F#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/general/abstract_tear_off.dart.weak.modular.expect b/pkg/front_end/testcases/general/abstract_tear_off.dart.weak.modular.expect
new file mode 100644
index 0000000..6d6be75cf
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_tear_off.dart.weak.modular.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+//   Class.new; // Error
+//         ^^^
+//
+// pkg/front_end/testcases/general/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+//   F.new; // Error
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::Class;
+abstract class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static factory redirect() → self::Class
+    return new self::ClassImpl::•();
+}
+class ClassImpl extends core::Object implements self::Class {
+  synthetic constructor •() → self::ClassImpl
+    : super core::Object::•()
+    ;
+}
+static method test() → dynamic {
+  invalid-expression "pkg/front_end/testcases/general/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+  Class.new; // Error
+        ^^^";
+  #C2;
+  invalid-expression "pkg/front_end/testcases/general/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+  F.new; // Error
+    ^^^";
+  #C3;
+}
+static method _#F#redirect#tearOff<unrelated T extends core::Object? = dynamic>() → self::Class
+  return self::Class::redirect();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = redirecting-factory-tearoff self::Class::redirect
+  #C3 = static-tearoff self::_#F#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/general/abstract_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/general/abstract_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..d0e48de
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_tear_off.dart.weak.outline.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::Class;
+abstract class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class::redirect]/*isLegacy*/;
+  constructor •() → self::Class
+    ;
+  static factory redirect() → self::Class
+    return new self::ClassImpl::•();
+}
+class ClassImpl extends core::Object implements self::Class {
+  synthetic constructor •() → self::ClassImpl
+    ;
+}
+static method test() → dynamic
+  ;
+static method _#F#redirect#tearOff<unrelated T extends core::Object? = dynamic>() → self::Class
+  return self::Class::redirect();
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///abstract_tear_off.dart:5:16 -> ConstructorTearOffConstant(Class.redirect)
+Extra constant evaluation: evaluated: 4, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/abstract_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/general/abstract_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..6d6be75cf
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+//   Class.new; // Error
+//         ^^^
+//
+// pkg/front_end/testcases/general/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+//   F.new; // Error
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::Class;
+abstract class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static factory redirect() → self::Class
+    return new self::ClassImpl::•();
+}
+class ClassImpl extends core::Object implements self::Class {
+  synthetic constructor •() → self::ClassImpl
+    : super core::Object::•()
+    ;
+}
+static method test() → dynamic {
+  invalid-expression "pkg/front_end/testcases/general/abstract_tear_off.dart:15:9: Error: Constructors on abstract classes can't be torn off.
+  Class.new; // Error
+        ^^^";
+  #C2;
+  invalid-expression "pkg/front_end/testcases/general/abstract_tear_off.dart:17:5: Error: Constructors on abstract classes can't be torn off.
+  F.new; // Error
+    ^^^";
+  #C3;
+}
+static method _#F#redirect#tearOff<unrelated T extends core::Object? = dynamic>() → self::Class
+  return self::Class::redirect();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = redirecting-factory-tearoff self::Class::redirect
+  #C3 = static-tearoff self::_#F#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.expect
index 4d039bc..d12b0e4 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.expect
@@ -126,7 +126,7 @@
   #C22 = static-tearoff var::id2
   #C23 = eval #C22<core::int>
   #C24 = eval #C20 ?{(core::int) → core::int} #C21 : #C23
-  #C25 = eval const core::identical(#C3, #C24)
+  #C25 = eval core::identical(#C3, #C24)
   #C26 = static-tearoff core::identical
 }
 
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.transformed.expect
index 44b37ee..28dd954 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.transformed.expect
@@ -126,7 +126,7 @@
   #C22 = static-tearoff var::id2
   #C23 = eval #C22<core::int>
   #C24 = eval #C20 ?{(core::int) → core::int} #C21 : #C23
-  #C25 = eval const core::identical(#C3, #C24)
+  #C25 = eval core::identical(#C3, #C24)
   #C26 = static-tearoff core::identical
 }
 
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.expect
index 243b858..e9db17c 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.expect
@@ -126,7 +126,7 @@
   #C22 = static-tearoff var::id2
   #C23 = eval #C22<core::int>
   #C24 = eval #C20 ?{(core::int) → core::int} #C21 : #C23
-  #C25 = eval const core::identical(#C3, #C24)
+  #C25 = eval core::identical(#C3, #C24)
   #C26 = static-tearoff core::identical
 }
 
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.modular.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.modular.expect
index 243b858..e9db17c 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.modular.expect
@@ -126,7 +126,7 @@
   #C22 = static-tearoff var::id2
   #C23 = eval #C22<core::int>
   #C24 = eval #C20 ?{(core::int) → core::int} #C21 : #C23
-  #C25 = eval const core::identical(#C3, #C24)
+  #C25 = eval core::identical(#C3, #C24)
   #C26 = static-tearoff core::identical
 }
 
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.transformed.expect
index fd2b782..e40d672 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.transformed.expect
@@ -126,7 +126,7 @@
   #C22 = static-tearoff var::id2
   #C23 = eval #C22<core::int>
   #C24 = eval #C20 ?{(core::int) → core::int} #C21 : #C23
-  #C25 = eval const core::identical(#C3, #C24)
+  #C25 = eval core::identical(#C3, #C24)
   #C26 = static-tearoff core::identical
 }