[cfe] Add verification of tear-off lowering

This adds verification that tear-off nodes for which the target
requested a lowering, do not occur in the generated AST.

Change-Id: Ic5e58d1cc607778d6239ced2bf9509439ae1e92b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/223080
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index 7543cd9..ae560e2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
@@ -29,7 +29,10 @@
 import '../type_inference/type_schema.dart' show UnknownType;
 
 import 'redirecting_factory_body.dart'
-    show RedirectingFactoryBody, isRedirectingFactory;
+    show
+        RedirectingFactoryBody,
+        isRedirectingFactory,
+        isRedirectingFactoryField;
 
 List<LocatedMessage> verifyComponent(Component component, Target target,
     {bool? isOutline, bool? afterConst, bool skipPlatform: false}) {
@@ -431,6 +434,89 @@
     exitTreeNode(node);
   }
 
+  void _checkConstructorTearOff(Node node, Member tearOffTarget) {
+    if (tearOffTarget.enclosingLibrary.importUri.scheme == 'dart') {
+      // Platform libraries are not compilation with test flags and might
+      // contain tear-offs not expected when testing lowerings.
+      return;
+    }
+    if (currentMember != null && isRedirectingFactoryField(currentMember!)) {
+      // The encoding of the redirecting factory field uses
+      // [ConstructorTearOffConstant] nodes also when lowerings are enabled.
+      return;
+    }
+    if (tearOffTarget is Constructor &&
+        target.isConstructorTearOffLoweringEnabled) {
+      problem(
+          node is TreeNode ? node : getLastSeenTreeNode(),
+          '${node.runtimeType} nodes for generative constructors should be '
+          'lowered for target "${target.name}".');
+    }
+    if (tearOffTarget is Procedure &&
+        tearOffTarget.isFactory &&
+        target.isFactoryTearOffLoweringEnabled) {
+      problem(
+          node is TreeNode ? node : getLastSeenTreeNode(),
+          '${node.runtimeType} nodes for factory constructors should be '
+          'lowered for target "${target.name}".');
+    }
+  }
+
+  @override
+  void visitConstructorTearOff(ConstructorTearOff node) {
+    _checkConstructorTearOff(node, node.target);
+    super.visitConstructorTearOff(node);
+  }
+
+  @override
+  void visitConstructorTearOffConstant(ConstructorTearOffConstant node) {
+    _checkConstructorTearOff(node, node.target);
+    super.visitConstructorTearOffConstant(node);
+  }
+
+  void _checkTypedefTearOff(Node node) {
+    if (target.isTypedefTearOffLoweringEnabled) {
+      problem(
+          node is TreeNode ? node : getLastSeenTreeNode(),
+          '${node.runtimeType} nodes for typedefs should be '
+          'lowered for target "${target.name}".');
+    }
+  }
+
+  @override
+  void visitTypedefTearOff(TypedefTearOff node) {
+    _checkTypedefTearOff(node);
+    super.visitTypedefTearOff(node);
+  }
+
+  @override
+  void visitTypedefTearOffConstant(TypedefTearOffConstant node) {
+    _checkTypedefTearOff(node);
+    super.visitTypedefTearOffConstant(node);
+  }
+
+  void _checkRedirectingFactoryTearOff(Node node) {
+    if (target.isRedirectingFactoryTearOffLoweringEnabled) {
+      problem(
+          node is TreeNode ? node : getLastSeenTreeNode(),
+          'ConstructorTearOff nodes for redirecting factories should be '
+          'lowered for target "${target.name}".');
+    }
+  }
+
+  @override
+  void visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+    _checkRedirectingFactoryTearOff(node);
+    super.visitRedirectingFactoryTearOff(node);
+  }
+
+  @override
+  void visitRedirectingFactoryTearOffConstant(
+      RedirectingFactoryTearOffConstant node) {
+    _checkRedirectingFactoryTearOff(node);
+    super.visitRedirectingFactoryTearOffConstant(node);
+  }
+
   @override
   void defaultTreeNode(TreeNode node) {
     enterTreeNode(node);
diff --git a/pkg/front_end/testcases/dart2js/constructor_tearoff.dart b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart
new file mode 100644
index 0000000..b7234a7
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+typedef Alias<T extends num> = Class<T>;
+
+class Class<T> {
+  Class();
+  factory Class.fact() => Class<T>();
+  factory Class.redirect() = Class<T>;
+}
+
+const a = Class.new;
+const b = Class.fact;
+const c = Class.redirect;
+const d = Alias.new;
+const e = Alias.fact;
+const f = Alias.redirect;
+
+main() {
+  print('$a$b$c$d$e$f');
+}
diff --git a/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.strong.expect b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.strong.expect
new file mode 100644
index 0000000..46e4364
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.strong.expect
@@ -0,0 +1,46 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef Alias<T extends core::num> = self::Class<T>;
+class Class<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class<self::Class::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#new#tearOff::T%>
+    return new self::Class::•<self::Class::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::Class<self::Class::fact::T%>
+    return new self::Class::•<self::Class::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#fact#tearOff::T%>
+    return self::Class::fact<self::Class::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::Class<self::Class::redirect::T%>
+    return new self::Class::•<self::Class::redirect::T%>();
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#redirect#tearOff::T%>
+    return new self::Class::•<self::Class::_#redirect#tearOff::T%>();
+}
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> a = #C2;
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> b = #C3;
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> c = #C4;
+static const field <T extends core::num>() → self::Class<T> d = #C5;
+static const field <T extends core::num>() → self::Class<T> e = #C6;
+static const field <T extends core::num>() → self::Class<T> f = #C7;
+static method main() → dynamic {
+  core::print("${#C2}${#C3}${#C4}${#C5}${#C6}${#C7}");
+}
+static method _#Alias#new#tearOff<T extends core::num>() → self::Class<self::_#Alias#new#tearOff::T>
+  return new self::Class::•<self::_#Alias#new#tearOff::T>();
+static method _#Alias#fact#tearOff<T extends core::num>() → self::Class<self::_#Alias#fact#tearOff::T>
+  return self::Class::fact<self::_#Alias#fact#tearOff::T>();
+static method _#Alias#redirect#tearOff<T extends core::num>() → self::Class<self::_#Alias#redirect#tearOff::T>
+  return self::Class::_#redirect#tearOff<self::_#Alias#redirect#tearOff::T>();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = static-tearoff self::Class::_#new#tearOff
+  #C3 = static-tearoff self::Class::_#fact#tearOff
+  #C4 = static-tearoff self::Class::_#redirect#tearOff
+  #C5 = static-tearoff self::_#Alias#new#tearOff
+  #C6 = static-tearoff self::_#Alias#fact#tearOff
+  #C7 = static-tearoff self::_#Alias#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.strong.transformed.expect
new file mode 100644
index 0000000..46e4364
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.strong.transformed.expect
@@ -0,0 +1,46 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef Alias<T extends core::num> = self::Class<T>;
+class Class<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class<self::Class::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#new#tearOff::T%>
+    return new self::Class::•<self::Class::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::Class<self::Class::fact::T%>
+    return new self::Class::•<self::Class::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#fact#tearOff::T%>
+    return self::Class::fact<self::Class::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::Class<self::Class::redirect::T%>
+    return new self::Class::•<self::Class::redirect::T%>();
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#redirect#tearOff::T%>
+    return new self::Class::•<self::Class::_#redirect#tearOff::T%>();
+}
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> a = #C2;
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> b = #C3;
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> c = #C4;
+static const field <T extends core::num>() → self::Class<T> d = #C5;
+static const field <T extends core::num>() → self::Class<T> e = #C6;
+static const field <T extends core::num>() → self::Class<T> f = #C7;
+static method main() → dynamic {
+  core::print("${#C2}${#C3}${#C4}${#C5}${#C6}${#C7}");
+}
+static method _#Alias#new#tearOff<T extends core::num>() → self::Class<self::_#Alias#new#tearOff::T>
+  return new self::Class::•<self::_#Alias#new#tearOff::T>();
+static method _#Alias#fact#tearOff<T extends core::num>() → self::Class<self::_#Alias#fact#tearOff::T>
+  return self::Class::fact<self::_#Alias#fact#tearOff::T>();
+static method _#Alias#redirect#tearOff<T extends core::num>() → self::Class<self::_#Alias#redirect#tearOff::T>
+  return self::Class::_#redirect#tearOff<self::_#Alias#redirect#tearOff::T>();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = static-tearoff self::Class::_#new#tearOff
+  #C3 = static-tearoff self::Class::_#fact#tearOff
+  #C4 = static-tearoff self::Class::_#redirect#tearOff
+  #C5 = static-tearoff self::_#Alias#new#tearOff
+  #C6 = static-tearoff self::_#Alias#fact#tearOff
+  #C7 = static-tearoff self::_#Alias#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.textual_outline.expect
new file mode 100644
index 0000000..89d865d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.textual_outline.expect
@@ -0,0 +1,15 @@
+typedef Alias<T extends num> = Class<T>;
+
+class Class<T> {
+  Class();
+  factory Class.fact() => Class<T>();
+  factory Class.redirect() = Class<T>;
+}
+
+const a = Class.new;
+const b = Class.fact;
+const c = Class.redirect;
+const d = Alias.new;
+const e = Alias.fact;
+const f = Alias.redirect;
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3f714c9
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class Class<T> {
+  Class();
+  factory Class.fact() => Class<T>();
+  factory Class.redirect() = Class<T>;
+}
+
+const a = Class.new;
+const b = Class.fact;
+const c = Class.redirect;
+const d = Alias.new;
+const e = Alias.fact;
+const f = Alias.redirect;
+main() {}
+typedef Alias<T extends num> = Class<T>;
diff --git a/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.weak.expect b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.weak.expect
new file mode 100644
index 0000000..46e4364
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.weak.expect
@@ -0,0 +1,46 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef Alias<T extends core::num> = self::Class<T>;
+class Class<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class<self::Class::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#new#tearOff::T%>
+    return new self::Class::•<self::Class::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::Class<self::Class::fact::T%>
+    return new self::Class::•<self::Class::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#fact#tearOff::T%>
+    return self::Class::fact<self::Class::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::Class<self::Class::redirect::T%>
+    return new self::Class::•<self::Class::redirect::T%>();
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#redirect#tearOff::T%>
+    return new self::Class::•<self::Class::_#redirect#tearOff::T%>();
+}
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> a = #C2;
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> b = #C3;
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> c = #C4;
+static const field <T extends core::num>() → self::Class<T> d = #C5;
+static const field <T extends core::num>() → self::Class<T> e = #C6;
+static const field <T extends core::num>() → self::Class<T> f = #C7;
+static method main() → dynamic {
+  core::print("${#C2}${#C3}${#C4}${#C5}${#C6}${#C7}");
+}
+static method _#Alias#new#tearOff<T extends core::num>() → self::Class<self::_#Alias#new#tearOff::T>
+  return new self::Class::•<self::_#Alias#new#tearOff::T>();
+static method _#Alias#fact#tearOff<T extends core::num>() → self::Class<self::_#Alias#fact#tearOff::T>
+  return self::Class::fact<self::_#Alias#fact#tearOff::T>();
+static method _#Alias#redirect#tearOff<T extends core::num>() → self::Class<self::_#Alias#redirect#tearOff::T>
+  return self::Class::_#redirect#tearOff<self::_#Alias#redirect#tearOff::T>();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = static-tearoff self::Class::_#new#tearOff
+  #C3 = static-tearoff self::Class::_#fact#tearOff
+  #C4 = static-tearoff self::Class::_#redirect#tearOff
+  #C5 = static-tearoff self::_#Alias#new#tearOff
+  #C6 = static-tearoff self::_#Alias#fact#tearOff
+  #C7 = static-tearoff self::_#Alias#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.weak.outline.expect
new file mode 100644
index 0000000..48c9e36
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.weak.outline.expect
@@ -0,0 +1,45 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef Alias<T extends core::num> = self::Class<T>;
+class Class<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class::redirect]/*isLegacy*/;
+  constructor •() → self::Class<self::Class::T%>
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#new#tearOff::T%>
+    return new self::Class::•<self::Class::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::Class<self::Class::fact::T%>
+    ;
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#fact#tearOff::T%>
+    return self::Class::fact<self::Class::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::Class<self::Class::redirect::T%>
+    return new self::Class::•<self::Class::redirect::T%>();
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#redirect#tearOff::T%>
+    return new self::Class::•<self::Class::_#redirect#tearOff::T%>();
+}
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> a = self::Class::_#new#tearOff;
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> b = self::Class::_#fact#tearOff;
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> c = self::Class::_#redirect#tearOff;
+static const field <T extends core::num>() → self::Class<T> d = self::_#Alias#new#tearOff;
+static const field <T extends core::num>() → self::Class<T> e = self::_#Alias#fact#tearOff;
+static const field <T extends core::num>() → self::Class<T> f = self::_#Alias#redirect#tearOff;
+static method main() → dynamic
+  ;
+static method _#Alias#new#tearOff<T extends core::num>() → self::Class<self::_#Alias#new#tearOff::T>
+  return new self::Class::•<self::_#Alias#new#tearOff::T>();
+static method _#Alias#fact#tearOff<T extends core::num>() → self::Class<self::_#Alias#fact#tearOff::T>
+  return self::Class::fact<self::_#Alias#fact#tearOff::T>();
+static method _#Alias#redirect#tearOff<T extends core::num>() → self::Class<self::_#Alias#redirect#tearOff::T>
+  return self::Class::_#redirect#tearOff<self::_#Alias#redirect#tearOff::T>();
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///constructor_tearoff.dart:7:7 -> ConstructorTearOffConstant(Class.redirect)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///constructor_tearoff.dart:13:11 -> StaticTearOffConstant(Class._#new#tearOff)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///constructor_tearoff.dart:14:11 -> StaticTearOffConstant(Class._#fact#tearOff)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///constructor_tearoff.dart:15:11 -> StaticTearOffConstant(Class._#redirect#tearOff)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///constructor_tearoff.dart:16:11 -> StaticTearOffConstant(_#Alias#new#tearOff)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///constructor_tearoff.dart:17:11 -> StaticTearOffConstant(_#Alias#fact#tearOff)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///constructor_tearoff.dart:18:11 -> StaticTearOffConstant(_#Alias#redirect#tearOff)
+Extra constant evaluation: evaluated: 15, effectively constant: 7
diff --git a/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.weak.transformed.expect
new file mode 100644
index 0000000..46e4364
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/constructor_tearoff.dart.weak.transformed.expect
@@ -0,0 +1,46 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef Alias<T extends core::num> = self::Class<T>;
+class Class<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •() → self::Class<self::Class::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#new#tearOff::T%>
+    return new self::Class::•<self::Class::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::Class<self::Class::fact::T%>
+    return new self::Class::•<self::Class::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#fact#tearOff::T%>
+    return self::Class::fact<self::Class::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::Class<self::Class::redirect::T%>
+    return new self::Class::•<self::Class::redirect::T%>();
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::Class<self::Class::_#redirect#tearOff::T%>
+    return new self::Class::•<self::Class::_#redirect#tearOff::T%>();
+}
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> a = #C2;
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> b = #C3;
+static const field <T extends core::Object? = dynamic>() → self::Class<T%> c = #C4;
+static const field <T extends core::num>() → self::Class<T> d = #C5;
+static const field <T extends core::num>() → self::Class<T> e = #C6;
+static const field <T extends core::num>() → self::Class<T> f = #C7;
+static method main() → dynamic {
+  core::print("${#C2}${#C3}${#C4}${#C5}${#C6}${#C7}");
+}
+static method _#Alias#new#tearOff<T extends core::num>() → self::Class<self::_#Alias#new#tearOff::T>
+  return new self::Class::•<self::_#Alias#new#tearOff::T>();
+static method _#Alias#fact#tearOff<T extends core::num>() → self::Class<self::_#Alias#fact#tearOff::T>
+  return self::Class::fact<self::_#Alias#fact#tearOff::T>();
+static method _#Alias#redirect#tearOff<T extends core::num>() → self::Class<self::_#Alias#redirect#tearOff::T>
+  return self::Class::_#redirect#tearOff<self::_#Alias#redirect#tearOff::T>();
+
+constants  {
+  #C1 = constructor-tearoff self::Class::redirect
+  #C2 = static-tearoff self::Class::_#new#tearOff
+  #C3 = static-tearoff self::Class::_#fact#tearOff
+  #C4 = static-tearoff self::Class::_#redirect#tearOff
+  #C5 = static-tearoff self::_#Alias#new#tearOff
+  #C6 = static-tearoff self::_#Alias#fact#tearOff
+  #C7 = static-tearoff self::_#Alias#redirect#tearOff
+}