[analyzer] Dot shorthands: Infer type parameters in constructor tearoffs.

This CL fixes co19/LanguageFeatures/Static-access-shorthand
/semantics_A05_t01.dart.

While working on this, I realized the static type was wrong and we weren't doing any inference for the constructor references so I updated the logic.

Unit tests passing, language test expectations are actually better than before and that particular co19 test passing.

Bug: https://github.com/dart-lang/sdk/issues/59835
Change-Id: I7437079c33640f53f48a4445890fadfebc9ec158
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/430561
Reviewed-by: Erik Ernst <eernst@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
index ead089f..18cb257 100644
--- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
@@ -12,6 +12,7 @@
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/extensions.dart';
+import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_schema.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
@@ -39,8 +40,9 @@
   TypeSystemImpl get _typeSystem => _resolver.typeSystem;
 
   PropertyElementResolverResult resolveDotShorthand(
-    DotShorthandPropertyAccessImpl node,
-  ) {
+    DotShorthandPropertyAccessImpl node, {
+    required TypeImpl contextType,
+  }) {
     if (_resolver.isDotShorthandContextEmpty) {
       assert(
         false,
@@ -76,6 +78,35 @@
           }
         }
 
+        // Infer type parameters.
+        var elementToInfer = _resolver.inferenceHelper
+            .constructorElementToInfer(
+              typeElement: context.element3,
+              constructorName: identifier,
+              definingLibrary: _resolver.definingLibrary,
+            );
+        if (elementToInfer != null &&
+            elementToInfer.typeParameters2.isNotEmpty) {
+          var inferred =
+              _resolver.inferenceHelper.inferTearOff(
+                    node,
+                    identifier,
+                    elementToInfer.asType,
+                    contextType: contextType,
+                  )
+                  as FunctionType;
+          var inferredType = inferred.returnType;
+          var constructorElement = ConstructorMember.from2(
+            elementToInfer.element2.baseElement,
+            inferredType as InterfaceType,
+          );
+          node.propertyName.element = constructorElement.baseElement;
+          return PropertyElementResolverResult(
+            readElementRequested2: node.propertyName.element,
+            getType: inferred.returnType,
+          );
+        }
+
         return PropertyElementResolverResult(
           readElementRequested2: element,
           getType: element.returnType,
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index eac26ef..2fe4dda 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2524,7 +2524,10 @@
     }
 
     checkUnreachableNode(node);
-    var result = _propertyElementResolver.resolveDotShorthand(node);
+    var result = _propertyElementResolver.resolveDotShorthand(
+      node,
+      contextType: contextType,
+    );
     _resolvePropertyAccessRhs_common(
       result,
       node,
@@ -4462,7 +4465,7 @@
     DartType type;
     if (element is MethodElement) {
       type = element.type;
-    } else if (element is ConstructorElementImpl2) {
+    } else if (element is ConstructorElementMixin2) {
       type = element.type;
     } else if (element is GetterElement) {
       type = resolverResult.getType!;
diff --git a/pkg/analyzer/test/src/dart/resolution/dot_shorthand_property_access_test.dart b/pkg/analyzer/test/src/dart/resolution/dot_shorthand_property_access_test.dart
index b086744..ea78ad2 100644
--- a/pkg/analyzer/test/src/dart/resolution/dot_shorthand_property_access_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/dot_shorthand_property_access_test.dart
@@ -652,6 +652,38 @@
     );
   }
 
+  test_tearOff_constructor_generic() async {
+    await assertNoErrorsInCode(r'''
+class C<T> {
+  T t;
+  C(this.t);
+  C.id(this.t);
+}
+
+void main() {
+  Object? o = C<int>(0);
+  if (o is C<int>) {
+    o = .new;
+    if (o is Function) {
+       o(1).t;
+    }
+  }
+}
+''');
+
+    var dotShorthand = findNode.singleDotShorthandPropertyAccess;
+    assertResolvedNodeText(dotShorthand, r'''
+DotShorthandPropertyAccess
+  period: .
+  propertyName: SimpleIdentifier
+    token: new
+    element: <testLibraryFragment>::@class::C::@constructor::new#element
+    staticType: C<T> Function(T)
+  correspondingParameter: <null>
+  staticType: C<T> Function(T)
+''');
+  }
+
   test_tearOff_constructor_new() async {
     await assertNoErrorsInCode('''
 void main() {
diff --git a/tests/language/dot_shorthands/type_parameter/type_parameter_error_test.dart b/tests/language/dot_shorthands/type_parameter/type_parameter_error_test.dart
index eb2caa0..2c5636c 100644
--- a/tests/language/dot_shorthands/type_parameter/type_parameter_error_test.dart
+++ b/tests/language/dot_shorthands/type_parameter/type_parameter_error_test.dart
@@ -58,8 +58,10 @@
   //                   ^^^^^
   // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION
   ET e = .new<int>;
-  //     ^^^^
-  // [analyzer] COMPILE_TIME_ERROR.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION
+  //     ^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
   //      ^
   // [cfe] A dot shorthand constructor invocation can't have type arguments.
+  //         ^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION
 }