[cfe] Check for misplaced type arguments on implicit creation expression

Change-Id: Ic3436f2bce0369d0efad9946cbbdae7c6bf334b9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/218400
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
index 82f970c..042507d 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
@@ -810,8 +810,8 @@
   }
 
   @override
-  void endImplicitCreationExpression(Token token) {
-    listener?.endImplicitCreationExpression(token);
+  void endImplicitCreationExpression(Token token, Token openAngleBracket) {
+    listener?.endImplicitCreationExpression(token, openAngleBracket);
   }
 
   @override
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
index cd83709..63a247f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
@@ -743,7 +743,7 @@
 
   void beginImplicitCreationExpression(Token token) {}
 
-  void endImplicitCreationExpression(Token token) {
+  void endImplicitCreationExpression(Token token, Token openAngleBracket) {
     logEvent("ImplicitCreationExpression");
   }
 
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index 0f466bf..cb1ef21 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -5404,7 +5404,8 @@
               Token afterPeriod = afterTypeArguments.next!;
               if (_isNewOrIdentifier(afterPeriod) &&
                   optional('(', afterPeriod.next!)) {
-                return parseImplicitCreationExpression(token, typeArg);
+                return parseImplicitCreationExpression(
+                    token, identifier.next!, typeArg);
               }
             }
           }
@@ -6057,13 +6058,13 @@
   }
 
   Token parseImplicitCreationExpression(
-      Token token, TypeParamOrArgInfo typeArg) {
-    Token begin = token;
-    listener.beginImplicitCreationExpression(token);
+      Token token, Token openAngleBracket, TypeParamOrArgInfo typeArg) {
+    Token begin = token.next!; // This is the class name.
+    listener.beginImplicitCreationExpression(begin);
     token = parseConstructorReference(
         token, ConstructorReferenceContext.Implicit, typeArg);
     token = parseConstructorInvocationArguments(token);
-    listener.endImplicitCreationExpression(begin);
+    listener.endImplicitCreationExpression(begin, openAngleBracket);
     return token;
   }
 
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index e88c858..4a50a3c 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -1664,7 +1664,7 @@
   }
 
   @override
-  void endImplicitCreationExpression(Token token) {
+  void endImplicitCreationExpression(Token token, Token openAngleBracket) {
     debugEvent("ImplicitCreationExpression");
 
     _handleInstanceCreation(null);
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 6f08b8b..c19ef88 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -4948,6 +4948,14 @@
     if (enableConstructorTearOffsInLibrary && inImplicitCreationContext) {
       Expression receiver = receiverFunction();
       if (typeArguments != null) {
+        if (receiver is StaticTearOff &&
+                (receiver.target.isFactory ||
+                    isTearOffLowering(receiver.target)) ||
+            receiver is ConstructorTearOff ||
+            receiver is RedirectingFactoryTearOff) {
+          return buildProblem(fasta.messageConstructorTearOffWithTypeArguments,
+              instantiationOffset, noLength);
+        }
         receiver = forest.createInstantiation(
             instantiationOffset,
             receiver,
@@ -4974,10 +4982,10 @@
   }
 
   @override
-  void endImplicitCreationExpression(Token token) {
+  void endImplicitCreationExpression(Token token, Token openAngleBracket) {
     debugEvent("ImplicitCreationExpression");
     _buildConstructorReferenceInvocation(
-        token.next!, token.offset, Constness.implicit,
+        token, openAngleBracket.offset, Constness.implicit,
         inMetadata: false, inImplicitCreationContext: true);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.dart b/pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.dart
index ffb7439..4fedb0b 100644
--- a/pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.dart
+++ b/pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.dart
@@ -1172,11 +1172,12 @@
   }
 
   @override
-  void endImplicitCreationExpression(Token token) {
+  void endImplicitCreationExpression(Token token, Token openAngleBracket) {
     DirectParserASTContentImplicitCreationExpressionEnd data =
         new DirectParserASTContentImplicitCreationExpressionEnd(
             DirectParserASTType.END,
-            token: token);
+            token: token,
+            openAngleBracket: openAngleBracket);
     seen(data);
   }
 
@@ -4782,14 +4783,16 @@
 class DirectParserASTContentImplicitCreationExpressionEnd
     extends DirectParserASTContent {
   final Token token;
+  final Token openAngleBracket;
 
   DirectParserASTContentImplicitCreationExpressionEnd(DirectParserASTType type,
-      {required this.token})
+      {required this.token, required this.openAngleBracket})
       : super("ImplicitCreationExpression", type);
 
   @override
   Map<String, Object?> get deprecatedArguments => {
         "token": token,
+        "openAngleBracket": openAngleBracket,
       };
 }
 
diff --git a/pkg/front_end/parser_testcases/general/function_reference_following_token.dart.expect b/pkg/front_end/parser_testcases/general/function_reference_following_token.dart.expect
index 2fca01a..8b8e356 100644
--- a/pkg/front_end/parser_testcases/general/function_reference_following_token.dart.expect
+++ b/pkg/front_end/parser_testcases/general/function_reference_following_token.dart.expect
@@ -293,7 +293,7 @@
       handleNoType(var)
       handleIdentifier(typeArgs_period_methodInvocation, topLevelVariableDeclaration)
       beginFieldInitializer(=)
-        beginImplicitCreationExpression(=)
+        beginImplicitCreationExpression(f)
           handleIdentifier(f, constructorReference)
           beginConstructorReference(f)
             beginTypeArguments(<)
@@ -308,7 +308,7 @@
           endConstructorReference(f, ., (, ConstructorReferenceContext.Implicit)
           beginArguments(()
           endArguments(0, (, ))
-        endImplicitCreationExpression(=)
+        endImplicitCreationExpression(f, <)
       endFieldInitializer(=, ;)
     endTopLevelFields(null, null, null, null, var, 1, var, ;)
   endTopLevelDeclaration(var)
diff --git a/pkg/front_end/parser_testcases/general/function_reference_following_token.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/function_reference_following_token.dart.intertwined.expect
index 32d6f7d..11e6ef5 100644
--- a/pkg/front_end/parser_testcases/general/function_reference_following_token.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/general/function_reference_following_token.dart.intertwined.expect
@@ -396,8 +396,8 @@
           parseExpression(=)
             parsePrecedenceExpression(=, 1, true)
               parseUnaryExpression(=, true)
-                parseImplicitCreationExpression(=, Instance of 'ComplexTypeParamOrArgInfo')
-                  listener: beginImplicitCreationExpression(=)
+                parseImplicitCreationExpression(=, <, Instance of 'ComplexTypeParamOrArgInfo')
+                  listener: beginImplicitCreationExpression(f)
                   parseConstructorReference(=, ConstructorReferenceContext.Implicit, Instance of 'ComplexTypeParamOrArgInfo')
                     ensureIdentifier(=, constructorReference)
                       listener: handleIdentifier(f, constructorReference)
@@ -418,7 +418,7 @@
                     parseArgumentsRest(()
                       listener: beginArguments(()
                       listener: endArguments(0, (, ))
-                  listener: endImplicitCreationExpression(=)
+                  listener: endImplicitCreationExpression(f, <)
           listener: endFieldInitializer(=, ;)
         listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
   listener: endTopLevelDeclaration(var)
diff --git a/pkg/front_end/parser_testcases/general/new_as_identifier.dart.expect b/pkg/front_end/parser_testcases/general/new_as_identifier.dart.expect
index 89b9611..97bcac4 100644
--- a/pkg/front_end/parser_testcases/general/new_as_identifier.dart.expect
+++ b/pkg/front_end/parser_testcases/general/new_as_identifier.dart.expect
@@ -545,7 +545,7 @@
       handleNoType(var)
       handleIdentifier(constructor_invocation_implicit_generic, topLevelVariableDeclaration)
       beginFieldInitializer(=)
-        beginImplicitCreationExpression(=)
+        beginImplicitCreationExpression(C)
           handleIdentifier(C, constructorReference)
           beginConstructorReference(C)
             beginTypeArguments(<)
@@ -558,7 +558,7 @@
           endConstructorReference(C, ., (, ConstructorReferenceContext.Implicit)
           beginArguments(()
           endArguments(0, (, ))
-        endImplicitCreationExpression(=)
+        endImplicitCreationExpression(C, <)
       endFieldInitializer(=, ;)
     endTopLevelFields(null, null, null, null, var, 1, var, ;)
   endTopLevelDeclaration(var)
@@ -595,7 +595,7 @@
       handleNoType(var)
       handleIdentifier(constructor_invocation_implicit_prefixed_generic, topLevelVariableDeclaration)
       beginFieldInitializer(=)
-        beginImplicitCreationExpression(=)
+        beginImplicitCreationExpression(prefix)
           handleIdentifier(prefix, constructorReference)
           beginConstructorReference(prefix)
             handleIdentifier(C, constructorReferenceContinuation)
@@ -610,7 +610,7 @@
           endConstructorReference(prefix, ., (, ConstructorReferenceContext.Implicit)
           beginArguments(()
           endArguments(0, (, ))
-        endImplicitCreationExpression(=)
+        endImplicitCreationExpression(prefix, <)
       endFieldInitializer(=, ;)
     endTopLevelFields(null, null, null, null, var, 1, var, ;)
   endTopLevelDeclaration(var)
diff --git a/pkg/front_end/parser_testcases/general/new_as_identifier.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/new_as_identifier.dart.intertwined.expect
index f1c6c1c..7af61b0 100644
--- a/pkg/front_end/parser_testcases/general/new_as_identifier.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/general/new_as_identifier.dart.intertwined.expect
@@ -1028,8 +1028,8 @@
           parseExpression(=)
             parsePrecedenceExpression(=, 1, true)
               parseUnaryExpression(=, true)
-                parseImplicitCreationExpression(=, Instance of 'SimpleTypeArgument1')
-                  listener: beginImplicitCreationExpression(=)
+                parseImplicitCreationExpression(=, <, Instance of 'SimpleTypeArgument1')
+                  listener: beginImplicitCreationExpression(C)
                   parseConstructorReference(=, ConstructorReferenceContext.Implicit, Instance of 'SimpleTypeArgument1')
                     ensureIdentifier(=, constructorReference)
                       listener: handleIdentifier(C, constructorReference)
@@ -1049,7 +1049,7 @@
                     parseArgumentsRest(()
                       listener: beginArguments(()
                       listener: endArguments(0, (, ))
-                  listener: endImplicitCreationExpression(=)
+                  listener: endImplicitCreationExpression(C, <)
           listener: endFieldInitializer(=, ;)
         listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
   listener: endTopLevelDeclaration(var)
@@ -1126,8 +1126,8 @@
           parseExpression(=)
             parsePrecedenceExpression(=, 1, true)
               parseUnaryExpression(=, true)
-                parseImplicitCreationExpression(=, Instance of 'SimpleTypeArgument1')
-                  listener: beginImplicitCreationExpression(=)
+                parseImplicitCreationExpression(=, <, Instance of 'SimpleTypeArgument1')
+                  listener: beginImplicitCreationExpression(prefix)
                   parseConstructorReference(=, ConstructorReferenceContext.Implicit, Instance of 'SimpleTypeArgument1')
                     ensureIdentifier(=, constructorReference)
                       listener: handleIdentifier(prefix, constructorReference)
@@ -1151,7 +1151,7 @@
                     parseArgumentsRest(()
                       listener: beginArguments(()
                       listener: endArguments(0, (, ))
-                  listener: endImplicitCreationExpression(=)
+                  listener: endImplicitCreationExpression(prefix, <)
           listener: endFieldInitializer(=, ;)
         listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
   listener: endTopLevelDeclaration(var)
diff --git a/pkg/front_end/test/parser_test_listener.dart b/pkg/front_end/test/parser_test_listener.dart
index 7fcb1c2..f82cd95 100644
--- a/pkg/front_end/test/parser_test_listener.dart
+++ b/pkg/front_end/test/parser_test_listener.dart
@@ -1086,10 +1086,11 @@
   }
 
   @override
-  void endImplicitCreationExpression(Token token) {
+  void endImplicitCreationExpression(Token token, Token openAngleBracket) {
     indent--;
     seen(token);
-    doPrint('endImplicitCreationExpression(' '$token)');
+    seen(openAngleBracket);
+    doPrint('endImplicitCreationExpression(' '$token, ' '$openAngleBracket)');
   }
 
   @override
diff --git a/pkg/front_end/test/parser_test_parser.dart b/pkg/front_end/test/parser_test_parser.dart
index 3ea2b0c..a6ba2ca 100644
--- a/pkg/front_end/test/parser_test_parser.dart
+++ b/pkg/front_end/test/parser_test_parser.dart
@@ -1651,10 +1651,14 @@
 
   @override
   Token parseImplicitCreationExpression(
-      Token token, TypeParamOrArgInfo typeArg) {
-    doPrint('parseImplicitCreationExpression(' '$token, ' '$typeArg)');
+      Token token, Token openAngleBracket, TypeParamOrArgInfo typeArg) {
+    doPrint('parseImplicitCreationExpression('
+        '$token, '
+        '$openAngleBracket, '
+        '$typeArg)');
     indent++;
-    var result = super.parseImplicitCreationExpression(token, typeArg);
+    var result =
+        super.parseImplicitCreationExpression(token, openAngleBracket, typeArg);
     indent--;
     return result;
   }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart b/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart
index efe748f..4232eea 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart
@@ -21,7 +21,7 @@
 }
 
 test() {
-  A.named<int>.toString();
+  A.named<int>.toString(); // error
 }
 
 void main() {
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.strong.expect
index 99500cc..a62bd0c 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.strong.expect
@@ -1,4 +1,12 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/issue46719.dart:24:10: Error: A constructor tear-off can't have type arguments after the constructor name.
+// Try removing the type arguments or placing them after the class name.
+//   A.named<int>.toString(); // error
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -27,30 +35,33 @@
 static method FunctionApplier|get#applyAndPrint(lowered final core::Function #this) → (core::List<core::Object?>) → void
   return (core::List<core::Object?> positionalArguments) → void => self::FunctionApplier|applyAndPrint(#this, positionalArguments);
 static method test() → dynamic {
-  #C3.{core::Object::toString}(){() → core::String};
+  invalid-expression "pkg/front_end/testcases/constructor_tearoffs/issue46719.dart:24:10: Error: A constructor tear-off can't have type arguments after the constructor name.
+Try removing the type arguments or placing them after the class name.
+  A.named<int>.toString(); // error
+         ^";
 }
 static method main() → void {
   self::A<dynamic> a = new self::A::•<dynamic>();
   self::FunctionApplier|applyAndPrint(a.{self::A::m}{<X extends core::Object? = dynamic>(X%) → core::List<X%>}<core::int>, <core::Object?>[2]);
   self::FunctionApplier|applyAndPrint(a.{self::A::m}{<X extends core::Object? = dynamic>(X%) → core::List<X%>}<core::String>, <core::Object?>["three"]);
-  self::FunctionApplier|applyAndPrint(#C5, <core::Object?>[2]);
-  self::FunctionApplier|applyAndPrint(#C6, <core::Object?>["three"]);
-  self::FunctionApplier|applyAndPrint(#C8, <core::Object?>[2]);
-  self::FunctionApplier|applyAndPrint(#C9, <core::Object?>["three"]);
-  self::FunctionApplier|applyAndPrint(#C5, <core::Object?>[2]);
-  self::FunctionApplier|applyAndPrint(#C6, <core::Object?>["three"]);
-  #C2.{core::Object::toString}(){() → core::String};
-  #C3.{core::Object::toString}(){() → core::String};
+  self::FunctionApplier|applyAndPrint(#C3, <core::Object?>[2]);
+  self::FunctionApplier|applyAndPrint(#C4, <core::Object?>["three"]);
+  self::FunctionApplier|applyAndPrint(#C6, <core::Object?>[2]);
+  self::FunctionApplier|applyAndPrint(#C7, <core::Object?>["three"]);
+  self::FunctionApplier|applyAndPrint(#C3, <core::Object?>[2]);
+  self::FunctionApplier|applyAndPrint(#C4, <core::Object?>["three"]);
+  #C8.{core::Object::toString}(){() → core::String};
+  #C9.{core::Object::toString}(){() → core::String};
 }
 
 constants  {
   #C1 = <core::Symbol, dynamic>{)
-  #C2 = constructor-tearoff self::A::named
+  #C2 = static-tearoff self::A::n
   #C3 = instantiation #C2 <core::int>
-  #C4 = static-tearoff self::A::n
-  #C5 = instantiation #C4 <core::int>
-  #C6 = instantiation #C4 <core::String>
-  #C7 = static-tearoff self::m
-  #C8 = instantiation #C7 <core::int>
-  #C9 = instantiation #C7 <core::String>
+  #C4 = instantiation #C2 <core::String>
+  #C5 = static-tearoff self::m
+  #C6 = instantiation #C5 <core::int>
+  #C7 = instantiation #C5 <core::String>
+  #C8 = constructor-tearoff self::A::named
+  #C9 = instantiation #C8 <core::int>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.strong.transformed.expect
index 4e41cb6..7124a3a 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.strong.transformed.expect
@@ -1,4 +1,12 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/issue46719.dart:24:10: Error: A constructor tear-off can't have type arguments after the constructor name.
+// Try removing the type arguments or placing them after the class name.
+//   A.named<int>.toString(); // error
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -27,30 +35,33 @@
 static method FunctionApplier|get#applyAndPrint(lowered final core::Function #this) → (core::List<core::Object?>) → void
   return (core::List<core::Object?> positionalArguments) → void => self::FunctionApplier|applyAndPrint(#this, positionalArguments);
 static method test() → dynamic {
-  #C3.{core::Object::toString}(){() → core::String};
+  invalid-expression "pkg/front_end/testcases/constructor_tearoffs/issue46719.dart:24:10: Error: A constructor tear-off can't have type arguments after the constructor name.
+Try removing the type arguments or placing them after the class name.
+  A.named<int>.toString(); // error
+         ^";
 }
 static method main() → void {
   self::A<dynamic> a = new self::A::•<dynamic>();
   self::FunctionApplier|applyAndPrint(a.{self::A::m}{<X extends core::Object? = dynamic>(X%) → core::List<X%>}<core::int>, core::_GrowableList::_literal1<core::Object?>(2));
   self::FunctionApplier|applyAndPrint(a.{self::A::m}{<X extends core::Object? = dynamic>(X%) → core::List<X%>}<core::String>, core::_GrowableList::_literal1<core::Object?>("three"));
-  self::FunctionApplier|applyAndPrint(#C5, core::_GrowableList::_literal1<core::Object?>(2));
-  self::FunctionApplier|applyAndPrint(#C6, core::_GrowableList::_literal1<core::Object?>("three"));
-  self::FunctionApplier|applyAndPrint(#C8, core::_GrowableList::_literal1<core::Object?>(2));
-  self::FunctionApplier|applyAndPrint(#C9, core::_GrowableList::_literal1<core::Object?>("three"));
-  self::FunctionApplier|applyAndPrint(#C5, core::_GrowableList::_literal1<core::Object?>(2));
-  self::FunctionApplier|applyAndPrint(#C6, core::_GrowableList::_literal1<core::Object?>("three"));
-  #C2.{core::Object::toString}(){() → core::String};
-  #C3.{core::Object::toString}(){() → core::String};
+  self::FunctionApplier|applyAndPrint(#C3, core::_GrowableList::_literal1<core::Object?>(2));
+  self::FunctionApplier|applyAndPrint(#C4, core::_GrowableList::_literal1<core::Object?>("three"));
+  self::FunctionApplier|applyAndPrint(#C6, core::_GrowableList::_literal1<core::Object?>(2));
+  self::FunctionApplier|applyAndPrint(#C7, core::_GrowableList::_literal1<core::Object?>("three"));
+  self::FunctionApplier|applyAndPrint(#C3, core::_GrowableList::_literal1<core::Object?>(2));
+  self::FunctionApplier|applyAndPrint(#C4, core::_GrowableList::_literal1<core::Object?>("three"));
+  #C8.{core::Object::toString}(){() → core::String};
+  #C9.{core::Object::toString}(){() → core::String};
 }
 
 constants  {
   #C1 = <core::Symbol, dynamic>{)
-  #C2 = constructor-tearoff self::A::named
+  #C2 = static-tearoff self::A::n
   #C3 = instantiation #C2 <core::int>
-  #C4 = static-tearoff self::A::n
-  #C5 = instantiation #C4 <core::int>
-  #C6 = instantiation #C4 <core::String>
-  #C7 = static-tearoff self::m
-  #C8 = instantiation #C7 <core::int>
-  #C9 = instantiation #C7 <core::String>
+  #C4 = instantiation #C2 <core::String>
+  #C5 = static-tearoff self::m
+  #C6 = instantiation #C5 <core::int>
+  #C7 = instantiation #C5 <core::String>
+  #C8 = constructor-tearoff self::A::named
+  #C9 = instantiation #C8 <core::int>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.weak.expect
index ce83852..6add537 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.weak.expect
@@ -1,4 +1,12 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/issue46719.dart:24:10: Error: A constructor tear-off can't have type arguments after the constructor name.
+// Try removing the type arguments or placing them after the class name.
+//   A.named<int>.toString(); // error
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -27,30 +35,33 @@
 static method FunctionApplier|get#applyAndPrint(lowered final core::Function #this) → (core::List<core::Object?>) → void
   return (core::List<core::Object?> positionalArguments) → void => self::FunctionApplier|applyAndPrint(#this, positionalArguments);
 static method test() → dynamic {
-  #C3.{core::Object::toString}(){() → core::String};
+  invalid-expression "pkg/front_end/testcases/constructor_tearoffs/issue46719.dart:24:10: Error: A constructor tear-off can't have type arguments after the constructor name.
+Try removing the type arguments or placing them after the class name.
+  A.named<int>.toString(); // error
+         ^";
 }
 static method main() → void {
   self::A<dynamic> a = new self::A::•<dynamic>();
   self::FunctionApplier|applyAndPrint(a.{self::A::m}{<X extends core::Object? = dynamic>(X%) → core::List<X%>}<core::int>, <core::Object?>[2]);
   self::FunctionApplier|applyAndPrint(a.{self::A::m}{<X extends core::Object? = dynamic>(X%) → core::List<X%>}<core::String>, <core::Object?>["three"]);
-  self::FunctionApplier|applyAndPrint(#C5, <core::Object?>[2]);
-  self::FunctionApplier|applyAndPrint(#C6, <core::Object?>["three"]);
-  self::FunctionApplier|applyAndPrint(#C8, <core::Object?>[2]);
-  self::FunctionApplier|applyAndPrint(#C9, <core::Object?>["three"]);
-  self::FunctionApplier|applyAndPrint(#C5, <core::Object?>[2]);
-  self::FunctionApplier|applyAndPrint(#C6, <core::Object?>["three"]);
-  #C2.{core::Object::toString}(){() → core::String};
-  #C3.{core::Object::toString}(){() → core::String};
+  self::FunctionApplier|applyAndPrint(#C3, <core::Object?>[2]);
+  self::FunctionApplier|applyAndPrint(#C4, <core::Object?>["three"]);
+  self::FunctionApplier|applyAndPrint(#C6, <core::Object?>[2]);
+  self::FunctionApplier|applyAndPrint(#C7, <core::Object?>["three"]);
+  self::FunctionApplier|applyAndPrint(#C3, <core::Object?>[2]);
+  self::FunctionApplier|applyAndPrint(#C4, <core::Object?>["three"]);
+  #C8.{core::Object::toString}(){() → core::String};
+  #C9.{core::Object::toString}(){() → core::String};
 }
 
 constants  {
   #C1 = <core::Symbol*, dynamic>{)
-  #C2 = constructor-tearoff self::A::named
+  #C2 = static-tearoff self::A::n
   #C3 = instantiation #C2 <core::int*>
-  #C4 = static-tearoff self::A::n
-  #C5 = instantiation #C4 <core::int*>
-  #C6 = instantiation #C4 <core::String*>
-  #C7 = static-tearoff self::m
-  #C8 = instantiation #C7 <core::int*>
-  #C9 = instantiation #C7 <core::String*>
+  #C4 = instantiation #C2 <core::String*>
+  #C5 = static-tearoff self::m
+  #C6 = instantiation #C5 <core::int*>
+  #C7 = instantiation #C5 <core::String*>
+  #C8 = constructor-tearoff self::A::named
+  #C9 = instantiation #C8 <core::int*>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.weak.transformed.expect
index cd0afe2..328de14 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue46719.dart.weak.transformed.expect
@@ -1,4 +1,12 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/issue46719.dart:24:10: Error: A constructor tear-off can't have type arguments after the constructor name.
+// Try removing the type arguments or placing them after the class name.
+//   A.named<int>.toString(); // error
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -27,30 +35,33 @@
 static method FunctionApplier|get#applyAndPrint(lowered final core::Function #this) → (core::List<core::Object?>) → void
   return (core::List<core::Object?> positionalArguments) → void => self::FunctionApplier|applyAndPrint(#this, positionalArguments);
 static method test() → dynamic {
-  #C3.{core::Object::toString}(){() → core::String};
+  invalid-expression "pkg/front_end/testcases/constructor_tearoffs/issue46719.dart:24:10: Error: A constructor tear-off can't have type arguments after the constructor name.
+Try removing the type arguments or placing them after the class name.
+  A.named<int>.toString(); // error
+         ^";
 }
 static method main() → void {
   self::A<dynamic> a = new self::A::•<dynamic>();
   self::FunctionApplier|applyAndPrint(a.{self::A::m}{<X extends core::Object? = dynamic>(X%) → core::List<X%>}<core::int>, core::_GrowableList::_literal1<core::Object?>(2));
   self::FunctionApplier|applyAndPrint(a.{self::A::m}{<X extends core::Object? = dynamic>(X%) → core::List<X%>}<core::String>, core::_GrowableList::_literal1<core::Object?>("three"));
-  self::FunctionApplier|applyAndPrint(#C5, core::_GrowableList::_literal1<core::Object?>(2));
-  self::FunctionApplier|applyAndPrint(#C6, core::_GrowableList::_literal1<core::Object?>("three"));
-  self::FunctionApplier|applyAndPrint(#C8, core::_GrowableList::_literal1<core::Object?>(2));
-  self::FunctionApplier|applyAndPrint(#C9, core::_GrowableList::_literal1<core::Object?>("three"));
-  self::FunctionApplier|applyAndPrint(#C5, core::_GrowableList::_literal1<core::Object?>(2));
-  self::FunctionApplier|applyAndPrint(#C6, core::_GrowableList::_literal1<core::Object?>("three"));
-  #C2.{core::Object::toString}(){() → core::String};
-  #C3.{core::Object::toString}(){() → core::String};
+  self::FunctionApplier|applyAndPrint(#C3, core::_GrowableList::_literal1<core::Object?>(2));
+  self::FunctionApplier|applyAndPrint(#C4, core::_GrowableList::_literal1<core::Object?>("three"));
+  self::FunctionApplier|applyAndPrint(#C6, core::_GrowableList::_literal1<core::Object?>(2));
+  self::FunctionApplier|applyAndPrint(#C7, core::_GrowableList::_literal1<core::Object?>("three"));
+  self::FunctionApplier|applyAndPrint(#C3, core::_GrowableList::_literal1<core::Object?>(2));
+  self::FunctionApplier|applyAndPrint(#C4, core::_GrowableList::_literal1<core::Object?>("three"));
+  #C8.{core::Object::toString}(){() → core::String};
+  #C9.{core::Object::toString}(){() → core::String};
 }
 
 constants  {
   #C1 = <core::Symbol*, dynamic>{)
-  #C2 = constructor-tearoff self::A::named
+  #C2 = static-tearoff self::A::n
   #C3 = instantiation #C2 <core::int*>
-  #C4 = static-tearoff self::A::n
-  #C5 = instantiation #C4 <core::int*>
-  #C6 = instantiation #C4 <core::String*>
-  #C7 = static-tearoff self::m
-  #C8 = instantiation #C7 <core::int*>
-  #C9 = instantiation #C7 <core::String*>
+  #C4 = instantiation #C2 <core::String*>
+  #C5 = static-tearoff self::m
+  #C6 = instantiation #C5 <core::int*>
+  #C7 = instantiation #C5 <core::String*>
+  #C8 = constructor-tearoff self::A::named
+  #C9 = instantiation #C8 <core::int*>
 }
diff --git a/tests/language/constructor/reference_test.dart b/tests/language/constructor/reference_test.dart
index 6828160..06755d1 100644
--- a/tests/language/constructor/reference_test.dart
+++ b/tests/language/constructor/reference_test.dart
@@ -97,8 +97,7 @@
   Foo.bar<int>.baz();
 //       ^^^^^
 // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
-//             ^
-// [cfe] The method 'baz' isn't defined for the class 'Foo<int> Function()'.
+// [cfe] A constructor tear-off can't have type arguments after the constructor name.
   Foo.bar.baz<int>();
 //        ^^^
 // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD