Issue 45579. Report WRONG_NUMBER_OF_TYPE_ARGUMENTS and TYPE_ARGUMENT_NOT_MATCHING_BOUNDS.

Bug: https://github.com/dart-lang/sdk/issues/45579
Change-Id: I757f4d782895fb1a9c89d8238a7929e12d6a6eed
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194000
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
index c82e332..efa3e86c 100644
--- a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -65,6 +66,7 @@
 
     _constructorInvocation(
       node,
+      classElement.name,
       constructorName,
       classElement.typeParameters,
       constructorElement,
@@ -113,6 +115,7 @@
 
   void _constructorInvocation(
     AnnotationImpl node,
+    String typeDisplayName,
     SimpleIdentifierImpl? constructorName,
     List<TypeParameterElement> typeParameters,
     ConstructorElement? constructorElement,
@@ -136,6 +139,18 @@
 
     // If no type parameters, the elements are correct.
     if (typeParameters.isEmpty) {
+      var typeArgumentList = node.typeArguments;
+      if (typeArgumentList != null) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
+          typeArgumentList,
+          [
+            typeDisplayName,
+            typeParameters.length,
+            typeArgumentList.arguments.length,
+          ],
+        );
+      }
       _resolveConstructorInvocationArguments(node);
       InferenceContext.setType(argumentList, constructorElement.type);
       _resolver.visitArgumentList(argumentList,
@@ -174,7 +189,35 @@
         typeArguments = typeArgumentList.arguments
             .map((element) => element.typeOrThrow)
             .toList();
+        var substitution = Substitution.fromPairs(
+          typeParameters,
+          typeArguments,
+        );
+        for (var i = 0; i < typeParameters.length; i++) {
+          var typeParameter = typeParameters[i];
+          var bound = typeParameter.bound;
+          if (bound != null) {
+            bound = substitution.substituteType(bound);
+            var typeArgument = typeArguments[i];
+            if (!_resolver.typeSystem.isSubtypeOf(typeArgument, bound)) {
+              _errorReporter.reportErrorForNode(
+                CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+                typeArgumentList.arguments[i],
+                [typeArgument, typeParameter.name, bound],
+              );
+            }
+          }
+        }
       } else {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
+          typeArgumentList,
+          [
+            typeDisplayName,
+            typeParameters.length,
+            typeArgumentList.arguments.length,
+          ],
+        );
         typeArguments = List.filled(
           typeParameters.length,
           DynamicTypeImpl.instance,
@@ -458,6 +501,7 @@
 
     _constructorInvocation(
       node,
+      typeAliasElement.name,
       constructorName,
       typeAliasElement.typeParameters,
       constructorElement,
diff --git a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
index 9d407aa..25184c2 100644
--- a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
@@ -471,6 +471,45 @@
 ''');
   }
 
+  test_metadata_matching() async {
+    await assertNoErrorsInCode(r'''
+class A<T extends num> {
+  const A();
+}
+
+@A<int>()
+void f() {}
+''');
+  }
+
+  test_metadata_notMatching() async {
+    await assertErrorsInCode(r'''
+class A<T extends num> {
+  const A();
+}
+
+@A<String>()
+void f() {}
+''', [
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 44, 6),
+    ]);
+  }
+
+  test_metadata_notMatching_viaTypeAlias() async {
+    await assertErrorsInCode(r'''
+class A<T> {
+  const A();
+}
+
+typedef B<T extends num> = A<T>;
+
+@B<String>()
+void f() {}
+''', [
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 66, 6),
+    ]);
+  }
+
   test_methodInvocation_genericFunctionTypeArgument_match() async {
     await assertNoErrorsInCode(r'''
 typedef F = void Function<T extends num>();
diff --git a/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart b/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
index 29e3eee..6754881 100644
--- a/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
@@ -93,6 +93,90 @@
     ]);
   }
 
+  test_metadata_1of0() async {
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+}
+
+@A<int>()
+void f() {}
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 28, 5),
+    ]);
+  }
+
+  test_metadata_1of0_viaTypeAlias() async {
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+}
+
+typedef B = A;
+
+@B<int>()
+void f() {}
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 44, 5),
+    ]);
+  }
+
+  test_metadata_1of2() async {
+    await assertErrorsInCode(r'''
+class A<T, U> {
+  const A();
+}
+
+@A<int>()
+void f() {}
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 34, 5),
+    ]);
+  }
+
+  test_metadata_1of2_viaTypeAlias() async {
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+}
+
+typedef B<T, U> = A;
+
+@B<int>()
+void f() {}
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 50, 5),
+    ]);
+  }
+
+  test_metadata_2of1() async {
+    await assertErrorsInCode(r'''
+class A<T> {
+  const A();
+}
+
+@A<int, String>()
+void f() {}
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 31, 13),
+    ]);
+  }
+
+  test_metadata_2of1_viaTypeAlias() async {
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+}
+
+typedef B<T> = A;
+
+@B<int, String>()
+void f() {}
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 47, 13),
+    ]);
+  }
+
   test_new_nonGeneric() async {
     await assertErrorsInCode('''
 class C {}