Version 2.15.0-143.0.dev

Merge commit '6459e73570a441bd8da3282097219df5c9e38c76' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 69105f8..670e73a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -80,7 +80,7 @@
 /// TODO(scheglov) Clean up the list of implicitly analyzed files.
 class AnalysisDriver implements AnalysisDriverGeneric {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 178;
+  static const int DATA_VERSION = 179;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/dart/error/ffi_code.dart b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
index c84bfad..8896d3e 100644
--- a/pkg/analyzer/lib/src/dart/error/ffi_code.dart
+++ b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
@@ -252,7 +252,7 @@
    * No parameters.
    */
   static const FfiCode NON_POSITIVE_ARRAY_DIMENSION = FfiCode(
-      name: 'NON_POSITIVE_INPUT_ON_ARRAY',
+      name: 'NON_POSITIVE_ARRAY_DIMENSION',
       message: "Array dimensions must be positive numbers.",
       correction: "Try changing the input to a positive number.");
 
diff --git a/pkg/analyzer/lib/src/dart/error/todo_codes.dart b/pkg/analyzer/lib/src/dart/error/todo_codes.dart
index 6b3d5c9..e1f955a 100644
--- a/pkg/analyzer/lib/src/dart/error/todo_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/todo_codes.dart
@@ -8,6 +8,51 @@
 // _documentation comment_ when each is written as an end-of-line comment.
 // ignore_for_file: slash_for_doc_comments
 
+/// Static helper methods and properties for working with [TodoCode]s.
+class Todo {
+  static const _codes = {
+    'TODO': TodoCode.TODO,
+    'FIXME': TodoCode.FIXME,
+    'HACK': TodoCode.HACK,
+    'UNDONE': TodoCode.UNDONE,
+  };
+
+  /// This matches the two common Dart task styles
+  ///
+  /// * TODO:
+  /// * TODO(username):
+  ///
+  /// As well as
+  /// * TODO
+  ///
+  /// But not
+  /// * todo
+  /// * TODOS
+  ///
+  /// It also supports wrapped TODOs where the next line is indented by a space:
+  ///
+  ///   /**
+  ///    * TODO(username): This line is
+  ///    *  wrapped onto the next line
+  ///    */
+  ///
+  /// The matched kind of the TODO (TODO, FIXME, etc.) is returned in named
+  /// captures of "kind1", "kind2" (since it is not possible to reuse a name
+  /// across different parts of the regex).
+  static RegExp TODO_REGEX = RegExp(
+      '([\\s/\\*])(((?<kind1>$_TODO_KIND_PATTERN)[^\\w\\d][^\\r\\n]*(?:\\n\\s*\\*  [^\\r\\n]*)*)'
+      '|((?<kind2>$_TODO_KIND_PATTERN):?\$))');
+
+  static final _TODO_KIND_PATTERN = _codes.keys.join('|');
+
+  Todo._() {
+    throw UnimplementedError('Do not construct');
+  }
+
+  /// Returns the TodoCode for [kind], falling back to [TodoCode.TODO].
+  static TodoCode forKind(String kind) => _codes[kind] ?? TodoCode.TODO;
+}
+
 /**
  * The error code indicating a marker in code for work that needs to be finished
  * or revisited.
@@ -33,43 +78,6 @@
    */
   static const TodoCode UNDONE = TodoCode('UNDONE');
 
-  static const _codes = {
-    'TODO': TODO,
-    'FIXME': FIXME,
-    'HACK': HACK,
-    'UNDONE': UNDONE,
-  };
-
-  /**
-   * This matches the two common Dart task styles
-   *
-   * * TODO:
-   * * TODO(username):
-   *
-   * As well as
-   * * TODO
-   *
-   * But not
-   * * todo
-   * * TODOS
-   *
-   * It also supports wrapped TODOs where the next line is indented by a space:
-   *
-   *   /**
-   *    * TODO(username): This line is
-   *    *  wrapped onto the next line
-   *    */
-   *
-   * The matched kind of the TODO (TODO, FIXME, etc.) is returned in named
-   * captures of "kind1", "kind2" (since it is not possible to reuse a name
-   * across different parts of the regex).
-   */
-  static RegExp TODO_REGEX = RegExp(
-      '([\\s/\\*])(((?<kind1>$_TODO_KIND_PATTERN)[^\\w\\d][^\\r\\n]*(?:\\n\\s*\\*  [^\\r\\n]*)*)'
-      '|((?<kind2>$_TODO_KIND_PATTERN):?\$))');
-
-  static final _TODO_KIND_PATTERN = _codes.keys.join('|');
-
   /**
    * Initialize a newly created error code to have the given [name].
    */
@@ -85,7 +93,4 @@
 
   @override
   ErrorType get type => ErrorType.TODO;
-
-  /// Returns the TodoCode for [kind], falling back to [TODO].
-  static TodoCode forKind(String kind) => _codes[kind] ?? TODO;
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart b/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
index d8138bc..1b78dc9 100644
--- a/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
@@ -225,24 +225,27 @@
   /// The [PrefixedIdentifier] may need to be rewritten as a
   /// [ConstructorReference].
   AstNode prefixedIdentifier(Scope nameScope, PrefixedIdentifier node) {
-    if (node.parent is Annotation) {
+    var parent = node.parent;
+    if (parent is Annotation) {
       // An annotations which is a const constructor invocation can initially be
       // represented with a [PrefixedIdentifier]. Do not rewrite such nodes.
       return node;
     }
-    if (node.parent is CommentReference) {
+    if (parent is CommentReference) {
       // TODO(srawlins): This probably should be rewritten to a
       // [ConstructorReference] at some point.
       return node;
     }
+    if (parent is AssignmentExpression && parent.leftHandSide == node) {
+      // A constructor cannot be assigned to, in some expression like
+      // `C.new = foo`; do not rewrite.
+      return node;
+    }
     var identifier = node.identifier;
     if (identifier.isSynthetic) {
       // This isn't a constructor reference.
       return node;
     }
-    if (node.parent is AssignmentExpression) {
-      return node;
-    }
     var prefix = node.prefix;
     var element = nameScope.lookup(prefix.name).getter;
     if (element is ClassElement) {
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 6427f89..966655d 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -5088,7 +5088,7 @@
         "others aren't.",
     correction: "Try adding initializers for the fields.",
     hasPublishedDocs: true,
-    uniqueName: 'FINAL_NOT_INITIALIZED_CONSTRUCTOR_3',
+    uniqueName: 'FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS',
   );
 
   /**
@@ -9069,7 +9069,7 @@
    */
   static const CompileTimeErrorCode NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS =
       CompileTimeErrorCode(
-          'NO_GENERATIVE_CONSTRUCTOR_IN_SUPERCLASS',
+          'NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS',
           "The class '{0}' cannot extend '{1}' because '{1}' only has factory "
               "constructors (no generative constructors), and '{0}' has at "
               "least one generative constructor.",
diff --git a/pkg/analyzer/lib/src/error/todo_finder.dart b/pkg/analyzer/lib/src/error/todo_finder.dart
index cbb1d38..e6a4df3 100644
--- a/pkg/analyzer/lib/src/error/todo_finder.dart
+++ b/pkg/analyzer/lib/src/error/todo_finder.dart
@@ -66,7 +66,7 @@
   /// any continuations).
   Token? _scrapeTodoComment(Token commentToken, LineInfo lineInfo) {
     Iterable<RegExpMatch> matches =
-        TodoCode.TODO_REGEX.allMatches(commentToken.lexeme);
+        Todo.TODO_REGEX.allMatches(commentToken.lexeme);
     // Track the comment that will be returned for looking for the next todo.
     // This will be moved along if additional comments are consumed by multiline
     // TODOs.
@@ -110,7 +110,7 @@
                   // And indented more than the original 'todo' text.
                   columnOfFirstNoneMarkerOrWhitespace == column + 1 &&
                   // And not their own todos.
-                  !TodoCode.TODO_REGEX.hasMatch(nextComment.lexeme);
+                  !Todo.TODO_REGEX.hasMatch(nextComment.lexeme);
           if (!isContinuation) {
             break;
           }
@@ -127,7 +127,7 @@
       }
 
       _errorReporter.reportErrorForOffset(
-          TodoCode.forKind(todoKind), offset, end - offset, [todoText]);
+          Todo.forKind(todoKind), offset, end - offset, [todoText]);
     }
 
     return nextComment;
diff --git a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
index 8a4401f..f5e1dd3 100644
--- a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
@@ -14,6 +14,14 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AstRewriteMethodInvocationTest);
+    defineReflectiveTests(AstRewritePrefixedIdentifierTest);
+
+    // TODO(srawlins): Add AstRewriteInstanceCreationExpressionTest test, likely
+    // moving many test cases from ConstructorReferenceResolutionTest,
+    // FunctionReferenceResolutionTest, and TypeLiteralResolutionTest.
+    // TODO(srawlins): Add AstRewritePropertyAccessTest test, likely
+    // moving many test cases from ConstructorReferenceResolutionTest,
+    // FunctionReferenceResolutionTest, and TypeLiteralResolutionTest.
   });
 }
 
@@ -484,3 +492,43 @@
     expect(argumentStrings, expectedArguments);
   }
 }
+
+@reflectiveTest
+class AstRewritePrefixedIdentifierTest extends PubPackageResolutionTest {
+  test_constructorReference_inAssignment_onLeftSide() async {
+    await assertErrorsInCode('''
+class C {}
+
+void f() {
+  C.new = 1;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_SETTER, 27, 3),
+    ]);
+
+    var identifier = findNode.prefixed('C.new');
+    // The left side of the assignment is resolved by
+    // [PropertyElementResolver._resolveTargetClassElement], which looks for
+    // getters and setters on `C`, and does not recover with other elements
+    // (methods, constructors). This prefixed identifier can have a real
+    // `staticElement` if we add such recovery.
+    assertElement(identifier, null);
+  }
+
+  test_constructorReference_inAssignment_onRightSide() async {
+    await assertNoErrorsInCode('''
+class C {}
+
+Function? f;
+void g() {
+  f = C.new;
+}
+''');
+
+    var identifier = findNode.constructorReference('C.new');
+    assertElement(identifier, findElement.unnamedConstructor('C'));
+  }
+
+  // TODO(srawlins): Complete tests of all cases of rewriting (or not) a
+  // prefixed identifier.
+}
diff --git a/pkg/telemetry/pubspec.yaml b/pkg/telemetry/pubspec.yaml
index b5b6b30..2ceeac0 100644
--- a/pkg/telemetry/pubspec.yaml
+++ b/pkg/telemetry/pubspec.yaml
@@ -12,7 +12,7 @@
     path: ../meta
   path: ^1.4.0
   stack_trace: ^1.7.0
-  usage: ^3.2.0+1
+  usage: ^4.0.0
 
 dev_dependencies:
   test: ^1.0.0
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 514f04e..e9ed8fb 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -6837,7 +6837,7 @@
     intptr_t num_free_fun_type_params,
     Heap::Space space,
     TrailPtr trail) const {
-  ASSERT(!IsInstantiated(kAny, num_free_fun_type_params));
+  ASSERT(!IsInstantiated());
   if ((instantiator_type_arguments.IsNull() ||
        instantiator_type_arguments.Length() == Length()) &&
       IsUninstantiatedIdentity()) {
@@ -6855,8 +6855,7 @@
     // during finalization of V, which is also the instantiator. T depends
     // solely on the type parameters of A and will be replaced by a non-null
     // type before A is marked as finalized.
-    if (!type.IsNull() &&
-        !type.IsInstantiated(kAny, num_free_fun_type_params)) {
+    if (!type.IsNull() && !type.IsInstantiated()) {
       type = type.InstantiateFrom(instantiator_type_arguments,
                                   function_type_arguments,
                                   num_free_fun_type_params, space, trail);
@@ -8771,16 +8770,14 @@
       sig_type_params.set_flags(Array::Handle(zone, type_params.flags()));
       TypeArguments& type_args = TypeArguments::Handle(zone);
       type_args = type_params.bounds();
-      if (!type_args.IsNull() &&
-          !type_args.IsInstantiated(kAny, num_free_fun_type_params)) {
+      if (!type_args.IsNull() && !type_args.IsInstantiated()) {
         type_args = type_args.InstantiateFrom(
             instantiator_type_arguments, function_type_arguments,
             num_free_fun_type_params, space, trail);
       }
       sig_type_params.set_bounds(type_args);
       type_args = type_params.defaults();
-      if (!type_args.IsNull() &&
-          !type_args.IsInstantiated(kAny, num_free_fun_type_params)) {
+      if (!type_args.IsNull() && !type_args.IsInstantiated()) {
         type_args = type_args.InstantiateFrom(
             instantiator_type_arguments, function_type_arguments,
             num_free_fun_type_params, space, trail);
@@ -8791,7 +8788,7 @@
   }
 
   type = result_type();
-  if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
+  if (!type.IsInstantiated()) {
     type = type.InstantiateFrom(instantiator_type_arguments,
                                 function_type_arguments,
                                 num_free_fun_type_params, space, trail);
@@ -8810,7 +8807,7 @@
   sig.set_parameter_types(Array::Handle(Array::New(num_params, space)));
   for (intptr_t i = 0; i < num_params; i++) {
     type = ParameterTypeAt(i);
-    if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
+    if (!type.IsInstantiated()) {
       type = type.InstantiateFrom(instantiator_type_arguments,
                                   function_type_arguments,
                                   num_free_fun_type_params, space, trail);
@@ -21799,16 +21796,11 @@
     if (!other_type_param.IsFunctionTypeParameter()) {
       return false;
     }
+    if (base() != other_type_param.base() ||
+        index() != other_type_param.index()) {
+      return false;
+    }
     if (kind == TypeEquality::kInSubtypeTest) {
-      // To be equivalent, the function type parameters should be declared
-      // at the same position in the generic function. Their index therefore
-      // needs adjustment before comparison.
-      // Example: 'foo<F>(bar<B>(B b)) { }' and 'baz<Z>(Z z) { }', baz can
-      // be assigned to bar, although B has index 1 and Z index 0.
-      if (index() - base() !=
-          other_type_param.index() - other_type_param.base()) {
-        return false;
-      }
       AbstractType& upper_bound = AbstractType::Handle(bound());
       AbstractType& other_type_param_upper_bound =
           AbstractType::Handle(other_type_param.bound());
@@ -21822,10 +21814,6 @@
         return false;
       }
     } else {
-      if (base() != other_type_param.base() ||
-          index() != other_type_param.index()) {
-        return false;
-      }
       AbstractType& type = AbstractType::Handle(bound());
       AbstractType& other_type = AbstractType::Handle(other_type_param.bound());
       if (!type.IsEquivalent(other_type, kind, trail)) {
@@ -21956,22 +21944,26 @@
     ASSERT(IsFinalized());
     if (index() >= num_free_fun_type_params) {
       // Do not instantiate the function type parameter, but possibly its bound.
+      // Also adjust index/base of the type parameter.
       result = ptr();
       AbstractType& upper_bound = AbstractType::Handle(bound());
-      if (!upper_bound.IsInstantiated(kAny, num_free_fun_type_params,
-                                      nullptr)) {
+      if (!upper_bound.IsInstantiated()) {
         upper_bound = upper_bound.InstantiateFrom(
             instantiator_type_arguments, function_type_arguments,
             num_free_fun_type_params, space, trail);
-        if ((upper_bound.IsTypeRef() &&
-             TypeRef::Cast(upper_bound).type() == Type::NeverType()) ||
-            (upper_bound.ptr() == Type::NeverType())) {
-          // Normalize 'X extends Never' to 'Never'.
-          result = Type::NeverType();
-        } else if (upper_bound.ptr() != bound()) {
-          result ^= Object::Clone(result, space);
-          TypeParameter::Cast(result).set_bound(upper_bound);
-        }
+      }
+      if ((upper_bound.IsTypeRef() &&
+           TypeRef::Cast(upper_bound).type() == Type::NeverType()) ||
+          (upper_bound.ptr() == Type::NeverType())) {
+        // Normalize 'X extends Never' to 'Never'.
+        result = Type::NeverType();
+      } else if ((upper_bound.ptr() != bound()) ||
+                 (num_free_fun_type_params != 0)) {
+        result ^= Object::Clone(result, space);
+        const auto& tp = TypeParameter::Cast(result);
+        tp.set_bound(upper_bound);
+        tp.set_base(tp.base() - num_free_fun_type_params);
+        tp.set_index(tp.index() - num_free_fun_type_params);
       }
     } else if (function_type_arguments.IsNull()) {
       return Type::DynamicType();
@@ -25522,8 +25514,7 @@
   } else {
     num_free_params = kAllFree;
   }
-  if (num_free_params == kCurrentAndEnclosingFree ||
-      !sig.IsInstantiated(kAny)) {
+  if (num_free_params == kCurrentAndEnclosingFree || !sig.IsInstantiated()) {
     sig ^= sig.InstantiateFrom(inst_type_args, fn_type_args, num_free_params,
                                Heap::kOld);
   }
diff --git a/tools/VERSION b/tools/VERSION
index 84ea1f9..cb88287 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 142
+PRERELEASE 143
 PRERELEASE_PATCH 0
\ No newline at end of file