Version 2.15.0-153.0.dev

Merge commit '7176311597509d456557c10e26066c4386c9eb8f' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b76d62e..036e134 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -268,6 +268,11 @@
 
 ### Core libraries
 
+#### `dart:async`
+
+- Make the `unawaited` function's argument nullable, to allow calls like
+  `unawaited(foo?.bar())` too.
+
 #### `dart:cli`
 
 - The experimental `waitFor` functionality, and the library containing only that
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 9a4f218..26fdf2b 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -1507,6 +1507,11 @@
     );
   }
 
+  @override
+  DartObjectImpl? visitTypeLiteral(TypeLiteral node) {
+    return node.type.accept(this);
+  }
+
   /// Add the entries produced by evaluating the given collection [element] to
   /// the given [list]. Return `true` if the evaluation of one or more of the
   /// elements failed.
@@ -1716,7 +1721,7 @@
     } else if (variableElement is TypeAliasElement) {
       var type = variableElement.instantiate(
         typeArguments: variableElement.typeParameters
-            .map((t) => _typeProvider.dynamicType)
+            .map((t) => t.bound ?? _typeProvider.dynamicType)
             .toList(),
         nullabilitySuffix: NullabilitySuffix.star,
       );
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 43707ea..af7d2b2 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -2486,7 +2486,7 @@
   /**
    * No parameters.
    */
-  /* // #### Description
+  // #### Description
   //
   // The analyzer produces this diagnostic when the operator `>>>` is used in
   // code that has an SDK constraint whose lower bound is less than 2.X.0. This
@@ -2534,7 +2534,7 @@
   //   }
   //   return leftOperand ~/ divisor;
   // }
-  // ``` */
+  // ```
   static const HintCode SDK_VERSION_GT_GT_GT_OPERATOR = HintCode(
       'SDK_VERSION_GT_GT_GT_OPERATOR',
       "The operator '>>>' wasn't supported until version 2.3.2, but this code "
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index d498abb..ed43512 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -130,555 +130,553 @@
 
 const ParserErrorCode _ABSTRACT_CLASS_MEMBER = ParserErrorCode(
     'ABSTRACT_CLASS_MEMBER',
-    r"Members of classes can't be declared to be 'abstract'.",
+    "Members of classes can't be declared to be 'abstract'.",
     correction:
         "Try removing the 'abstract' keyword. You can add the 'abstract' keyword before the class declaration.");
 
 const ParserErrorCode _ABSTRACT_EXTERNAL_FIELD = ParserErrorCode(
     'ABSTRACT_EXTERNAL_FIELD',
-    r"Fields can't be declared both 'abstract' and 'external'.",
+    "Fields can't be declared both 'abstract' and 'external'.",
     correction: "Try removing the 'abstract' or 'external' keyword.");
 
 const ParserErrorCode _ABSTRACT_LATE_FIELD = ParserErrorCode(
-    'ABSTRACT_LATE_FIELD', r"Abstract fields cannot be late.",
+    'ABSTRACT_LATE_FIELD', "Abstract fields cannot be late.",
     correction: "Try removing the 'abstract' or 'late' keyword.");
 
 const ParserErrorCode _ABSTRACT_STATIC_FIELD = ParserErrorCode(
-    'ABSTRACT_STATIC_FIELD', r"Static fields can't be declared 'abstract'.",
+    'ABSTRACT_STATIC_FIELD', "Static fields can't be declared 'abstract'.",
     correction: "Try removing the 'abstract' or 'static' keyword.");
 
 const ParserErrorCode _ANNOTATION_ON_TYPE_ARGUMENT = ParserErrorCode(
     'ANNOTATION_ON_TYPE_ARGUMENT',
-    r"Type arguments can't have annotations because they aren't declarations.");
+    "Type arguments can't have annotations because they aren't declarations.");
 
 const ParserErrorCode _ANNOTATION_WITH_TYPE_ARGUMENTS = ParserErrorCode(
     'ANNOTATION_WITH_TYPE_ARGUMENTS',
-    r"An annotation can't use type arguments.");
+    "An annotation can't use type arguments.");
 
 const ParserErrorCode _ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED =
     ParserErrorCode('ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED',
-        r"An annotation with type arguments must be followed by an argument list.");
+        "An annotation with type arguments must be followed by an argument list.");
 
 const ParserErrorCode _BINARY_OPERATOR_WRITTEN_OUT = ParserErrorCode(
     'BINARY_OPERATOR_WRITTEN_OUT',
-    r"Binary operator '{0}' is written as '{1}' instead of the written out word.",
+    "Binary operator '{0}' is written as '{1}' instead of the written out word.",
     correction: "Try replacing '{0}' with '{1}'.");
 
 const ParserErrorCode _BREAK_OUTSIDE_OF_LOOP = ParserErrorCode(
     'BREAK_OUTSIDE_OF_LOOP',
-    r"A break statement can't be used outside of a loop or switch statement.",
+    "A break statement can't be used outside of a loop or switch statement.",
     correction: "Try removing the break statement.");
 
 const ParserErrorCode _CATCH_SYNTAX = ParserErrorCode('CATCH_SYNTAX',
-    r"'catch' must be followed by '(identifier)' or '(identifier, identifier)'.",
+    "'catch' must be followed by '(identifier)' or '(identifier, identifier)'.",
     correction:
         "No types are needed, the first is given by 'on', the second is always 'StackTrace'.");
 
 const ParserErrorCode _CATCH_SYNTAX_EXTRA_PARAMETERS = ParserErrorCode(
     'CATCH_SYNTAX_EXTRA_PARAMETERS',
-    r"'catch' must be followed by '(identifier)' or '(identifier, identifier)'.",
+    "'catch' must be followed by '(identifier)' or '(identifier, identifier)'.",
     correction:
         "No types are needed, the first is given by 'on', the second is always 'StackTrace'.");
 
 const ParserErrorCode _CLASS_IN_CLASS = ParserErrorCode(
-    'CLASS_IN_CLASS', r"Classes can't be declared inside other classes.",
+    'CLASS_IN_CLASS', "Classes can't be declared inside other classes.",
     correction: "Try moving the class to the top-level.");
 
 const ParserErrorCode _COLON_IN_PLACE_OF_IN = ParserErrorCode(
-    'COLON_IN_PLACE_OF_IN', r"For-in loops use 'in' rather than a colon.",
+    'COLON_IN_PLACE_OF_IN', "For-in loops use 'in' rather than a colon.",
     correction: "Try replacing the colon with the keyword 'in'.");
 
 const ParserErrorCode _CONFLICTING_MODIFIERS = ParserErrorCode(
     'CONFLICTING_MODIFIERS',
-    r"Members can't be declared to be both '{0}' and '{1}'.",
+    "Members can't be declared to be both '{0}' and '{1}'.",
     correction: "Try removing one of the keywords.");
 
 const ParserErrorCode _CONSTRUCTOR_WITH_RETURN_TYPE = ParserErrorCode(
-    'CONSTRUCTOR_WITH_RETURN_TYPE', r"Constructors can't have a return type.",
+    'CONSTRUCTOR_WITH_RETURN_TYPE', "Constructors can't have a return type.",
     correction: "Try removing the return type.");
 
 const ParserErrorCode _CONSTRUCTOR_WITH_TYPE_ARGUMENTS = ParserErrorCode(
     'CONSTRUCTOR_WITH_TYPE_ARGUMENTS',
-    r"A constructor invocation can't have type arguments after the constructor name.",
+    "A constructor invocation can't have type arguments after the constructor name.",
     correction:
         "Try removing the type arguments or placing them after the class name.");
 
 const ParserErrorCode _CONST_AND_FINAL = ParserErrorCode('CONST_AND_FINAL',
-    r"Members can't be declared to be both 'const' and 'final'.",
+    "Members can't be declared to be both 'const' and 'final'.",
     correction: "Try removing either the 'const' or 'final' keyword.");
 
 const ParserErrorCode _CONST_CLASS = ParserErrorCode(
-    'CONST_CLASS', r"Classes can't be declared to be 'const'.",
+    'CONST_CLASS', "Classes can't be declared to be 'const'.",
     correction:
         "Try removing the 'const' keyword. If you're trying to indicate that instances of the class can be constants, place the 'const' keyword on  the class' constructor(s).");
 
 const ParserErrorCode _CONST_FACTORY = ParserErrorCode('CONST_FACTORY',
-    r"Only redirecting factory constructors can be declared to be 'const'.",
+    "Only redirecting factory constructors can be declared to be 'const'.",
     correction:
         "Try removing the 'const' keyword, or replacing the body with '=' followed by a valid target.");
 
 const ParserErrorCode _CONST_METHOD = ParserErrorCode('CONST_METHOD',
-    r"Getters, setters and methods can't be declared to be 'const'.",
+    "Getters, setters and methods can't be declared to be 'const'.",
     correction: "Try removing the 'const' keyword.");
 
 const ParserErrorCode _CONTINUE_OUTSIDE_OF_LOOP = ParserErrorCode(
     'CONTINUE_OUTSIDE_OF_LOOP',
-    r"A continue statement can't be used outside of a loop or switch statement.",
+    "A continue statement can't be used outside of a loop or switch statement.",
     correction: "Try removing the continue statement.");
 
 const ParserErrorCode _CONTINUE_WITHOUT_LABEL_IN_CASE = ParserErrorCode(
     'CONTINUE_WITHOUT_LABEL_IN_CASE',
-    r"A continue statement in a switch statement must have a label as a target.",
+    "A continue statement in a switch statement must have a label as a target.",
     correction:
         "Try adding a label associated with one of the case clauses to the continue statement.");
 
 const ParserErrorCode _COVARIANT_AND_STATIC = ParserErrorCode(
     'COVARIANT_AND_STATIC',
-    r"Members can't be declared to be both 'covariant' and 'static'.",
+    "Members can't be declared to be both 'covariant' and 'static'.",
     correction: "Try removing either the 'covariant' or 'static' keyword.");
 
 const ParserErrorCode _COVARIANT_MEMBER = ParserErrorCode('COVARIANT_MEMBER',
-    r"Getters, setters and methods can't be declared to be 'covariant'.",
+    "Getters, setters and methods can't be declared to be 'covariant'.",
     correction: "Try removing the 'covariant' keyword.");
 
 const ParserErrorCode _DEFERRED_AFTER_PREFIX = ParserErrorCode(
     'DEFERRED_AFTER_PREFIX',
-    r"The deferred keyword should come immediately before the prefix ('as' clause).",
+    "The deferred keyword should come immediately before the prefix ('as' clause).",
     correction: "Try moving the deferred keyword before the prefix.");
 
 const ParserErrorCode _DIRECTIVE_AFTER_DECLARATION = ParserErrorCode(
     'DIRECTIVE_AFTER_DECLARATION',
-    r"Directives must appear before any declarations.",
+    "Directives must appear before any declarations.",
     correction: "Try moving the directive before any declarations.");
 
 const ParserErrorCode _DUPLICATED_MODIFIER = ParserErrorCode(
-    'DUPLICATED_MODIFIER', r"The modifier '{0}' was already specified.",
+    'DUPLICATED_MODIFIER', "The modifier '{0}' was already specified.",
     correction: "Try removing all but one occurrence of the modifier.");
 
 const ParserErrorCode _DUPLICATE_DEFERRED = ParserErrorCode(
     'DUPLICATE_DEFERRED',
-    r"An import directive can only have one 'deferred' keyword.",
+    "An import directive can only have one 'deferred' keyword.",
     correction: "Try removing all but one 'deferred' keyword.");
 
 const ParserErrorCode _DUPLICATE_LABEL_IN_SWITCH_STATEMENT = ParserErrorCode(
     'DUPLICATE_LABEL_IN_SWITCH_STATEMENT',
-    r"The label '{0}' was already used in this switch statement.",
+    "The label '{0}' was already used in this switch statement.",
     correction: "Try choosing a different name for this label.");
 
 const ParserErrorCode _DUPLICATE_PREFIX = ParserErrorCode('DUPLICATE_PREFIX',
-    r"An import directive can only have one prefix ('as' clause).",
+    "An import directive can only have one prefix ('as' clause).",
     correction: "Try removing all but one prefix.");
 
 const ParserErrorCode _ENUM_IN_CLASS = ParserErrorCode(
-    'ENUM_IN_CLASS', r"Enums can't be declared inside classes.",
+    'ENUM_IN_CLASS', "Enums can't be declared inside classes.",
     correction: "Try moving the enum to the top-level.");
 
 const ParserErrorCode _EQUALITY_CANNOT_BE_EQUALITY_OPERAND = ParserErrorCode(
     'EQUALITY_CANNOT_BE_EQUALITY_OPERAND',
-    r"A comparison expression can't be an operand of another comparison expression.",
+    "A comparison expression can't be an operand of another comparison expression.",
     correction: "Try putting parentheses around one of the comparisons.");
 
 const ParserErrorCode _EXPECTED_BODY = ParserErrorCode(
-    'EXPECTED_BODY', r"A {0} must have a body, even if it is empty.",
+    'EXPECTED_BODY', "A {0} must have a body, even if it is empty.",
     correction: "Try adding an empty body.");
 
 const ParserErrorCode _EXPECTED_ELSE_OR_COMMA =
-    ParserErrorCode('EXPECTED_ELSE_OR_COMMA', r"Expected 'else' or comma.");
+    ParserErrorCode('EXPECTED_ELSE_OR_COMMA', "Expected 'else' or comma.");
 
 const ParserErrorCode _EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD = ParserErrorCode(
     'EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD',
-    r"'{0}' can't be used as an identifier because it's a keyword.",
+    "'{0}' can't be used as an identifier because it's a keyword.",
     correction: "Try renaming this to be an identifier that isn't a keyword.");
 
 const ParserErrorCode _EXPECTED_INSTEAD =
-    ParserErrorCode('EXPECTED_INSTEAD', r"Expected '{0}' instead of this.");
+    ParserErrorCode('EXPECTED_INSTEAD', "Expected '{0}' instead of this.");
 
 const ParserErrorCode _EXPERIMENT_NOT_ENABLED = ParserErrorCode(
     'EXPERIMENT_NOT_ENABLED',
-    r"This requires the '{0}' language feature to be enabled.",
+    "This requires the '{0}' language feature to be enabled.",
     correction:
         "Try updating your pubspec.yaml to set the minimum SDK constraint to {1} or higher, and running 'pub get'.");
 
 const ParserErrorCode _EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = ParserErrorCode(
     'EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE',
-    r"Export directives must precede part directives.",
+    "Export directives must precede part directives.",
     correction: "Try moving the export directives before the part directives.");
 
 const ParserErrorCode _EXTENSION_DECLARES_ABSTRACT_MEMBER = ParserErrorCode(
     'EXTENSION_DECLARES_ABSTRACT_MEMBER',
-    r"Extensions can't declare abstract members.",
+    "Extensions can't declare abstract members.",
     correction: "Try providing an implementation for the member.",
     hasPublishedDocs: true);
 
 const ParserErrorCode _EXTENSION_DECLARES_CONSTRUCTOR = ParserErrorCode(
-    'EXTENSION_DECLARES_CONSTRUCTOR', r"Extensions can't declare constructors.",
+    'EXTENSION_DECLARES_CONSTRUCTOR', "Extensions can't declare constructors.",
     correction: "Try removing the constructor declaration.",
     hasPublishedDocs: true);
 
 const ParserErrorCode _EXTENSION_DECLARES_INSTANCE_FIELD = ParserErrorCode(
     'EXTENSION_DECLARES_INSTANCE_FIELD',
-    r"Extensions can't declare instance fields",
+    "Extensions can't declare instance fields",
     correction:
         "Try removing the field declaration or making it a static field",
     hasPublishedDocs: true);
 
 const ParserErrorCode _EXTERNAL_CLASS = ParserErrorCode(
-    'EXTERNAL_CLASS', r"Classes can't be declared to be 'external'.",
+    'EXTERNAL_CLASS', "Classes can't be declared to be 'external'.",
     correction: "Try removing the keyword 'external'.");
 
 const ParserErrorCode _EXTERNAL_CONSTRUCTOR_WITH_BODY = ParserErrorCode(
     'EXTERNAL_CONSTRUCTOR_WITH_BODY',
-    r"External constructors can't have a body.",
+    "External constructors can't have a body.",
     correction:
         "Try removing the body of the constructor, or removing the keyword 'external'.");
 
 const ParserErrorCode _EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER = ParserErrorCode(
     'EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER',
-    r"An external constructor can't have any initializers.");
+    "An external constructor can't have any initializers.");
 
 const ParserErrorCode _EXTERNAL_ENUM = ParserErrorCode(
-    'EXTERNAL_ENUM', r"Enums can't be declared to be 'external'.",
+    'EXTERNAL_ENUM', "Enums can't be declared to be 'external'.",
     correction: "Try removing the keyword 'external'.");
 
 const ParserErrorCode _EXTERNAL_FACTORY_REDIRECTION = ParserErrorCode(
-    'EXTERNAL_FACTORY_REDIRECTION', r"A redirecting factory can't be external.",
+    'EXTERNAL_FACTORY_REDIRECTION', "A redirecting factory can't be external.",
     correction: "Try removing the 'external' modifier.");
 
 const ParserErrorCode _EXTERNAL_FACTORY_WITH_BODY = ParserErrorCode(
-    'EXTERNAL_FACTORY_WITH_BODY', r"External factories can't have a body.",
+    'EXTERNAL_FACTORY_WITH_BODY', "External factories can't have a body.",
     correction:
         "Try removing the body of the factory, or removing the keyword 'external'.");
 
 const ParserErrorCode _EXTERNAL_FIELD = ParserErrorCode(
-    'EXTERNAL_FIELD', r"Fields can't be declared to be 'external'.",
+    'EXTERNAL_FIELD', "Fields can't be declared to be 'external'.",
     correction:
         "Try removing the keyword 'external', or replacing the field by an external getter and/or setter.");
 
 const ParserErrorCode _EXTERNAL_LATE_FIELD = ParserErrorCode(
-    'EXTERNAL_LATE_FIELD', r"External fields cannot be late.",
+    'EXTERNAL_LATE_FIELD', "External fields cannot be late.",
     correction: "Try removing the 'external' or 'late' keyword.");
 
 const ParserErrorCode _EXTERNAL_METHOD_WITH_BODY = ParserErrorCode(
     'EXTERNAL_METHOD_WITH_BODY',
-    r"An external or native method can't have a body.");
+    "An external or native method can't have a body.");
 
 const ParserErrorCode _EXTERNAL_TYPEDEF = ParserErrorCode(
-    'EXTERNAL_TYPEDEF', r"Typedefs can't be declared to be 'external'.",
+    'EXTERNAL_TYPEDEF', "Typedefs can't be declared to be 'external'.",
     correction: "Try removing the keyword 'external'.");
 
 const ParserErrorCode _EXTRANEOUS_MODIFIER = ParserErrorCode(
-    'EXTRANEOUS_MODIFIER', r"Can't have modifier '{0}' here.",
+    'EXTRANEOUS_MODIFIER', "Can't have modifier '{0}' here.",
     correction: "Try removing '{0}'.");
 
 const ParserErrorCode _FACTORY_TOP_LEVEL_DECLARATION = ParserErrorCode(
     'FACTORY_TOP_LEVEL_DECLARATION',
-    r"Top-level declarations can't be declared to be 'factory'.",
+    "Top-level declarations can't be declared to be 'factory'.",
     correction: "Try removing the keyword 'factory'.");
 
 const ParserErrorCode _FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS = ParserErrorCode(
     'FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS',
-    r"A field can only be initialized in its declaring class",
+    "A field can only be initialized in its declaring class",
     correction:
         "Try passing a value into the superclass constructor, or moving the initialization into the constructor body.");
 
 const ParserErrorCode _FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR = ParserErrorCode(
     'FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR',
-    r"Field formal parameters can only be used in a constructor.",
+    "Field formal parameters can only be used in a constructor.",
     correction: "Try removing 'this.'.");
 
 const ParserErrorCode _FINAL_AND_COVARIANT = ParserErrorCode(
     'FINAL_AND_COVARIANT',
-    r"Members can't be declared to be both 'final' and 'covariant'.",
+    "Members can't be declared to be both 'final' and 'covariant'.",
     correction: "Try removing either the 'final' or 'covariant' keyword.");
 
 const ParserErrorCode _FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER = ParserErrorCode(
     'FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER',
-    r"Members marked 'late' with an initializer can't be declared to be both 'final' and 'covariant'.",
+    "Members marked 'late' with an initializer can't be declared to be both 'final' and 'covariant'.",
     correction:
         "Try removing either the 'final' or 'covariant' keyword, or removing the initializer.");
 
 const ParserErrorCode _FINAL_AND_VAR = ParserErrorCode(
-    'FINAL_AND_VAR', r"Members can't be declared to be both 'final' and 'var'.",
+    'FINAL_AND_VAR', "Members can't be declared to be both 'final' and 'var'.",
     correction: "Try removing the keyword 'var'.");
 
 const ParserErrorCode _GETTER_CONSTRUCTOR = ParserErrorCode(
-    'GETTER_CONSTRUCTOR', r"Constructors can't be a getter.",
+    'GETTER_CONSTRUCTOR', "Constructors can't be a getter.",
     correction: "Try removing 'get'.");
 
 const ParserErrorCode _ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE = ParserErrorCode(
     'ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE',
-    r"Illegal assignment to non-assignable expression.");
+    "Illegal assignment to non-assignable expression.");
 
 const ParserErrorCode _IMPLEMENTS_BEFORE_EXTENDS = ParserErrorCode(
     'IMPLEMENTS_BEFORE_EXTENDS',
-    r"The extends clause must be before the implements clause.",
+    "The extends clause must be before the implements clause.",
     correction: "Try moving the extends clause before the implements clause.");
 
 const ParserErrorCode _IMPLEMENTS_BEFORE_ON = ParserErrorCode(
     'IMPLEMENTS_BEFORE_ON',
-    r"The on clause must be before the implements clause.",
+    "The on clause must be before the implements clause.",
     correction: "Try moving the on clause before the implements clause.");
 
 const ParserErrorCode _IMPLEMENTS_BEFORE_WITH = ParserErrorCode(
     'IMPLEMENTS_BEFORE_WITH',
-    r"The with clause must be before the implements clause.",
+    "The with clause must be before the implements clause.",
     correction: "Try moving the with clause before the implements clause.");
 
 const ParserErrorCode _IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = ParserErrorCode(
     'IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE',
-    r"Import directives must precede part directives.",
+    "Import directives must precede part directives.",
     correction: "Try moving the import directives before the part directives.");
 
 const ParserErrorCode _INITIALIZED_VARIABLE_IN_FOR_EACH = ParserErrorCode(
     'INITIALIZED_VARIABLE_IN_FOR_EACH',
-    r"The loop variable in a for-each loop can't be initialized.",
+    "The loop variable in a for-each loop can't be initialized.",
     correction:
         "Try removing the initializer, or using a different kind of loop.");
 
 const ParserErrorCode _INVALID_AWAIT_IN_FOR = ParserErrorCode(
     'INVALID_AWAIT_IN_FOR',
-    r"The keyword 'await' isn't allowed for a normal 'for' statement.",
+    "The keyword 'await' isn't allowed for a normal 'for' statement.",
     correction: "Try removing the keyword, or use a for-each statement.");
 
 const ParserErrorCode _INVALID_CONSTRUCTOR_NAME = ParserErrorCode(
     'INVALID_CONSTRUCTOR_NAME',
-    r"The name of a constructor must match the name of the enclosing class.");
+    "The name of a constructor must match the name of the enclosing class.");
 
 const ParserErrorCode _INVALID_HEX_ESCAPE = ParserErrorCode(
     'INVALID_HEX_ESCAPE',
-    r"An escape sequence starting with '\x' must be followed by 2 hexadecimal digits.");
+    "An escape sequence starting with '\\x' must be followed by 2 hexadecimal digits.");
 
 const ParserErrorCode _INVALID_INITIALIZER = ParserErrorCode(
-    'INVALID_INITIALIZER', r"Not a valid initializer.",
+    'INVALID_INITIALIZER', "Not a valid initializer.",
     correction: "To initialize a field, use the syntax 'name = value'.");
 
 const ParserErrorCode _INVALID_OPERATOR = ParserErrorCode(
-    'INVALID_OPERATOR', r"The string '{0}' isn't a user-definable operator.");
+    'INVALID_OPERATOR', "The string '{0}' isn't a user-definable operator.");
 
 const ParserErrorCode _INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER =
     ParserErrorCode('INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER',
-        r"The operator '?.' cannot be used with 'super' because 'super' cannot be null.",
+        "The operator '?.' cannot be used with 'super' because 'super' cannot be null.",
         correction: "Try replacing '?.' with '.'");
 
 const ParserErrorCode _INVALID_SUPER_IN_INITIALIZER = ParserErrorCode(
     'INVALID_SUPER_IN_INITIALIZER',
-    r"Can only use 'super' in an initializer for calling the superclass constructor (e.g. 'super()' or 'super.namedConstructor()')");
+    "Can only use 'super' in an initializer for calling the superclass constructor (e.g. 'super()' or 'super.namedConstructor()')");
 
 const ParserErrorCode _INVALID_THIS_IN_INITIALIZER = ParserErrorCode(
     'INVALID_THIS_IN_INITIALIZER',
-    r"Can only use 'this' in an initializer for field initialization (e.g. 'this.x = something') and constructor redirection (e.g. 'this()' or 'this.namedConstructor())");
+    "Can only use 'this' in an initializer for field initialization (e.g. 'this.x = something') and constructor redirection (e.g. 'this()' or 'this.namedConstructor())");
 
 const ParserErrorCode _INVALID_UNICODE_ESCAPE = ParserErrorCode(
     'INVALID_UNICODE_ESCAPE',
-    r"An escape sequence starting with '\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.");
+    "An escape sequence starting with '\\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.");
 
 const ParserErrorCode _INVALID_USE_OF_COVARIANT_IN_EXTENSION = ParserErrorCode(
     'INVALID_USE_OF_COVARIANT_IN_EXTENSION',
-    r"Can't have modifier '{0}' in an extension.",
+    "Can't have modifier '{0}' in an extension.",
     correction: "Try removing '{0}'.",
     hasPublishedDocs: true);
 
 const ParserErrorCode _LIBRARY_DIRECTIVE_NOT_FIRST = ParserErrorCode(
     'LIBRARY_DIRECTIVE_NOT_FIRST',
-    r"The library directive must appear before all other directives.",
+    "The library directive must appear before all other directives.",
     correction:
         "Try moving the library directive before any other directives.");
 
 const ParserErrorCode _LITERAL_WITH_CLASS = ParserErrorCode(
-    'LITERAL_WITH_CLASS', r"A {0} literal can't be prefixed by '{1}'.",
+    'LITERAL_WITH_CLASS', "A {0} literal can't be prefixed by '{1}'.",
     correction: "Try removing '{1}'");
 
 const ParserErrorCode _LITERAL_WITH_CLASS_AND_NEW = ParserErrorCode(
     'LITERAL_WITH_CLASS_AND_NEW',
-    r"A {0} literal can't be prefixed by 'new {1}'.",
+    "A {0} literal can't be prefixed by 'new {1}'.",
     correction: "Try removing 'new' and '{1}'");
 
 const ParserErrorCode _LITERAL_WITH_NEW = ParserErrorCode(
-    'LITERAL_WITH_NEW', r"A literal can't be prefixed by 'new'.",
+    'LITERAL_WITH_NEW', "A literal can't be prefixed by 'new'.",
     correction: "Try removing 'new'");
 
 const ParserErrorCode _MEMBER_WITH_CLASS_NAME = ParserErrorCode(
     'MEMBER_WITH_CLASS_NAME',
-    r"A class member can't have the same name as the enclosing class.",
+    "A class member can't have the same name as the enclosing class.",
     correction: "Try renaming the member.");
 
 const ParserErrorCode _MISSING_ASSIGNABLE_SELECTOR = ParserErrorCode(
     'MISSING_ASSIGNABLE_SELECTOR',
-    r"Missing selector such as '.identifier' or '[0]'.",
+    "Missing selector such as '.identifier' or '[0]'.",
     correction: "Try adding a selector.");
 
 const ParserErrorCode _MISSING_ASSIGNMENT_IN_INITIALIZER = ParserErrorCode(
     'MISSING_ASSIGNMENT_IN_INITIALIZER',
-    r"Expected an assignment after the field name.",
+    "Expected an assignment after the field name.",
     correction: "To initialize a field, use the syntax 'name = value'.");
 
 const ParserErrorCode _MISSING_CATCH_OR_FINALLY = ParserErrorCode(
     'MISSING_CATCH_OR_FINALLY',
-    r"A try block must be followed by an 'on', 'catch', or 'finally' clause.",
+    "A try block must be followed by an 'on', 'catch', or 'finally' clause.",
     correction:
         "Try adding either a catch or finally clause, or remove the try statement.");
 
 const ParserErrorCode _MISSING_CONST_FINAL_VAR_OR_TYPE = ParserErrorCode(
     'MISSING_CONST_FINAL_VAR_OR_TYPE',
-    r"Variables must be declared using the keywords 'const', 'final', 'var' or a type name.",
+    "Variables must be declared using the keywords 'const', 'final', 'var' or a type name.",
     correction:
         "Try adding the name of the type of the variable or the keyword 'var'.");
 
 const ParserErrorCode _MISSING_EXPRESSION_IN_THROW = ParserErrorCode(
-    'MISSING_EXPRESSION_IN_THROW', r"Missing expression after 'throw'.",
+    'MISSING_EXPRESSION_IN_THROW', "Missing expression after 'throw'.",
     correction:
         "Add an expression after 'throw' or use 'rethrow' to throw a caught exception");
 
 const ParserErrorCode _MISSING_INITIALIZER =
-    ParserErrorCode('MISSING_INITIALIZER', r"Expected an initializer.");
+    ParserErrorCode('MISSING_INITIALIZER', "Expected an initializer.");
 
 const ParserErrorCode _MISSING_KEYWORD_OPERATOR = ParserErrorCode(
     'MISSING_KEYWORD_OPERATOR',
-    r"Operator declarations must be preceded by the keyword 'operator'.",
+    "Operator declarations must be preceded by the keyword 'operator'.",
     correction: "Try adding the keyword 'operator'.");
 
 const ParserErrorCode _MISSING_PREFIX_IN_DEFERRED_IMPORT = ParserErrorCode(
     'MISSING_PREFIX_IN_DEFERRED_IMPORT',
-    r"Deferred imports should have a prefix.",
+    "Deferred imports should have a prefix.",
     correction: "Try adding a prefix to the import by adding an 'as' clause.");
 
 const ParserErrorCode _MISSING_STATEMENT =
-    ParserErrorCode('MISSING_STATEMENT', r"Expected a statement.");
+    ParserErrorCode('MISSING_STATEMENT', "Expected a statement.");
 
 const ParserErrorCode _MIXIN_DECLARES_CONSTRUCTOR = ParserErrorCode(
-    'MIXIN_DECLARES_CONSTRUCTOR', r"Mixins can't declare constructors.");
+    'MIXIN_DECLARES_CONSTRUCTOR', "Mixins can't declare constructors.");
 
 const ParserErrorCode _MODIFIER_OUT_OF_ORDER = ParserErrorCode(
     'MODIFIER_OUT_OF_ORDER',
-    r"The modifier '{0}' should be before the modifier '{1}'.",
+    "The modifier '{0}' should be before the modifier '{1}'.",
     correction: "Try re-ordering the modifiers.");
 
 const ParserErrorCode _MULTIPLE_EXTENDS_CLAUSES = ParserErrorCode(
     'MULTIPLE_EXTENDS_CLAUSES',
-    r"Each class definition can have at most one extends clause.",
+    "Each class definition can have at most one extends clause.",
     correction:
         "Try choosing one superclass and define your class to implement (or mix in) the others.");
 
 const ParserErrorCode _MULTIPLE_LIBRARY_DIRECTIVES = ParserErrorCode(
     'MULTIPLE_LIBRARY_DIRECTIVES',
-    r"Only one library directive may be declared in a file.",
+    "Only one library directive may be declared in a file.",
     correction: "Try removing all but one of the library directives.");
 
 const ParserErrorCode _MULTIPLE_ON_CLAUSES = ParserErrorCode(
     'MULTIPLE_ON_CLAUSES',
-    r"Each mixin definition can have at most one on clause.",
+    "Each mixin definition can have at most one on clause.",
     correction: "Try combining all of the on clauses into a single clause.");
 
 const ParserErrorCode _MULTIPLE_PART_OF_DIRECTIVES = ParserErrorCode(
     'MULTIPLE_PART_OF_DIRECTIVES',
-    r"Only one part-of directive may be declared in a file.",
+    "Only one part-of directive may be declared in a file.",
     correction: "Try removing all but one of the part-of directives.");
 
 const ParserErrorCode _MULTIPLE_VARIANCE_MODIFIERS = ParserErrorCode(
     'MULTIPLE_VARIANCE_MODIFIERS',
-    r"Each type parameter can have at most one variance modifier.",
+    "Each type parameter can have at most one variance modifier.",
     correction: "Use at most one of the 'in', 'out', or 'inout' modifiers.");
 
 const ParserErrorCode _MULTIPLE_WITH_CLAUSES = ParserErrorCode(
     'MULTIPLE_WITH_CLAUSES',
-    r"Each class definition can have at most one with clause.",
+    "Each class definition can have at most one with clause.",
     correction: "Try combining all of the with clauses into a single clause.");
 
 const ParserErrorCode _NATIVE_CLAUSE_SHOULD_BE_ANNOTATION = ParserErrorCode(
     'NATIVE_CLAUSE_SHOULD_BE_ANNOTATION',
-    r"Native clause in this form is deprecated.",
+    "Native clause in this form is deprecated.",
     correction:
         "Try removing this native clause and adding @native() or @native('native-name') before the declaration.");
 
 const ParserErrorCode _NULL_AWARE_CASCADE_OUT_OF_ORDER = ParserErrorCode(
     'NULL_AWARE_CASCADE_OUT_OF_ORDER',
-    r"The '?..' cascade operator must be first in the cascade sequence.",
+    "The '?..' cascade operator must be first in the cascade sequence.",
     correction:
         "Try moving the '?..' operator to be the first cascade operator in the sequence.");
 
 const ParserErrorCode _PREFIX_AFTER_COMBINATOR = ParserErrorCode(
     'PREFIX_AFTER_COMBINATOR',
-    r"The prefix ('as' clause) should come before any show/hide combinators.",
+    "The prefix ('as' clause) should come before any show/hide combinators.",
     correction: "Try moving the prefix before the combinators.");
 
 const ParserErrorCode _REDIRECTING_CONSTRUCTOR_WITH_BODY = ParserErrorCode(
     'REDIRECTING_CONSTRUCTOR_WITH_BODY',
-    r"Redirecting constructors can't have a body.",
+    "Redirecting constructors can't have a body.",
     correction:
         "Try removing the body, or not making this a redirecting constructor.");
 
 const ParserErrorCode _REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR = ParserErrorCode(
     'REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR',
-    r"Only factory constructor can specify '=' redirection.",
+    "Only factory constructor can specify '=' redirection.",
     correction:
         "Try making this a factory constructor, or remove the redirection.");
 
 const ParserErrorCode _SETTER_CONSTRUCTOR = ParserErrorCode(
-    'SETTER_CONSTRUCTOR', r"Constructors can't be a setter.",
+    'SETTER_CONSTRUCTOR', "Constructors can't be a setter.",
     correction: "Try removing 'set'.");
 
-const ParserErrorCode _STACK_OVERFLOW = ParserErrorCode('STACK_OVERFLOW',
-    r"The file has too many nested expressions or statements.",
+const ParserErrorCode _STACK_OVERFLOW = ParserErrorCode(
+    'STACK_OVERFLOW', "The file has too many nested expressions or statements.",
     correction: "Try simplifying the code.");
 
 const ParserErrorCode _STATIC_CONSTRUCTOR = ParserErrorCode(
-    'STATIC_CONSTRUCTOR', r"Constructors can't be static.",
+    'STATIC_CONSTRUCTOR', "Constructors can't be static.",
     correction: "Try removing the keyword 'static'.");
 
 const ParserErrorCode _STATIC_OPERATOR = ParserErrorCode(
-    'STATIC_OPERATOR', r"Operators can't be static.",
+    'STATIC_OPERATOR', "Operators can't be static.",
     correction: "Try removing the keyword 'static'.");
 
 const ParserErrorCode _SWITCH_HAS_CASE_AFTER_DEFAULT_CASE = ParserErrorCode(
     'SWITCH_HAS_CASE_AFTER_DEFAULT_CASE',
-    r"The default case should be the last case in a switch statement.",
+    "The default case should be the last case in a switch statement.",
     correction: "Try moving the default case after the other case clauses.");
 
 const ParserErrorCode _SWITCH_HAS_MULTIPLE_DEFAULT_CASES = ParserErrorCode(
     'SWITCH_HAS_MULTIPLE_DEFAULT_CASES',
-    r"The 'default' case can only be declared once.",
+    "The 'default' case can only be declared once.",
     correction: "Try removing all but one default case.");
 
 const ParserErrorCode _TOP_LEVEL_OPERATOR = ParserErrorCode(
-    'TOP_LEVEL_OPERATOR', r"Operators must be declared within a class.",
+    'TOP_LEVEL_OPERATOR', "Operators must be declared within a class.",
     correction:
         "Try removing the operator, moving it to a class, or converting it to be a function.");
 
 const ParserErrorCode _TYPEDEF_IN_CLASS = ParserErrorCode(
-    'TYPEDEF_IN_CLASS', r"Typedefs can't be declared inside classes.",
+    'TYPEDEF_IN_CLASS', "Typedefs can't be declared inside classes.",
     correction: "Try moving the typedef to the top-level.");
 
 const ParserErrorCode _TYPE_ARGUMENTS_ON_TYPE_VARIABLE = ParserErrorCode(
     'TYPE_ARGUMENTS_ON_TYPE_VARIABLE',
-    r"Can't use type arguments with type variable '{0}'.",
+    "Can't use type arguments with type variable '{0}'.",
     correction: "Try removing the type arguments.");
 
 const ParserErrorCode _TYPE_BEFORE_FACTORY = ParserErrorCode(
-    'TYPE_BEFORE_FACTORY', r"Factory constructors cannot have a return type.",
+    'TYPE_BEFORE_FACTORY', "Factory constructors cannot have a return type.",
     correction: "Try removing the type appearing before 'factory'.");
 
 const ParserErrorCode _TYPE_PARAMETER_ON_CONSTRUCTOR = ParserErrorCode(
-    'TYPE_PARAMETER_ON_CONSTRUCTOR',
-    r"Constructors can't have type parameters.",
+    'TYPE_PARAMETER_ON_CONSTRUCTOR', "Constructors can't have type parameters.",
     correction: "Try removing the type parameters.");
 
 const ParserErrorCode _VAR_AND_TYPE = ParserErrorCode('VAR_AND_TYPE',
-    r"Variables can't be declared using both 'var' and a type name.",
+    "Variables can't be declared using both 'var' and a type name.",
     correction: "Try removing 'var.'");
 
 const ParserErrorCode _VAR_AS_TYPE_NAME = ParserErrorCode(
-    'VAR_AS_TYPE_NAME', r"The keyword 'var' can't be used as a type name.");
+    'VAR_AS_TYPE_NAME', "The keyword 'var' can't be used as a type name.");
 
 const ParserErrorCode _VAR_RETURN_TYPE = ParserErrorCode(
-    'VAR_RETURN_TYPE', r"The return type can't be 'var'.",
+    'VAR_RETURN_TYPE', "The return type can't be 'var'.",
     correction:
         "Try removing the keyword 'var', or replacing it with the name of the return type.");
 
 const ParserErrorCode _VOID_WITH_TYPE_ARGUMENTS = ParserErrorCode(
-    'VOID_WITH_TYPE_ARGUMENTS', r"Type 'void' can't have type arguments.",
+    'VOID_WITH_TYPE_ARGUMENTS', "Type 'void' can't have type arguments.",
     correction: "Try removing the type arguments.");
 
 const ParserErrorCode _WITH_BEFORE_EXTENDS = ParserErrorCode(
-    'WITH_BEFORE_EXTENDS',
-    r"The extends clause must be before the with clause.",
+    'WITH_BEFORE_EXTENDS', "The extends clause must be before the with clause.",
     correction: "Try moving the extends clause before the with clause.");
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 4cd3002..0754988 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -3049,7 +3049,7 @@
   /**
    * No parameters.
    */
-  /* #### Description
+  // #### Description
   //
   // The analyzer produces this diagnostic when a named parameter has both the
   // `required` modifier and a default value. If the parameter is required, then
@@ -3077,7 +3077,7 @@
   //
   // ```dart
   // void log({String message = 'no message'}) {}
-  // ``` */
+  // ```
   static const CompileTimeErrorCode DEFAULT_VALUE_ON_REQUIRED_PARAMETER =
       CompileTimeErrorCode('DEFAULT_VALUE_ON_REQUIRED_PARAMETER',
           "Required named parameters can't have a default value.",
@@ -8468,7 +8468,7 @@
   // #### Example
   //
   // The following code produces this diagnostic because the mixin `M` requires
-  //that the class to which it's applied be a subclass of `A`, but `Object`
+  // that the class to which it's applied be a subclass of `A`, but `Object`
   // isn't a subclass of `A`:
   //
   // ```dart
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 9aa5e8e..a05f61d 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -365,6 +365,7 @@
   int operator -();
   int operator <<(int shiftAmount);
   int operator >>(int shiftAmount);
+  int operator >>>(int shiftAmount);
   int operator ^(int other);
   int operator |(int other);
   int operator ~();
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 7b42573..9facdf6 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -177,6 +177,120 @@
     );
   }
 
+  test_identical_typeLiteral_explicitTypeArgs_differentTypeArgs() async {
+    await resolveTestCode('''
+class C<T> {}
+const c = identical(C<int>, C<String>);
+''');
+    expect(
+      _evaluateConstant('c'),
+      _boolValue(false),
+    );
+  }
+
+  test_identical_typeLiteral_explicitTypeArgs_differentTypes() async {
+    await resolveTestCode('''
+class C<T> {}
+class D<T> {}
+const c = identical(C<int>, D<int>);
+''');
+    expect(
+      _evaluateConstant('c'),
+      _boolValue(false),
+    );
+  }
+
+  test_identical_typeLiteral_explicitTypeArgs_sameType() async {
+    await resolveTestCode('''
+class C<T> {}
+const c = identical(C<int>, C<int>);
+''');
+    expect(
+      _evaluateConstant('c'),
+      _boolValue(true),
+    );
+  }
+
+  test_identical_typeLiteral_explicitTypeArgs_simpleTypeAlias() async {
+    await resolveTestCode('''
+class C<T> {}
+typedef TC = C<int>;
+const c = identical(C<int>, TC);
+''');
+    expect(
+      _evaluateConstant('c'),
+      _boolValue(true),
+    );
+  }
+
+  test_identical_typeLiteral_explicitTypeArgs_typeAlias() async {
+    await resolveTestCode('''
+class C<T> {}
+typedef TC<T> = C<T>;
+const c = identical(C<int>, TC<int>);
+''');
+    expect(
+      _evaluateConstant('c'),
+      _boolValue(true),
+    );
+  }
+
+  test_identical_typeLiteral_explicitTypeArgs_typeAlias_differentTypeArgs() async {
+    await resolveTestCode('''
+class C<T> {}
+typedef TC<T> = C<T>;
+const c = identical(C<int>, TC<String>);
+''');
+    expect(
+      _evaluateConstant('c'),
+      _boolValue(false),
+    );
+  }
+
+  test_identical_typeLiteral_explicitTypeArgs_typeAlias_implicitTypeArgs() async {
+    await resolveTestCode('''
+class C<T> {}
+typedef TC<T> = C<T>;
+const c = identical(C<dynamic>, TC);
+''');
+    expect(
+      _evaluateConstant('c'),
+      _boolValue(true),
+    );
+  }
+
+  test_identical_typeLiteral_explicitTypeArgs_typeAlias_implicitTypeArgs_bound() async {
+    await resolveTestCode('''
+class C<T extends num> {}
+typedef TC<T extends num> = C<T>;
+const c = identical(C<num>, TC);
+''');
+    expect(
+      _evaluateConstant('c'),
+      _boolValue(true),
+    );
+  }
+
+  test_identical_typeLiteral_simple_differentTypes() async {
+    await resolveTestCode('''
+const c = identical(int, String);
+''');
+    expect(
+      _evaluateConstant('c'),
+      _boolValue(false),
+    );
+  }
+
+  test_identical_typeLiteral_simple_sameType() async {
+    await resolveTestCode('''
+const c = identical(int, int);
+''');
+    expect(
+      _evaluateConstant('c'),
+      _boolValue(true),
+    );
+  }
+
   test_visitAsExpression_potentialConstType() async {
     await assertNoErrorsInCode('''
 const num three = 3;
diff --git a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
index 5be34e4..47869ef 100644
--- a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
@@ -273,7 +273,7 @@
 ''');
 
     assertTypeArgumentTypes(findNode.methodInvocation('f()'),
-        [typeToStringWithNullability ? 'int' : 'num']);
+        [typeStringByNullability(nullable: 'int', legacy: 'num')]);
   }
 
   test_minus_int_double() async {
@@ -320,7 +320,7 @@
 ''');
 
     assertTypeArgumentTypes(findNode.methodInvocation('f()'),
-        [typeToStringWithNullability ? 'int' : 'num']);
+        [typeStringByNullability(nullable: 'int', legacy: 'num')]);
   }
 
   test_mod_int_double() async {
@@ -421,7 +421,7 @@
 ''');
 
     assertTypeArgumentTypes(findNode.methodInvocation('f()'),
-        [typeToStringWithNullability ? 'double' : 'num']);
+        [typeStringByNullability(nullable: 'double', legacy: 'num')]);
   }
 
   test_plus_int_context_int() async {
@@ -434,7 +434,7 @@
 ''');
 
     assertTypeArgumentTypes(findNode.methodInvocation('f()'),
-        [typeToStringWithNullability ? 'int' : 'num']);
+        [typeStringByNullability(nullable: 'int', legacy: 'num')]);
   }
 
   test_plus_int_context_int_target_rewritten() async {
@@ -447,7 +447,7 @@
 ''');
 
     assertTypeArgumentTypes(findNode.methodInvocation('f()'),
-        [typeToStringWithNullability ? 'int' : 'num']);
+        [typeStringByNullability(nullable: 'int', legacy: 'num')]);
   }
 
   test_plus_int_context_int_via_extension_explicit() async {
@@ -774,7 +774,7 @@
 ''');
 
     assertTypeArgumentTypes(findNode.methodInvocation('f()'),
-        [typeToStringWithNullability ? 'int' : 'num']);
+        [typeStringByNullability(nullable: 'int', legacy: 'num')]);
   }
 
   test_star_int_double() async {
diff --git a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
index 20e87bf..c02261d 100644
--- a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
@@ -189,7 +189,7 @@
         numPlusElement,
         isLegacy: isLegacyLibrary,
       ),
-      type: typeToStringWithNullability ? 'double' : 'num',
+      type: typeStringByNullability(nullable: 'double', legacy: 'num'),
     );
     assertParameterElement(
       assignment.rightHandSide,
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index f9f50e2..17bac73 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -33,9 +33,9 @@
 ''');
 
     assertTypeArgumentTypes(findNode.methodInvocation('f(),'),
-        [typeToStringWithNullability ? 'double' : 'num']);
+        [typeStringByNullability(nullable: 'double', legacy: 'num')]);
     assertTypeArgumentTypes(findNode.methodInvocation('f())'),
-        [typeToStringWithNullability ? 'double' : 'num']);
+        [typeStringByNullability(nullable: 'double', legacy: 'num')]);
   }
 
   test_clamp_double_context_int() async {
@@ -79,7 +79,8 @@
         elementMatcher(numElement.getMethod('clamp'),
             isLegacy: isLegacyLibrary),
         'num Function(num, num)',
-        expectedType: typeToStringWithNullability ? 'double' : 'num');
+        expectedType:
+            typeStringByNullability(nullable: 'double', legacy: 'num'));
   }
 
   test_clamp_double_double_int() async {
@@ -154,9 +155,9 @@
 ''');
 
     assertTypeArgumentTypes(findNode.methodInvocation('f(),'),
-        [typeToStringWithNullability ? 'int' : 'num']);
+        [typeStringByNullability(nullable: 'int', legacy: 'num')]);
     assertTypeArgumentTypes(findNode.methodInvocation('f())'),
-        [typeToStringWithNullability ? 'int' : 'num']);
+        [typeStringByNullability(nullable: 'int', legacy: 'num')]);
   }
 
   test_clamp_int_context_none() async {
@@ -288,7 +289,7 @@
         elementMatcher(numElement.getMethod('clamp'),
             isLegacy: isLegacyLibrary),
         'num Function(num, num)',
-        expectedType: typeToStringWithNullability ? 'int' : 'num');
+        expectedType: typeStringByNullability(nullable: 'int', legacy: 'num'));
   }
 
   test_clamp_int_int_int_from_cascade() async {
@@ -307,7 +308,7 @@
         elementMatcher(numElement.getMethod('clamp'),
             isLegacy: isLegacyLibrary),
         'num Function(num, num)',
-        expectedType: typeToStringWithNullability ? 'int' : 'num');
+        expectedType: typeStringByNullability(nullable: 'int', legacy: 'num'));
   }
 
   test_clamp_int_int_int_via_extension_explicit() async {
@@ -377,7 +378,8 @@
 
     assertMethodInvocation(
         findNode.methodInvocation('clamp'), isNull, 'dynamic',
-        expectedType: typeToStringWithNullability ? 'Never' : 'dynamic');
+        expectedType:
+            typeStringByNullability(nullable: 'Never', legacy: 'dynamic'));
   }
 
   test_clamp_other_context_int() async {
@@ -2217,7 +2219,7 @@
 ''');
 
     assertTypeArgumentTypes(findNode.methodInvocation('f()'),
-        [typeToStringWithNullability ? 'int' : 'num']);
+        [typeStringByNullability(nullable: 'int', legacy: 'num')]);
   }
 
   test_remainder_int_context_int_target_rewritten() async {
@@ -2230,7 +2232,7 @@
 ''');
 
     assertTypeArgumentTypes(findNode.methodInvocation('f()'),
-        [typeToStringWithNullability ? 'int' : 'num']);
+        [typeStringByNullability(nullable: 'int', legacy: 'num')]);
   }
 
   test_remainder_int_context_int_via_extension_explicit() async {
@@ -2273,7 +2275,8 @@
         elementMatcher(numElement.getMethod('remainder'),
             isLegacy: isLegacyLibrary),
         'num Function(num)',
-        expectedType: typeToStringWithNullability ? 'double' : 'num');
+        expectedType:
+            typeStringByNullability(nullable: 'double', legacy: 'num'));
   }
 
   test_remainder_int_int() async {
@@ -2288,7 +2291,7 @@
         elementMatcher(numElement.getMethod('remainder'),
             isLegacy: isLegacyLibrary),
         'num Function(num)',
-        expectedType: typeToStringWithNullability ? 'int' : 'num');
+        expectedType: typeStringByNullability(nullable: 'int', legacy: 'num'));
   }
 
   test_remainder_int_int_target_rewritten() async {
@@ -2303,7 +2306,7 @@
         elementMatcher(numElement.getMethod('remainder'),
             isLegacy: isLegacyLibrary),
         'num Function(num)',
-        expectedType: typeToStringWithNullability ? 'int' : 'num');
+        expectedType: typeStringByNullability(nullable: 'int', legacy: 'num'));
   }
 
   test_remainder_other_context_int_via_extension_explicit() async {
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
index ec6150f..fd70b98 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
@@ -22,23 +22,16 @@
       '${ExperimentStatus.currentVersion.minor}';
 
   test_const_equals() async {
-    // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
-    //  UNDEFINED_OPERATOR when triple_shift is enabled by default.
     await verifyVersion('2.5.0', '''
 const a = 42 >>> 3;
-''', expectedErrors: [
-      error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 13, 3),
-    ]);
+''');
   }
 
   test_const_lessThan() async {
-    // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
-    //  UNDEFINED_OPERATOR when triple_shift is enabled by default.
     await verifyVersion('2.2.0', '''
 const a = 42 >>> 3;
 ''', expectedErrors: [
       error(HintCode.SDK_VERSION_GT_GT_GT_OPERATOR, 13, 3),
-      error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 13, 3),
     ]);
   }
 
@@ -61,23 +54,16 @@
   }
 
   test_nonConst_equals() async {
-    // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
-    //  UNDEFINED_OPERATOR when triple_shift is enabled by default.
     await verifyVersion('2.5.0', '''
 var a = 42 >>> 3;
-''', expectedErrors: [
-      error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 11, 3),
-    ]);
+''');
   }
 
   test_nonConst_lessThan() async {
-    // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
-    //  UNDEFINED_OPERATOR when triple_shift is enabled by default.
     await verifyVersion('2.2.0', '''
 var a = 42 >>> 3;
 ''', expectedErrors: [
       error(HintCode.SDK_VERSION_GT_GT_GT_OPERATOR, 11, 3),
-      error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 11, 3),
     ]);
   }
 }
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 2a99024..e41c85f 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -3096,6 +3096,40 @@
 }
 {% endprettify %}
 
+### default_value_on_required_parameter
+
+_Required named parameters can't have a default value._
+
+#### Description
+
+The analyzer produces this diagnostic when a named parameter has both the
+`required` modifier and a default value. If the parameter is required, then
+a value for the parameter is always provided at the call sites, so the
+default value can never be used.
+
+#### Examples
+
+The following code generates this diagnostic:
+
+{% prettify dart tag=pre+code %}
+void log({required String [!message!] = 'no message'}) {}
+{% endprettify %}
+
+#### Common fixes
+
+If the parameter is really required, then remove the default value:
+
+{% prettify dart tag=pre+code %}
+void log({required String message}) {}
+{% endprettify %}
+
+If the parameter isn't always required, then remove the `required`
+modifier:
+
+{% prettify dart tag=pre+code %}
+void log({String message = 'no message'}) {}
+{% endprettify %}
+
 ### deferred_import_of_extension
 
 _Imports of deferred libraries must hide all extensions._
@@ -8401,6 +8435,7 @@
 #### Example
 
 The following code produces this diagnostic because the mixin `M` requires
+that the class to which it's applied be a subclass of `A`, but `Object`
 isn't a subclass of `A`:
 
 {% prettify dart tag=pre+code %}
@@ -12172,6 +12207,60 @@
 }
 {% endprettify %}
 
+### sdk_version_gt_gt_gt_operator
+
+_The operator '>>>' wasn't supported until version 2.3.2, but this code is
+required to be able to run on earlier versions._
+
+#### Description
+
+The analyzer produces this diagnostic when the operator `>>>` is used in
+code that has an SDK constraint whose lower bound is less than 2.X.0. This
+operator wasn't supported in earlier versions, so this code won't be able
+to run against earlier versions of the SDK.
+
+#### Examples
+
+Here's an example of a pubspec that defines an SDK constraint with a lower
+bound of less than 2.X.0:
+
+```yaml
+environment:
+ sdk: '>=2.0.0 <2.4.0'
+```
+
+In the package that has that pubspec, code like the following produces this
+diagnostic:
+
+{% prettify dart tag=pre+code %}
+int x = 3 [!>>>!] 4;
+{% endprettify %}
+
+#### Common fixes
+
+If you don't need to support older versions of the SDK, then you can
+increase the SDK constraint to allow the operator to be used:
+
+```yaml
+environment:
+  sdk: '>=2.3.2 <2.4.0'
+```
+
+If you need to support older versions of the SDK, then rewrite the code to
+not use the `>>>` operator:
+
+{% prettify dart tag=pre+code %}
+int x = logicalShiftRight(3, 4);
+
+int logicalShiftRight(int leftOperand, int rightOperand) {
+  int divisor = 1 << rightOperand;
+  if (divisor == 0) {
+    return 0;
+  }
+  return leftOperand ~/ divisor;
+}
+{% endprettify %}
+
 ### sdk_version_is_expression_in_const_context
 
 _The use of an is expression in a constant context wasn't supported until
diff --git a/pkg/analyzer/tool/messages/error_code_info.dart b/pkg/analyzer/tool/messages/error_code_info.dart
new file mode 100644
index 0000000..322759b
--- /dev/null
+++ b/pkg/analyzer/tool/messages/error_code_info.dart
@@ -0,0 +1,122 @@
+// 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 'dart:convert';
+
+/// Decodes a YAML object (obtained from `pkg/front_end/messages.yaml`) into a
+/// map from error name to [ErrorCodeInfo].
+Map<String, ErrorCodeInfo> decodeCfeMessagesYaml(Map<Object?, Object?> yaml) {
+  var result = <String, ErrorCodeInfo>{};
+  for (var entry in yaml.entries) {
+    result[entry.key as String] =
+        ErrorCodeInfo.fromYaml(entry.value as Map<Object?, Object?>);
+  }
+  return result;
+}
+
+/// In-memory representation of error code information obtained from a
+/// `messages.yaml` file.
+class ErrorCodeInfo {
+  /// Pattern used by the front end to identify placeholders in error message
+  /// strings.  TODO(paulberry): share this regexp (and the code for interpreting
+  /// it) between the CFE and analyzer.
+  static final RegExp _placeholderPattern =
+      RegExp("#\([-a-zA-Z0-9_]+\)(?:%\([0-9]*\)\.\([0-9]+\))?");
+
+  /// For error code information obtained from the CFE, the set of analyzer
+  /// error codes that corresponds to this error code, if any.
+  final List<String> analyzerCode;
+
+  /// `true` if diagnostics with this code have documentation for them that has
+  /// been published.
+  final bool hasPublishedDocs;
+
+  /// For error code information obtained from the CFE, the index of the error
+  /// in the analyzer's `fastaAnalyzerErrorCodes` table.
+  final int? index;
+
+  /// The template for the error message.
+  final String template;
+
+  /// If the error code has an associated tip/correction message, the template
+  /// for it.
+  final String? tip;
+
+  ErrorCodeInfo(
+      {this.analyzerCode = const [],
+      this.hasPublishedDocs = false,
+      this.index,
+      required this.template,
+      this.tip});
+
+  /// Decodes an [ErrorCodeInfo] object from its YAML representation.
+  ErrorCodeInfo.fromYaml(Map<Object?, Object?> yaml)
+      : this(
+            analyzerCode: _decodeAnalyzerCode(yaml['analyzerCode']),
+            hasPublishedDocs: yaml['hasPublishedDocs'] as bool? ?? false,
+            index: yaml['index'] as int?,
+            template: yaml['template'] as String,
+            tip: yaml['tip'] as String?);
+
+  /// Generates a dart declaration for this error code, suitable for inclusion
+  /// in the error class [className].  [errorCode] is the name of the error code
+  /// to be generated.
+  String toAnalyzerCode(String className, String errorCode) {
+    var out = StringBuffer();
+    out.writeln('$className(');
+    out.writeln("'$errorCode',");
+    final placeholderToIndexMap = _computePlaceholderToIndexMap();
+    out.writeln(json.encode(_convertTemplate(placeholderToIndexMap, template)));
+    final tip = this.tip;
+    if (tip is String) {
+      out.write(',correction: ');
+      out.writeln(json.encode(_convertTemplate(placeholderToIndexMap, tip)));
+    }
+    if (hasPublishedDocs) {
+      out.writeln(',hasPublishedDocs:true');
+    }
+    out.write(');');
+    return out.toString();
+  }
+
+  /// Given a messages.yaml entry, come up with a mapping from placeholder
+  /// patterns in its message and tip strings to their corresponding indices.
+  Map<String, int> _computePlaceholderToIndexMap() {
+    var mapping = <String, int>{};
+    for (var value in [template, tip]) {
+      if (value is! String) continue;
+      for (Match match in _placeholderPattern.allMatches(value)) {
+        // CFE supports a bunch of formatting options that we don't; make sure
+        // none of those are used.
+        if (match.group(0) != '#${match.group(1)}') {
+          throw 'Template string ${json.encode(value)} contains unsupported '
+              'placeholder pattern ${json.encode(match.group(0))}';
+        }
+
+        mapping[match.group(0)!] ??= mapping.length;
+      }
+    }
+    return mapping;
+  }
+
+  /// Convert a CFE template string (which uses placeholders like `#string`) to
+  /// an analyzer template string (which uses placeholders like `{0}`).
+  static String _convertTemplate(
+      Map<String, int> placeholderToIndexMap, String entry) {
+    return entry.replaceAllMapped(_placeholderPattern,
+        (match) => '{${placeholderToIndexMap[match.group(0)!]}}');
+  }
+
+  static List<String> _decodeAnalyzerCode(Object? value) {
+    if (value == null) {
+      return const [];
+    } else if (value is String) {
+      return [value];
+    } else if (value is List) {
+      return [for (var s in value) s as String];
+    } else {
+      throw 'Unrecognized analyzer code: $value';
+    }
+  }
+}
diff --git a/pkg/analyzer/tool/messages/generate.dart b/pkg/analyzer/tool/messages/generate.dart
index 3747771..d9b973c 100644
--- a/pkg/analyzer/tool/messages/generate.dart
+++ b/pkg/analyzer/tool/messages/generate.dart
@@ -14,7 +14,6 @@
 ///
 /// It is expected that 'pkg/front_end/tool/fasta generate-messages'
 /// has already been successfully run.
-import 'dart:convert';
 import 'dart:io';
 
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
@@ -25,6 +24,8 @@
 import 'package:path/path.dart';
 import 'package:yaml/yaml.dart' show loadYaml;
 
+import 'error_code_info.dart';
+
 main() async {
   await GeneratedContent.generateAll(analyzerPkgPath, allTargets);
 
@@ -61,22 +62,17 @@
 final String analyzerPkgPath =
     normalize(join(pkg_root.packageRoot, 'analyzer'));
 
-/// Pattern used by the front end to identify placeholders in error message
-/// strings.  TODO(paulberry): share this regexp (and the code for interpreting
-/// it) between the CFE and analyzer.
-final RegExp _placeholderPattern =
-    RegExp("#\([-a-zA-Z0-9_]+\)(?:%\([0-9]*\)\.\([0-9]+\))?");
-
 /// Return an entry containing 2 strings,
 /// the name of the class containing the error and the name of the error,
 /// or throw an exception if 'analyzerCode:' field is invalid.
-List<String> nameForEntry(Map entry) {
-  final analyzerCode = entry['analyzerCode'];
-  if (analyzerCode is String) {
-    if (!analyzerCode.startsWith('ParserErrorCode.')) {
+List<String> nameForEntry(ErrorCodeInfo entry) {
+  final analyzerCode = entry.analyzerCode;
+  if (analyzerCode.length == 1) {
+    var code = analyzerCode.single;
+    if (!code.startsWith('ParserErrorCode.')) {
       throw invalidAnalyzerCode;
     }
-    List<String> name = analyzerCode.split('.');
+    List<String> name = code.split('.');
     if (name.length != 2 || name[1].isEmpty) {
       throw invalidAnalyzerCode;
     }
@@ -86,11 +82,11 @@
 }
 
 class _SyntacticErrorGenerator {
-  final Map messagesYaml;
+  final Map<String, ErrorCodeInfo> messages;
   final String errorConverterSource;
   final String syntacticErrorsSource;
   final String parserSource;
-  final translatedEntries = <Map>[];
+  final translatedEntries = <ErrorCodeInfo>[];
   final translatedFastaErrorCodes = <String>{};
   final out = StringBuffer('''
 //
@@ -120,18 +116,18 @@
             joinAll(posix.split('lib/src/parser/parser.dart'))))
         .readAsStringSync();
 
-    return _SyntacticErrorGenerator._(messagesYaml, errorConverterSource,
-        syntacticErrorsSource, parserSource);
+    return _SyntacticErrorGenerator._(decodeCfeMessagesYaml(messagesYaml),
+        errorConverterSource, syntacticErrorsSource, parserSource);
   }
 
-  _SyntacticErrorGenerator._(this.messagesYaml, this.errorConverterSource,
+  _SyntacticErrorGenerator._(this.messages, this.errorConverterSource,
       this.syntacticErrorsSource, this.parserSource);
 
   void checkForManualChanges() {
     // Check for ParserErrorCodes that could be removed from
     // error_converter.dart now that those ParserErrorCodes are auto generated.
     int converterCount = 0;
-    for (Map entry in translatedEntries) {
+    for (ErrorCodeInfo entry in translatedEntries) {
       final name = nameForEntry(entry);
       final errorCode = name[1];
       if (errorConverterSource.contains('"$errorCode"')) {
@@ -151,7 +147,7 @@
     // Check that the public ParserErrorCodes have been updated
     // to reference the generated codes.
     int publicCount = 0;
-    for (Map entry in translatedEntries) {
+    for (ErrorCodeInfo entry in translatedEntries) {
       final name = nameForEntry(entry);
       final errorCode = name[1];
       if (!syntacticErrorsSource.contains(' _$errorCode')) {
@@ -176,7 +172,7 @@
 
   void generateErrorCodes() {
     final sortedErrorCodes = <String>[];
-    final entryMap = <String, Map>{};
+    final entryMap = <String, ErrorCodeInfo>{};
     for (var entry in translatedEntries) {
       final name = nameForEntry(entry);
       final errorCode = name[1];
@@ -193,28 +189,14 @@
       final className = nameForEntry(entry)[0];
       out.writeln();
       out.writeln('const $className _$errorCode =');
-      out.writeln('$className(');
-      out.writeln("'$errorCode',");
-      final placeholderToIndexMap = _computePlaceholderToIndexMap(entry);
-      out.writeln(
-          'r"${_convertTemplate(placeholderToIndexMap, entry['template'])}"');
-      final tip = entry['tip'];
-      if (tip is String) {
-        out.writeln(
-            ',correction: "${_convertTemplate(placeholderToIndexMap, tip)}"');
-      }
-      final hasPublishedDocs = entry['hasPublishedDocs'];
-      if (hasPublishedDocs is bool && hasPublishedDocs) {
-        out.writeln(',hasPublishedDocs:true');
-      }
-      out.writeln(');');
+      out.writeln(entry.toAnalyzerCode(className, errorCode));
     }
   }
 
   void generateFastaAnalyzerErrorCodeList() {
-    final sorted = List<Map?>.filled(translatedEntries.length, null);
+    final sorted = List<ErrorCodeInfo?>.filled(translatedEntries.length, null);
     for (var entry in translatedEntries) {
-      var index = entry['index'];
+      var index = entry.index;
       if (index is int && index >= 1 && index <= sorted.length) {
         if (sorted[index - 1] == null) {
           sorted[index - 1] = entry;
@@ -232,15 +214,14 @@
   }
 
   void generateFormatCode() {
-    messagesYaml.forEach((name, entry) {
-      if (entry is Map) {
-        if (entry['index'] is int) {
-          if (entry['analyzerCode'] is String) {
-            translatedFastaErrorCodes.add(name);
-            translatedEntries.add(entry);
-          } else {
-            throw invalidAnalyzerCode;
-          }
+    messages.forEach((name, entry) {
+      if (entry.index != null) {
+        // TODO(paulberry): handle multiple analyzer codes
+        if (entry.analyzerCode.length == 1) {
+          translatedFastaErrorCodes.add(name);
+          translatedEntries.add(entry);
+        } else {
+          throw invalidAnalyzerCode;
         }
       }
     });
@@ -258,14 +239,14 @@
       }
     }
 
-    String messageFromEntryTemplate(Map entry) {
-      String template = entry['template'];
+    String messageFromEntryTemplate(ErrorCodeInfo entry) {
+      String template = entry.template;
       String message = template.replaceAll(RegExp(r'#\w+'), '');
       return message;
     }
 
     // Remove entries that have already been translated
-    for (Map entry in translatedEntries) {
+    for (ErrorCodeInfo entry in translatedEntries) {
       messageToName.remove(messageFromEntryTemplate(entry));
     }
 
@@ -276,14 +257,12 @@
     // List the ParserErrorCodes that could easily be auto generated
     // but have not been already.
     final analyzerToFasta = <String, List<String>>{};
-    messagesYaml.forEach((fastaName, entry) {
-      if (entry is Map) {
-        final analyzerName = messageToName[messageFromEntryTemplate(entry)];
-        if (analyzerName != null) {
-          analyzerToFasta
-              .putIfAbsent(analyzerName, () => <String>[])
-              .add(fastaName);
-        }
+    messages.forEach((fastaName, entry) {
+      final analyzerName = messageToName[messageFromEntryTemplate(entry)];
+      if (analyzerName != null) {
+        analyzerToFasta
+            .putIfAbsent(analyzerName, () => <String>[])
+            .add(fastaName);
       }
     });
     if (analyzerToFasta.isNotEmpty) {
@@ -332,11 +311,12 @@
       for (String fastaErrorCode in sorted) {
         String analyzerCode = '';
         String template = '';
-        var entry = messagesYaml[fastaErrorCode];
-        if (entry is Map) {
-          if (entry['index'] is! int && entry['analyzerCode'] is String) {
-            analyzerCode = entry['analyzerCode'];
-            template = entry['template'];
+        var entry = messages[fastaErrorCode];
+        if (entry != null) {
+          // TODO(paulberry): handle multiple analyzer codes
+          if (entry.index == null && entry.analyzerCode.length == 1) {
+            analyzerCode = entry.analyzerCode.single;
+            template = entry.template;
           }
         }
         print('  ${fastaErrorCode.padRight(30)} --> $analyzerCode'
@@ -344,33 +324,4 @@
       }
     }
   }
-
-  /// Given a messages.yaml entry, come up with a mapping from placeholder
-  /// patterns in its message and tip strings to their corresponding indices.
-  Map<String, int> _computePlaceholderToIndexMap(Map<Object?, Object?> entry) {
-    var mapping = <String, int>{};
-    for (var key in const ['template', 'tip']) {
-      var value = entry[key];
-      if (value is! String) continue;
-      for (Match match in _placeholderPattern.allMatches(value)) {
-        // CFE supports a bunch of formatting options that we don't; make sure
-        // none of those are used.
-        if (match.group(0) != '#${match.group(1)}') {
-          throw 'Template string ${json.encode(entry)} contains unsupported '
-              'placeholder pattern ${json.encode(match.group(0))}';
-        }
-
-        mapping[match.group(0)!] ??= mapping.length;
-      }
-    }
-    return mapping;
-  }
-
-  /// Convert a CFE template string (which uses placeholders like `#string`) to
-  /// an analyzer template string (which uses placeholders like `{0}`).
-  String _convertTemplate(
-      Map<String, int> placeholderToIndexMap, String entry) {
-    return entry.replaceAllMapped(_placeholderPattern,
-        (match) => '{${placeholderToIndexMap[match.group(0)!]}}');
-  }
 }
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index e43b92a..f663b08 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -780,7 +780,8 @@
 ///
 /// Not all futures need to be awaited.
 /// The Dart linter has an optional ["unawaited futures" lint](https://dart-lang.github.io/linter/lints/unawaited_futures.html)
-/// which enforces that futures (expressions with a static type of [Future])
+/// which enforces that potential futures
+/// (expressions with a static type of [Future] or `Future?`)
 /// in asynchronous functions are handled *somehow*.
 /// If a particular future value doesn't need to be awaited,
 /// you can call `unawaited(...)` with it, which will avoid the lint,
@@ -797,8 +798,8 @@
 /// are *expected* to complete with a value.
 /// You can use [FutureExtensions.ignore] if you also don't want to know
 /// about errors from this future.
-@Since("2.14")
-void unawaited(Future<void> future) {}
+@Since("2.15")
+void unawaited(Future<void>? future) {}
 
 /// Convenience methods on futures.
 ///
diff --git a/tests/language/explicit_type_instantiation_parsing_test.dart b/tests/language/explicit_type_instantiation_parsing_test.dart
index f848e9b..e0584e7 100644
--- a/tests/language/explicit_type_instantiation_parsing_test.dart
+++ b/tests/language/explicit_type_instantiation_parsing_test.dart
@@ -292,20 +292,14 @@
   // [cfe] A comparison expression can't be an operand of another comparison expression.
   // [analyzer] SYNTACTIC_ERROR.EQUALITY_CANNOT_BE_EQUALITY_OPERAND
 
-  // Parsed as a generic instantiation, but `v` is not generic function or type.
-  // Would be valid if parsed as operators.
+  // Parsed as a generic invocation. Valid because of the `call` extension
+  // method on `Object?`.
   expect1(v < X, X > (2));
-  //        ^^^^^^^^
-  // [cfe] unspecified
-  // [analyzer] unspecified
 
-  // Parsed as a generic instantiation, but `d` is not generic function or type.
-  // Being dynamic doesn't help.
-  // Would be valid if parsed as operators.
+  // Parsed as a generic invocation. Valid because this is an *invocation*
+  // rather than an *instantiation*. We don't allow instantiation on `dynamic`,
+  // but we do allow calling.
   expect1(d < X, X > (2));
-  //        ^^^^^^^^
-  // [cfe] unspecified
-  // [analyzer] unspecified
 
   // Valid only if parenthesized.
   expect1((Z < X, X >) * 2);
diff --git a/tests/lib/async/unawaited_test.dart b/tests/lib/async/unawaited_test.dart
index dc095cc..5ed05af 100644
--- a/tests/lib/async/unawaited_test.dart
+++ b/tests/lib/async/unawaited_test.dart
@@ -14,13 +14,16 @@
 
 void testUnawaited() {
   // Exists where expected.
-  prefix.unawaited.expectStaticType<Exactly<void Function(Future<Object?>)>>();
+  prefix.unawaited.expectStaticType<Exactly<void Function(Future<Object?>?)>>();
 
   var future = Future<int>.value(42);
   captureStaticType(unawaited(future), <T>(value) {
     Expect.equals(typeOf<void>(), T);
   });
 
+  Future<Never>? noFuture = null;
+  unawaited(noFuture); // Doesn't throw on null.
+
   asyncStart();
   // Unawaited futures still throw.
   {
diff --git a/tests/lib_2/async/unawaited_test.dart b/tests/lib_2/async/unawaited_test.dart
index 16bd285..5554a48 100644
--- a/tests/lib_2/async/unawaited_test.dart
+++ b/tests/lib_2/async/unawaited_test.dart
@@ -23,6 +23,9 @@
     Expect.equals(typeOf<void>(), T);
   });
 
+  Future<Never> noFuture = null;
+  unawaited(noFuture); // Doesn't throw on `null`.
+
   asyncStart();
   // Unawaited futures still throw.
   {
diff --git a/tools/VERSION b/tools/VERSION
index 4291b21..9ad0a02 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 152
+PRERELEASE 153
 PRERELEASE_PATCH 0
\ No newline at end of file