[cfe] Add flag for lowering redirecting factories

+ handle constructor tear offs in part files

Change-Id: Id3100ebbabb1c125b18c52cca7cb06871ed0f726
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/206621
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
index 890c76c..505f29b 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -138,7 +138,7 @@
           ..fileEndOffset = charEndOffset
           ..isNonNullableByDefault = compilationUnit.isNonNullableByDefault,
         _constructorTearOff = createConstructorTearOffProcedure(
-            name, compilationUnit, charOffset,
+            name, compilationUnit, compilationUnit.fileUri, charOffset,
             forAbstractClassOrEnum: forAbstractClassOrEnum),
         super(metadata, modifiers, returnType, name, typeVariables, formals,
             compilationUnit, charOffset, nativeMethodName);
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 33aa5d1..64c8403 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
@@ -20,15 +20,15 @@
 /// the given [name] in [compilationUnit].
 ///
 /// If constructor tear off lowering is not enabled, `null` is returned.
-Procedure? createConstructorTearOffProcedure(
-    String name, SourceLibraryBuilder compilationUnit, int fileOffset,
+Procedure? createConstructorTearOffProcedure(String name,
+    SourceLibraryBuilder compilationUnit, Uri fileUri, int fileOffset,
     {required bool forAbstractClassOrEnum}) {
   if (!forAbstractClassOrEnum &&
       compilationUnit
           .loader.target.backendTarget.isConstructorTearOffLoweringEnabled) {
     return new Procedure(constructorTearOffName(name, compilationUnit.library),
         ProcedureKind.Method, new FunctionNode(null),
-        fileUri: compilationUnit.fileUri, isStatic: true)
+        fileUri: fileUri, isStatic: true)
       ..startFileOffset = fileOffset
       ..fileOffset = fileOffset
       ..fileEndOffset = fileOffset
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 2531ba7..ef5652b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -810,7 +810,7 @@
       ..isNonNullableByDefault =
           enclosingClass.enclosingLibrary.isNonNullableByDefault;
     Procedure? constructorTearOff = createConstructorTearOffProcedure(
-        '', classBuilder.library, constructor.fileOffset,
+        '', classBuilder.library, classBuilder.fileUri, constructor.fileOffset,
         forAbstractClassOrEnum:
             enclosingClass.isAbstract || enclosingClass.isEnum);
     if (constructorTearOff != null) {
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 510170a..6f4a1af 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -1017,6 +1017,7 @@
 remedy
 removal
 remover
+renames
 render
 reparse
 repeating
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart
new file mode 100644
index 0000000..d268773
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart
@@ -0,0 +1,7 @@
+// 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.
+
+part 'constructor_tear_off_uri_part.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.expect
new file mode 100644
index 0000000..7998cc3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+//  - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+//   Class Function(int) f = Class.new;
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+  (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+  Class Function(int) f = Class.new;
+                          ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants  {
+  #C1 = tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.transformed.expect
new file mode 100644
index 0000000..7998cc3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+//  - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+//   Class Function(int) f = Class.new;
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+  (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+  Class Function(int) f = Class.new;
+                          ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants  {
+  #C1 = tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline.expect
new file mode 100644
index 0000000..428e3bc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+part 'constructor_tear_off_uri_part.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..428e3bc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+part 'constructor_tear_off_uri_part.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.expect
new file mode 100644
index 0000000..7998cc3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+//  - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+//   Class Function(int) f = Class.new;
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+  (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+  Class Function(int) f = Class.new;
+                          ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants  {
+  #C1 = tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.outline.expect
new file mode 100644
index 0000000..90a7e36
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.outline.expect
@@ -0,0 +1,15 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic
+  ;
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.transformed.expect
new file mode 100644
index 0000000..7998cc3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+//  - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+//   Class Function(int) f = Class.new;
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+  (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+  Class Function(int) f = Class.new;
+                          ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants  {
+  #C1 = tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart
new file mode 100644
index 0000000..042cb62
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart
@@ -0,0 +1,23 @@
+// 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.
+
+part of 'constructor_tear_off_uri.dart';
+
+test() {
+  Class Function(int) f = Class.new;
+}
+
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+
+class Class {}
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 90615e8..8d01d1f 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -362,6 +362,14 @@
           ConstructorTearOffLowering.constructors) !=
       0;
 
+  /// Returns `true` if lowering of redirecting factory tear offs is enabled.
+  ///
+  /// This is determined by the [enabledConstructorTearOffLowerings] mask.
+  bool get isRedirectingFactoryTearOffLoweringEnabled =>
+      (enabledConstructorTearOffLowerings &
+          ConstructorTearOffLowering.redirectingFactories) !=
+      0;
+
   /// Returns `true` if lowering of typedef tear offs is enabled.
   ///
   /// This is determined by the [enabledConstructorTearOffLowerings] mask.
@@ -635,13 +643,16 @@
 }
 
 class ConstructorTearOffLowering {
-  /// Create top level functions to use as tear offs of constructors.
+  /// Create static functions to use as tear offs of constructors and.
   static const int constructors = 1 << 0;
 
-  /// Create top level functions to use as tear offs of non trivial redirecting
-  /// factory constructors and typedefs.
-  static const int typedefs = 1 << 1;
+  /// Create static functions to use as tear offs of redirecting factories.
+  static const int redirectingFactories = 1 << 1;
+
+  /// Create top level functions to use as tear offs of typedefs that are not
+  /// proper renames.
+  static const int typedefs = 1 << 2;
 
   static const int none = 0;
-  static const int all = (1 << 2) - 1;
+  static const int all = (1 << 3) - 1;
 }