Version 2.13.0-189.0.dev

Merge commit 'e673c1982045905c6bd488f524c0d7c497c733d9' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
index d246ff1..c82e332 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/resolver/invocation_inference_helper.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
@@ -46,6 +47,38 @@
     }
   }
 
+  void _classConstructorInvocation(
+    AnnotationImpl node,
+    ClassElement classElement,
+    SimpleIdentifierImpl? constructorName,
+    ArgumentList argumentList,
+    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
+  ) {
+    ConstructorElement? constructorElement;
+    if (constructorName != null) {
+      constructorElement = classElement.getNamedConstructor(
+        constructorName.name,
+      );
+    } else {
+      constructorElement = classElement.unnamedConstructor;
+    }
+
+    _constructorInvocation(
+      node,
+      constructorName,
+      classElement.typeParameters,
+      constructorElement,
+      argumentList,
+      (typeArguments) {
+        return classElement.instantiate(
+          typeArguments: typeArguments,
+          nullabilitySuffix: _resolver.noneOrStarSuffix,
+        );
+      },
+      whyNotPromotedList,
+    );
+  }
+
   void _classGetter(
     AnnotationImpl node,
     ClassElement classElement,
@@ -80,20 +113,13 @@
 
   void _constructorInvocation(
     AnnotationImpl node,
-    ClassElement classElement,
     SimpleIdentifierImpl? constructorName,
+    List<TypeParameterElement> typeParameters,
+    ConstructorElement? constructorElement,
     ArgumentList argumentList,
+    InterfaceType Function(List<DartType> typeArguments) instantiateElement,
     List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
   ) {
-    ConstructorElement? constructorElement;
-    if (constructorName != null) {
-      constructorElement = classElement.getNamedConstructor(
-        constructorName.name,
-      );
-    } else {
-      constructorElement = classElement.unnamedConstructor;
-    }
-
     constructorElement = _resolver.toLegacyElement(constructorElement);
     constructorName?.staticElement = constructorElement;
     node.element = constructorElement;
@@ -108,8 +134,6 @@
       return;
     }
 
-    var typeParameters = classElement.typeParameters;
-
     // If no type parameters, the elements are correct.
     if (typeParameters.isEmpty) {
       _resolveConstructorInvocationArguments(node);
@@ -123,10 +147,7 @@
       List<DartType> typeArguments,
       ConstructorElement constructorElement,
     ) {
-      var type = classElement.instantiate(
-        typeArguments: typeArguments,
-        nullabilitySuffix: _resolver.noneOrStarSuffix,
-      );
+      var type = instantiateElement(typeArguments);
       constructorElement = ConstructorMember.from(constructorElement, type);
       constructorName?.staticElement = constructorElement;
       node.element = constructorElement;
@@ -166,8 +187,11 @@
     _resolver.visitArgumentList(argumentList,
         whyNotPromotedList: whyNotPromotedList);
 
-    var constructorRawType = _resolver.typeAnalyzer
-        .constructorToGenericFunctionType(constructorElement);
+    var elementToInfer = ConstructorElementToInfer(
+      typeParameters,
+      constructorElement,
+    );
+    var constructorRawType = elementToInfer.asType;
 
     var inferred = _resolver.inferenceHelper.inferGenericInvoke(
         node, constructorRawType, typeArgumentList, argumentList, node,
@@ -264,7 +288,7 @@
     // Class(args) or Class.CONST
     if (element1 is ClassElement) {
       if (argumentList != null) {
-        _constructorInvocation(
+        _classConstructorInvocation(
             node, element1, name2, argumentList, whyNotPromotedList);
       } else {
         _classGetter(node, element1, name2, whyNotPromotedList);
@@ -286,7 +310,7 @@
         // prefix.Class(args) or prefix.Class.CONST
         if (element2 is ClassElement) {
           if (argumentList != null) {
-            _constructorInvocation(
+            _classConstructorInvocation(
                 node, element2, name3, argumentList, whyNotPromotedList);
           } else {
             _classGetter(node, element2, name3, whyNotPromotedList);
@@ -303,6 +327,19 @@
           _propertyAccessorElement(node, name2, element2, whyNotPromotedList);
           return;
         }
+
+        // prefix.TypeAlias(args) or prefix.TypeAlias.CONST
+        if (element2 is TypeAliasElement) {
+          var aliasedType = element2.aliasedType;
+          var argumentList = node.arguments;
+          if (aliasedType is InterfaceType && argumentList != null) {
+            _typeAliasConstructorInvocation(node, element2, name3, aliasedType,
+                argumentList, whyNotPromotedList);
+          } else {
+            _typeAliasGetter(node, element2, name3, whyNotPromotedList);
+          }
+          return;
+        }
         // undefined
         if (element2 == null) {
           _errorReporter.reportErrorForNode(
@@ -322,6 +359,19 @@
       return;
     }
 
+    // TypeAlias(args) or TypeAlias.CONST
+    if (element1 is TypeAliasElement) {
+      var aliasedType = element1.aliasedType;
+      var argumentList = node.arguments;
+      if (aliasedType is InterfaceType && argumentList != null) {
+        _typeAliasConstructorInvocation(node, element1, name2, aliasedType,
+            argumentList, whyNotPromotedList);
+      } else {
+        _typeAliasGetter(node, element1, name2, whyNotPromotedList);
+      }
+      return;
+    }
+
     // TODO(scheglov) Must be const.
     if (element1 is VariableElement) {
       return;
@@ -393,6 +443,67 @@
     }
   }
 
+  void _typeAliasConstructorInvocation(
+    AnnotationImpl node,
+    TypeAliasElement typeAliasElement,
+    SimpleIdentifierImpl? constructorName,
+    InterfaceType aliasedType,
+    ArgumentList argumentList,
+    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
+  ) {
+    var constructorElement = aliasedType.lookUpConstructor(
+      constructorName?.name,
+      _definingLibrary,
+    );
+
+    _constructorInvocation(
+      node,
+      constructorName,
+      typeAliasElement.typeParameters,
+      constructorElement,
+      argumentList,
+      (typeArguments) {
+        return typeAliasElement.instantiate(
+          typeArguments: typeArguments,
+          nullabilitySuffix: _resolver.noneOrStarSuffix,
+        ) as InterfaceType;
+      },
+      whyNotPromotedList,
+    );
+  }
+
+  void _typeAliasGetter(
+    AnnotationImpl node,
+    TypeAliasElement typeAliasElement,
+    SimpleIdentifierImpl? getterName,
+    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
+  ) {
+    ExecutableElement? getter;
+    var aliasedType = typeAliasElement.aliasedType;
+    if (aliasedType is InterfaceType) {
+      var classElement = aliasedType.element;
+      if (getterName != null) {
+        getter = classElement.getGetter(getterName.name);
+        getter = _resolver.toLegacyElement(getter);
+      }
+    }
+
+    getterName?.staticElement = getter;
+    node.element = getter;
+
+    if (getterName != null && getter is PropertyAccessorElement) {
+      _propertyAccessorElement(node, getterName, getter, whyNotPromotedList);
+      _resolveAnnotationElementGetter(node, getter);
+    } else if (getter is! ConstructorElement) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.INVALID_ANNOTATION,
+        node,
+      );
+    }
+
+    _visitArguments(node, whyNotPromotedList);
+  }
+
   void _visitArguments(AnnotationImpl node,
       List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     var arguments = node.arguments;
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
index 65f17a2..4635774 100644
--- a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
@@ -40,6 +40,12 @@
 
   ConstructorElementToInfer(this.typeParameters, this.element);
 
+  /// Return the equivalent generic function type that we could use to
+  /// forward to the constructor, or for a non-generic type simply returns
+  /// the constructor type.
+  ///
+  /// For example given the type `class C<T> { C(T arg); }`, the generic
+  /// function type is `<T>(T) -> C<T>`.
   FunctionType get asType {
     return FunctionTypeImpl(
       typeFormals: typeParameters,
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 9ef5076..ead332f 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -4,13 +4,10 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
-import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/generated/migration.dart';
@@ -48,28 +45,6 @@
     _dynamicType = _typeProvider.dynamicType;
   }
 
-  /// Given a constructor for a generic type, returns the equivalent generic
-  /// function type that we could use to forward to the constructor, or for a
-  /// non-generic type simply returns the constructor type.
-  ///
-  /// For example given the type `class C<T> { C(T arg); }`, the generic function
-  /// type is `<T>(T) -> C<T>`.
-  FunctionType constructorToGenericFunctionType(
-      ConstructorElement constructor) {
-    var classElement = constructor.enclosingElement;
-    var typeParameters = classElement.typeParameters;
-    if (typeParameters.isEmpty) {
-      return constructor.type;
-    }
-
-    return FunctionTypeImpl(
-      typeFormals: typeParameters,
-      parameters: constructor.parameters,
-      returnType: constructor.returnType,
-      nullabilitySuffix: NullabilitySuffix.star,
-    );
-  }
-
   /// Record that the static type of the given node is the given type.
   ///
   /// @param expression the node whose type is to be recorded
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
index 53cdcc4..75e989e 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -149,6 +149,7 @@
     return result!;
   }
 
+  @override
   ParameterElement parameter(String name) {
     ParameterElement? result;
 
@@ -527,6 +528,28 @@
     throw StateError('Not found: $name');
   }
 
+  ParameterElement parameter(String name) {
+    ParameterElement? result;
+
+    for (var class_ in unitElement.types) {
+      for (var constructor in class_.constructors) {
+        for (var parameter in constructor.parameters) {
+          if (parameter.name == name) {
+            if (result != null) {
+              throw StateError('Not unique: $name');
+            }
+            result = parameter;
+          }
+        }
+      }
+    }
+
+    if (result != null) {
+      return result;
+    }
+    throw StateError('Not found: $name');
+  }
+
   PropertyAccessorElement setter(String name, {String? of}) {
     PropertyAccessorElement? result;
 
diff --git a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
index d96b3dc..75eaf41 100644
--- a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
@@ -2,6 +2,8 @@
 // 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.
 
+import 'dart:collection';
+
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -367,6 +369,38 @@
     );
   }
 
+  test_value_class_staticConstField() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  static const int foo = 42;
+}
+
+@A.foo
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@A');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  element: self::@class::A::@getter::foo
+  name: PrefixedIdentifier
+    identifier: SimpleIdentifier
+      staticElement: self::@class::A::@getter::foo
+      staticType: null
+      token: foo
+    period: .
+    prefix: SimpleIdentifier
+      staticElement: self::@class::A
+      staticType: null
+      token: A
+    staticElement: self::@class::A::@getter::foo
+    staticType: null
+''');
+    _assertAnnotationValueText(annotation, '''
+int 42
+''');
+  }
+
   test_value_class_unnamedConstructor() async {
     await assertNoErrorsInCode(r'''
  class A {
@@ -822,6 +856,819 @@
 ''');
   }
 
+  test_value_prefix_typeAlias_class_staticConstField() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class A {
+  static const int foo = 42;
+}
+
+typedef B = A;
+''');
+    await assertNoErrorsInCode(r'''
+import 'a.dart' as prefix;
+
+@prefix.B.foo
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@prefix.B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  constructorName: SimpleIdentifier
+    staticElement: package:test/a.dart::@class::A::@getter::foo
+    staticType: null
+    token: foo
+  element: package:test/a.dart::@class::A::@getter::foo
+  name: PrefixedIdentifier
+    identifier: SimpleIdentifier
+      staticElement: package:test/a.dart::@typeAlias::B
+      staticType: null
+      token: B
+    period: .
+    prefix: SimpleIdentifier
+      staticElement: self::@prefix::prefix
+      staticType: null
+      token: prefix
+    staticElement: package:test/a.dart::@typeAlias::B
+    staticType: null
+''');
+    _assertAnnotationValueText(annotation, '''
+int 42
+''');
+  }
+
+  test_value_prefix_typeAlias_generic_class_generic_all_inference_namedConstructor() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class A<T> {
+  final T f;
+  const A.named(this.f);
+}
+
+typedef B<U> = A<U>;
+''');
+    await assertNoErrorsInCode(r'''
+import 'a.dart' as prefix;
+
+@prefix.B.named(42)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@prefix.B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+  constructorName: SimpleIdentifier
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::A::@constructor::named
+      substitution: {T: int}
+    staticType: null
+    token: named
+  element: ConstructorMember
+    base: package:test/a.dart::@class::A::@constructor::named
+    substitution: {T: int}
+  name: PrefixedIdentifier
+    identifier: SimpleIdentifier
+      staticElement: package:test/a.dart::@typeAlias::B
+      staticType: null
+      token: B
+    period: .
+    prefix: SimpleIdentifier
+      staticElement: self::@prefix::prefix
+      staticType: null
+      token: prefix
+    staticElement: package:test/a.dart::@typeAlias::B
+    staticType: null
+''');
+    _assertAnnotationValueText(annotation, r'''
+A<int>
+  f: int 42
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.importFind('package:test/a.dart').parameter('f'),
+      substitution: {'T': 'int'},
+    );
+  }
+
+  test_value_prefix_typeAlias_generic_class_generic_all_inference_unnamedConstructor() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class A<T> {
+  final T f;
+  const A(this.f);
+}
+
+typedef B<U> = A<U>;
+''');
+    await assertNoErrorsInCode(r'''
+import 'a.dart' as prefix;
+
+@prefix.B(42)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@prefix.B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+  element: ConstructorMember
+    base: package:test/a.dart::@class::A::@constructor::•
+    substitution: {T: int}
+  name: PrefixedIdentifier
+    identifier: SimpleIdentifier
+      staticElement: package:test/a.dart::@typeAlias::B
+      staticType: null
+      token: B
+    period: .
+    prefix: SimpleIdentifier
+      staticElement: self::@prefix::prefix
+      staticType: null
+      token: prefix
+    staticElement: package:test/a.dart::@typeAlias::B
+    staticType: null
+''');
+    _assertAnnotationValueText(annotation, r'''
+A<int>
+  f: int 42
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.importFind('package:test/a.dart').parameter('f'),
+      substitution: {'T': 'int'},
+    );
+  }
+
+  test_value_prefix_typeAlias_generic_class_generic_all_typeArguments_namedConstructor() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class A<T> {
+  final T f;
+  const A.named(this.f);
+}
+
+typedef B<U> = A<U>;
+''');
+    await assertNoErrorsInCode(r'''
+import 'a.dart' as prefix;
+
+@prefix.B<int>.named(42)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@prefix.B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+  constructorName: SimpleIdentifier
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::A::@constructor::named
+      substitution: {T: int}
+    staticType: null
+    token: named
+  element: ConstructorMember
+    base: package:test/a.dart::@class::A::@constructor::named
+    substitution: {T: int}
+  name: PrefixedIdentifier
+    identifier: SimpleIdentifier
+      staticElement: package:test/a.dart::@typeAlias::B
+      staticType: null
+      token: B
+    period: .
+    prefix: SimpleIdentifier
+      staticElement: self::@prefix::prefix
+      staticType: null
+      token: prefix
+    staticElement: package:test/a.dart::@typeAlias::B
+    staticType: null
+  typeArguments: TypeArgumentList
+    arguments
+      TypeName
+        name: SimpleIdentifier
+          staticElement: dart:core::@class::int
+          staticType: null
+          token: int
+        type: int
+''');
+    _assertAnnotationValueText(annotation, r'''
+A<int>
+  f: int 42
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.importFind('package:test/a.dart').parameter('f'),
+      substitution: {'T': 'int'},
+    );
+  }
+
+  test_value_prefix_typeAlias_generic_class_generic_all_typeArguments_unnamedConstructor() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class A<T> {
+  final T f;
+  const A(this.f);
+}
+
+typedef B<U> = A<U>;
+''');
+    await assertNoErrorsInCode(r'''
+import 'a.dart' as prefix;
+
+@prefix.B<int>(42)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@prefix.B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+  element: ConstructorMember
+    base: package:test/a.dart::@class::A::@constructor::•
+    substitution: {T: int}
+  name: PrefixedIdentifier
+    identifier: SimpleIdentifier
+      staticElement: package:test/a.dart::@typeAlias::B
+      staticType: null
+      token: B
+    period: .
+    prefix: SimpleIdentifier
+      staticElement: self::@prefix::prefix
+      staticType: null
+      token: prefix
+    staticElement: package:test/a.dart::@typeAlias::B
+    staticType: null
+  typeArguments: TypeArgumentList
+    arguments
+      TypeName
+        name: SimpleIdentifier
+          staticElement: dart:core::@class::int
+          staticType: null
+          token: int
+        type: int
+''');
+    _assertAnnotationValueText(annotation, r'''
+A<int>
+  f: int 42
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.importFind('package:test/a.dart').parameter('f'),
+      substitution: {'T': 'int'},
+    );
+  }
+
+  test_value_typeAlias_class_staticConstField() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  static const int foo = 42;
+}
+
+typedef B = A;
+
+@B.foo
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  element: self::@class::A::@getter::foo
+  name: PrefixedIdentifier
+    identifier: SimpleIdentifier
+      staticElement: self::@class::A::@getter::foo
+      staticType: null
+      token: foo
+    period: .
+    prefix: SimpleIdentifier
+      staticElement: self::@typeAlias::B
+      staticType: null
+      token: B
+    staticElement: self::@class::A::@getter::foo
+    staticType: null
+''');
+    _assertAnnotationValueText(annotation, '''
+int 42
+''');
+  }
+
+  test_value_typeAlias_generic_class_generic_1of2_typeArguments_namedConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A<T, U> {
+  final T t;
+  final U u;
+  const A.named(this.t, this.u);
+}
+
+typedef B<T> = A<T, double>;
+
+@B<int>.named(42, 1.2)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+      DoubleLiteral
+        literal: 1.2
+        staticType: double
+  constructorName: SimpleIdentifier
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::named
+      substitution: {T: int, U: double}
+    staticType: null
+    token: named
+  element: ConstructorMember
+    base: self::@class::A::@constructor::named
+    substitution: {T: int, U: double}
+  name: SimpleIdentifier
+    staticElement: self::@typeAlias::B
+    staticType: null
+    token: B
+  typeArguments: TypeArgumentList
+    arguments
+      TypeName
+        name: SimpleIdentifier
+          staticElement: dart:core::@class::int
+          staticType: null
+          token: int
+        type: int
+''');
+    _assertAnnotationValueText(annotation, r'''
+A<int, double>
+  t: int 42
+  u: double 1.2
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.fieldFormalParameter('t'),
+      substitution: {'T': 'int', 'U': 'double'},
+    );
+
+    assertElement2(
+      findNode.doubleLiteral('1.2').staticParameterElement,
+      declaration: findElement.fieldFormalParameter('u'),
+      substitution: {'T': 'int', 'U': 'double'},
+    );
+  }
+
+  test_value_typeAlias_generic_class_generic_1of2_typeArguments_unnamedConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A<T, U> {
+  final T t;
+  final U u;
+  const A(this.t, this.u);
+}
+
+typedef B<T> = A<T, double>;
+
+@B<int>(42, 1.2)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+      DoubleLiteral
+        literal: 1.2
+        staticType: double
+  element: ConstructorMember
+    base: self::@class::A::@constructor::•
+    substitution: {T: int, U: double}
+  name: SimpleIdentifier
+    staticElement: self::@typeAlias::B
+    staticType: null
+    token: B
+  typeArguments: TypeArgumentList
+    arguments
+      TypeName
+        name: SimpleIdentifier
+          staticElement: dart:core::@class::int
+          staticType: null
+          token: int
+        type: int
+''');
+    _assertAnnotationValueText(annotation, r'''
+A<int, double>
+  t: int 42
+  u: double 1.2
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.fieldFormalParameter('t'),
+      substitution: {'T': 'int', 'U': 'double'},
+    );
+
+    assertElement2(
+      findNode.doubleLiteral('1.2').staticParameterElement,
+      declaration: findElement.fieldFormalParameter('u'),
+      substitution: {'T': 'int', 'U': 'double'},
+    );
+  }
+
+  test_value_typeAlias_generic_class_generic_all_inference_namedConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  final T f;
+  const A.named(this.f);
+}
+
+typedef B<U> = A<U>;
+
+@B.named(42)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+  element: ConstructorMember
+    base: self::@class::A::@constructor::named
+    substitution: {T: int}
+  name: PrefixedIdentifier
+    identifier: SimpleIdentifier
+      staticElement: ConstructorMember
+        base: self::@class::A::@constructor::named
+        substitution: {T: int}
+      staticType: null
+      token: named
+    period: .
+    prefix: SimpleIdentifier
+      staticElement: self::@typeAlias::B
+      staticType: null
+      token: B
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::named
+      substitution: {T: int}
+    staticType: null
+''');
+    _assertAnnotationValueText(annotation, r'''
+A<int>
+  f: int 42
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.fieldFormalParameter('f'),
+      substitution: {'T': 'int'},
+    );
+  }
+
+  test_value_typeAlias_generic_class_generic_all_inference_unnamedConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  final T f;
+  const A(this.f);
+}
+
+typedef B<U> = A<U>;
+
+@B(42)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+  element: ConstructorMember
+    base: self::@class::A::@constructor::•
+    substitution: {T: int}
+  name: SimpleIdentifier
+    staticElement: self::@typeAlias::B
+    staticType: null
+    token: B
+''');
+    _assertAnnotationValueText(annotation, r'''
+A<int>
+  f: int 42
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.fieldFormalParameter('f'),
+      substitution: {'T': 'int'},
+    );
+  }
+
+  test_value_typeAlias_generic_class_generic_all_typeArguments_namedConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  final T f;
+  const A.named(this.f);
+}
+
+typedef B<U> = A<U>;
+
+@B<int>.named(42)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+  constructorName: SimpleIdentifier
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::named
+      substitution: {T: int}
+    staticType: null
+    token: named
+  element: ConstructorMember
+    base: self::@class::A::@constructor::named
+    substitution: {T: int}
+  name: SimpleIdentifier
+    staticElement: self::@typeAlias::B
+    staticType: null
+    token: B
+  typeArguments: TypeArgumentList
+    arguments
+      TypeName
+        name: SimpleIdentifier
+          staticElement: dart:core::@class::int
+          staticType: null
+          token: int
+        type: int
+''');
+    _assertAnnotationValueText(annotation, r'''
+A<int>
+  f: int 42
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.fieldFormalParameter('f'),
+      substitution: {'T': 'int'},
+    );
+  }
+
+  test_value_typeAlias_generic_class_generic_all_typeArguments_unnamedConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  final T f;
+  const A(this.f);
+}
+
+typedef B<U> = A<U>;
+
+@B<int>(42)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+  element: ConstructorMember
+    base: self::@class::A::@constructor::•
+    substitution: {T: int}
+  name: SimpleIdentifier
+    staticElement: self::@typeAlias::B
+    staticType: null
+    token: B
+  typeArguments: TypeArgumentList
+    arguments
+      TypeName
+        name: SimpleIdentifier
+          staticElement: dart:core::@class::int
+          staticType: null
+          token: int
+        type: int
+''');
+    _assertAnnotationValueText(annotation, r'''
+A<int>
+  f: int 42
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.fieldFormalParameter('f'),
+      substitution: {'T': 'int'},
+    );
+  }
+
+  test_value_typeAlias_notGeneric_class_generic_namedConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  final T f;
+  const A.named(this.f);
+}
+
+typedef B = A<int>;
+
+@B.named(42)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+  element: ConstructorMember
+    base: self::@class::A::@constructor::named
+    substitution: {T: int}
+  name: PrefixedIdentifier
+    identifier: SimpleIdentifier
+      staticElement: ConstructorMember
+        base: self::@class::A::@constructor::named
+        substitution: {T: int}
+      staticType: null
+      token: named
+    period: .
+    prefix: SimpleIdentifier
+      staticElement: self::@typeAlias::B
+      staticType: null
+      token: B
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::named
+      substitution: {T: int}
+    staticType: null
+''');
+    _assertAnnotationValueText(annotation, r'''
+A<int>
+  f: int 42
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.fieldFormalParameter('f'),
+      substitution: {'T': 'int'},
+    );
+  }
+
+  test_value_typeAlias_notGeneric_class_generic_unnamedConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  final T f;
+  const A(this.f);
+}
+
+typedef B = A<int>;
+
+@B(42)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+  element: ConstructorMember
+    base: self::@class::A::@constructor::•
+    substitution: {T: int}
+  name: SimpleIdentifier
+    staticElement: self::@typeAlias::B
+    staticType: null
+    token: B
+''');
+    _assertAnnotationValueText(annotation, r'''
+A<int>
+  f: int 42
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.fieldFormalParameter('f'),
+      substitution: {'T': 'int'},
+    );
+  }
+
+  test_value_typeAlias_notGeneric_class_notGeneric_namedConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  final int f;
+  const A.named(this.f);
+}
+
+typedef B = A;
+
+@B.named(42)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+  element: self::@class::A::@constructor::named
+  name: PrefixedIdentifier
+    identifier: SimpleIdentifier
+      staticElement: self::@class::A::@constructor::named
+      staticType: null
+      token: named
+    period: .
+    prefix: SimpleIdentifier
+      staticElement: self::@typeAlias::B
+      staticType: null
+      token: B
+    staticElement: self::@class::A::@constructor::named
+    staticType: null
+''');
+    _assertAnnotationValueText(annotation, r'''
+A
+  f: int 42
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.fieldFormalParameter('f'),
+    );
+  }
+
+  test_value_typeAlias_notGeneric_class_notGeneric_unnamedConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  final int f;
+  const A(this.f);
+}
+
+typedef B = A;
+
+@B(42)
+void f() {}
+''');
+
+    var annotation = findNode.annotation('@B');
+    _assertResolvedNodeText(annotation, r'''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 42
+        staticType: int
+  element: self::@class::A::@constructor::•
+  name: SimpleIdentifier
+    staticElement: self::@typeAlias::B
+    staticType: null
+    token: B
+''');
+    _assertAnnotationValueText(annotation, r'''
+A
+  f: int 42
+''');
+
+    assertElement2(
+      findNode.integerLiteral('42').staticParameterElement,
+      declaration: findElement.fieldFormalParameter('f'),
+    );
+  }
+
   void _assertAnnotationValueText(Annotation annotation, String expected) {
     var elementAnnotation = annotation.elementAnnotation!;
     _assertElementAnnotationValueText(elementAnnotation, expected);
@@ -874,7 +1721,10 @@
   void write(DartObjectImpl? object, String indent) {
     if (object != null) {
       var type = object.type;
-      if (type.isDartCoreInt) {
+      if (type.isDartCoreDouble) {
+        sink.write('double ');
+        sink.writeln(object.toDoubleValue());
+      } else if (type.isDartCoreInt) {
         sink.write('int ');
         sink.writeln(object.toIntValue());
       } else if (object.isUserDefinedObject) {
@@ -883,7 +1733,8 @@
         sink.writeln(typeStr);
         var fields = object.fields;
         if (fields != null) {
-          for (var entry in fields.entries) {
+          var sortedFields = SplayTreeMap.of(fields);
+          for (var entry in sortedFields.entries) {
             sink.write(newIndent);
             sink.write('${entry.key}: ');
             write(entry.value, newIndent);
diff --git a/pkg/test_runner/lib/src/static_error.dart b/pkg/test_runner/lib/src/static_error.dart
index a24aad6..8252dc5 100644
--- a/pkg/test_runner/lib/src/static_error.dart
+++ b/pkg/test_runner/lib/src/static_error.dart
@@ -490,7 +490,12 @@
   /// For errors that have a number associated with them, tracks that number.
   ///
   /// These are used after parsing to attach context messages to their errors.
-  final Map<StaticError, int> _errorNumbers = {};
+  ///
+  /// Note: if the same context message appears multiple times at the same
+  /// location, there will be distinct (non-identical) StaticError instances
+  /// that compare equal.  We use `Map.identity` to ensure that we can associate
+  /// each with its own context number.
+  final Map<StaticError, int> _errorNumbers = Map.identity();
 
   int _currentLine = 0;
 
diff --git a/pkg/test_runner/lib/src/update_errors.dart b/pkg/test_runner/lib/src/update_errors.dart
index 0023b02..7ef97fe 100644
--- a/pkg/test_runner/lib/src/update_errors.dart
+++ b/pkg/test_runner/lib/src/update_errors.dart
@@ -174,7 +174,11 @@
 /// Assigns unique numbers to all [errors] that have context messages, as well
 /// as their context messages.
 Map<StaticError, int> _numberErrors(List<StaticError> errors) {
-  var result = <StaticError, int>{};
+  // Note: if the same context message appears multiple times at the same
+  // location, there will be distinct (non-identical) StaticError instances
+  // that compare equal.  We use `Map.identity` to ensure that we can associate
+  // each with its own context number.
+  var result = Map<StaticError, int>.identity();
   var number = 1;
   for (var error in errors) {
     if (error.contextMessages.isEmpty) continue;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index e82c80d..bbe41e4 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -5976,23 +5976,24 @@
   if (num_types <= kNullabilityMaxTypes) {
     AbstractType& type = AbstractType::Handle();
     for (intptr_t i = 0; i < num_types; i++) {
-      result <<= kNullabilityBitsPerType;
       type = TypeAt(i);
+      intptr_t type_bits = 0;
       if (!type.IsNull() && !type.IsNullTypeRef()) {
         switch (type.nullability()) {
           case Nullability::kNullable:
-            result |= kNullableBits;
+            type_bits = kNullableBits;
             break;
           case Nullability::kNonNullable:
-            result |= kNonNullableBits;
+            type_bits = kNonNullableBits;
             break;
           case Nullability::kLegacy:
-            result |= kLegacyBits;
+            type_bits = kLegacyBits;
             break;
           default:
             UNREACHABLE();
         }
       }
+      result |= (type_bits << (i * kNullabilityBitsPerType));
     }
   }
   set_nullability(result);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 6a4b5bb..259e3df 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -7368,10 +7368,12 @@
   // 2 bits per type:
   //  - the high bit is set if the type is nullable or legacy.
   //  - the low bit is set if the type is nullable.
-  // The nullabilty is 0 if the vector is longer than kNullabilityMaxTypes.
+  // The nullability is 0 if the vector is longer than kNullabilityMaxTypes.
   // The condition evaluated at runtime to decide whether UTA can share ITA is
   //   (UTA.nullability & ITA.nullability) == UTA.nullability
-  // Note that this allows for ITA to be longer than UTA.
+  // Note that this allows for ITA to be longer than UTA (the bit vector must be
+  // stored in the same order as the corresponding type vector, i.e. with the
+  // least significant 2 bits representing the nullability of the first type).
   static const intptr_t kNullabilityBitsPerType = 2;
   static const intptr_t kNullabilityMaxTypes =
       kSmiBits / kNullabilityBitsPerType;
diff --git a/tests/language/regress/regress45529_test.dart b/tests/language/regress/regress45529_test.dart
new file mode 100644
index 0000000..6cd4ed2
--- /dev/null
+++ b/tests/language/regress/regress45529_test.dart
@@ -0,0 +1,24 @@
+// 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.
+
+import "package:expect/expect.dart";
+
+void main() {
+  final baz = Foo<Null>().baz;
+  Expect.equals("Baz<Bar<Null>?>", baz.runtimeType.toString());
+  baz.v = baz.v;
+}
+
+class Bar<T> {}
+
+class Foo<T> extends Quux<Bar<T>> {}
+
+class Baz<T> {
+  Baz(this.v);
+  T v;
+}
+
+class Quux<T> {
+  final baz = Baz<T?>(null);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 079095e..27132aa 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 188
+PRERELEASE 189
 PRERELEASE_PATCH 0
\ No newline at end of file