Version 3.10.0-237.0.dev

Merge eb938ee4bbca62b27e13859d17b8c0f29c12c9bd into dev
diff --git a/pkg/analyzer/lib/src/binary/binary_reader.dart b/pkg/analyzer/lib/src/binary/binary_reader.dart
index 97e6d66..23c2531 100644
--- a/pkg/analyzer/lib/src/binary/binary_reader.dart
+++ b/pkg/analyzer/lib/src/binary/binary_reader.dart
@@ -6,6 +6,7 @@
 import 'dart:typed_data';
 
 import 'package:_fe_analyzer_shared/src/scanner/string_canonicalizer.dart';
+import 'package:analyzer/src/binary/binary_writer.dart';
 import 'package:analyzer/src/binary/string_table.dart';
 
 /// Reader for binary formats.
@@ -23,10 +24,6 @@
 
   BinaryReader(this.bytes);
 
-  void createStringTable(int offset) {
-    _stringTable = StringTable(bytes: bytes, startOffset: offset);
-  }
-
   /// Create a new instance with the given [offset].
   /// It shares the same bytes and string reader.
   BinaryReader fork(int offset) {
@@ -36,6 +33,29 @@
     return result;
   }
 
+  void initializeStringTableAtOffset(int offset) {
+    _stringTable = StringTable(bytes: bytes, startOffset: offset);
+  }
+
+  /// Initializes the string table by reading its offset from the end of the
+  /// buffer.
+  ///
+  /// This is the counterpart to [BinaryWriter.writeStringTableAtEnd]. That
+  /// method writes the string table data, and then appends a `uint32` offset
+  /// pointing to the beginning of that data. This method reads that final
+  /// offset to initialize the reader's string table, preserving the reader's
+  /// current position.
+  void initializeStringTableFromEnd() {
+    var savedOffset = offset;
+    try {
+      offset = bytes.length - 4 * 1;
+      var stringTableOffset = readUint32();
+      initializeStringTableAtOffset(stringTableOffset);
+    } finally {
+      offset = savedOffset;
+    }
+  }
+
   @pragma("vm:prefer-inline")
   bool readBool() {
     return readByte() != 0;
diff --git a/pkg/analyzer/lib/src/binary/binary_writer.dart b/pkg/analyzer/lib/src/binary/binary_writer.dart
index 650dec7..1b14a81 100644
--- a/pkg/analyzer/lib/src/binary/binary_writer.dart
+++ b/pkg/analyzer/lib/src/binary/binary_writer.dart
@@ -5,6 +5,9 @@
 import 'dart:convert';
 import 'dart:typed_data';
 
+import 'package:analyzer/src/binary/binary_reader.dart';
+import 'package:analyzer/src/binary/string_table.dart';
+
 /// Buffered writer for binary formats.
 class BinaryWriter {
   static const int _SIZE = 128 * 1024;
@@ -21,10 +24,19 @@
   final Float64List _doubleBuffer = Float64List(1);
   late final Uint8List _doubleBufferUint8 = _doubleBuffer.buffer.asUint8List();
 
-  BinaryWriter();
+  final StringIndexer _stringIndexer;
+
+  BinaryWriter() : this.withStringIndexer(stringIndexer: StringIndexer());
+
+  BinaryWriter.withStringIndexer({required StringIndexer stringIndexer})
+    : _stringIndexer = stringIndexer;
 
   int get offset => _builder.length + _length;
 
+  BinaryWriter clone() {
+    return BinaryWriter.withStringIndexer(stringIndexer: _stringIndexer);
+  }
+
   Uint8List takeBytes() {
     _builder.add(_buffer.sublist(0, _length));
     return _builder.takeBytes();
@@ -162,6 +174,15 @@
     }
   }
 
+  void writeOptionalStringReference(String? value) {
+    if (value != null) {
+      writeBool(true);
+      writeStringReference(value);
+    } else {
+      writeBool(false);
+    }
+  }
+
   void writeOptionalStringUtf8(String? value) {
     if (value != null) {
       writeBool(true);
@@ -198,6 +219,30 @@
     }
   }
 
+  void writeStringList(List<String> values) {
+    writeList(values, writeStringReference);
+  }
+
+  void writeStringReference(String value) {
+    var index = _stringIndexer[value];
+    writeUint30(index);
+  }
+
+  /// Writes the string table and its starting offset.
+  ///
+  /// This method writes the collected string data first, then writes the
+  /// `uint32` offset where that data begins.
+  ///
+  /// It must be called after all other data has been written and immediately
+  /// before [takeBytes]. This ensures the last 4 bytes reliably point to
+  /// the string table, which a reader will use to decode string references.
+  ///
+  /// This is the counterpart to [BinaryReader.initializeStringTableFromEnd].
+  void writeStringTableAtEnd() {
+    var offset = _stringIndexer.write(this);
+    writeUint32(offset);
+  }
+
   /// Write the [value] as UTF8 encoded byte array.
   void writeStringUtf8(String value) {
     var bytes = const Utf8Encoder().convert(value);
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 1f576b0..cfafa16 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -106,7 +106,7 @@
 // TODO(scheglov): Clean up the list of implicitly analyzed files.
 class AnalysisDriver {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 559;
+  static const int DATA_VERSION = 560;
 
   /// 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/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index afad7fc..9557328 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -5,7 +5,6 @@
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/binary/string_table.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/summary2/ast_binary_flags.dart';
 import 'package:analyzer/src/summary2/ast_binary_tag.dart';
@@ -15,13 +14,8 @@
 /// Serializer of fully resolved ASTs.
 class AstBinaryWriter extends ThrowingAstVisitor<void> {
   final ResolutionSink _sink;
-  final StringIndexer _stringIndexer;
 
-  AstBinaryWriter({
-    required ResolutionSink sink,
-    required StringIndexer stringIndexer,
-  }) : _sink = sink,
-       _stringIndexer = stringIndexer;
+  AstBinaryWriter({required ResolutionSink sink}) : _sink = sink;
 
   @override
   void visitAdjacentStrings(AdjacentStrings node) {
@@ -990,8 +984,7 @@
   }
 
   void _writeStringReference(String string) {
-    var index = _stringIndexer[string];
-    _writeUint30(index);
+    _sink.writeStringReference(string);
   }
 
   @pragma("vm:prefer-inline")
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 6f4f552..7db535a 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -54,7 +54,7 @@
     var librariesOffset = _reader.readUint32();
     var referencesOffset = _reader.readUint32();
     var stringsOffset = _reader.readUint32();
-    _reader.createStringTable(stringsOffset);
+    _reader.initializeStringTableAtOffset(stringsOffset);
 
     var referenceReader = _ReferenceReader(
       elementFactory,
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index d732630..06f5d0f 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -37,7 +37,7 @@
   /// require any other declaration read it later. For example type inference
   /// errors, or whether a parameter inherits `covariant`, or a class is
   /// simply bounded.
-  late _SummaryDataWriter _sink = _SummaryDataWriter(
+  late BinaryWriter _sink = BinaryWriter.withStringIndexer(
     stringIndexer: _stringIndexer,
   );
 
@@ -74,13 +74,13 @@
 
     var librariesOffset = _sink.offset;
     _sink.writeList<_Library>(_libraries, (library) {
-      _sink._writeStringReference(library.uriStr);
+      _sink.writeStringReference(library.uriStr);
       _sink.writeUint30(library.offset);
     });
 
     var referencesOffset = _sink.offset;
     _sink.writeUint30List(_references._referenceParents);
-    _sink._writeStringList(_references._referenceNames);
+    _sink.writeStringList(_references._referenceNames);
     _references._clearIndexes();
 
     var stringTableOffset = _stringIndexer.write(_sink);
@@ -99,7 +99,7 @@
     var libraryOffset = _sink.offset;
 
     // Write non-resolution data for the library.
-    _sink._writeStringReference(libraryElement.name);
+    _sink.writeStringReference(libraryElement.name);
     _writeFeatureSet(libraryElement.featureSet);
     libraryElement.writeModifiers(_sink);
     _writeLanguageVersion(libraryElement.languageVersion);
@@ -205,7 +205,7 @@
 
   void _writeConstructorFragment(ConstructorFragmentImpl fragment) {
     _writeTemplateFragment(fragment, () {
-      _sink._writeOptionalStringReference(fragment.typeName);
+      _sink.writeOptionalStringReference(fragment.typeName);
       _writeTypeParameters(fragment.typeParameters, () {
         _sink.writeList(fragment.formalParameters, _writeParameterElement);
         _resolutionSink._writeMetadata(fragment.metadata);
@@ -219,17 +219,17 @@
 
   void _writeDirectiveUri(DirectiveUri element) {
     void writeWithUriString(DirectiveUriWithRelativeUriString element) {
-      _sink._writeStringReference(element.relativeUriString);
+      _sink.writeStringReference(element.relativeUriString);
     }
 
     void writeWithRelativeUri(DirectiveUriWithRelativeUri element) {
       writeWithUriString(element);
-      _sink._writeStringReference('${element.relativeUri}');
+      _sink.writeStringReference('${element.relativeUri}');
     }
 
     void writeWithSource(DirectiveUriWithSource element) {
       writeWithRelativeUri(element);
-      _sink._writeStringReference('${element.source.uri}');
+      _sink.writeStringReference('${element.source.uri}');
     }
 
     if (element is DirectiveUriWithLibrary) {
@@ -432,7 +432,7 @@
       _resolutionSink.writeMap(
         info,
         writeKey: (key) {
-          _resolutionSink._writeStringReference(key);
+          _resolutionSink.writeStringReference(key);
         },
         writeValue: (value) {
           _resolutionSink._writeElementList(value.conflictingFields);
@@ -468,7 +468,7 @@
   }
 
   void _writeFragmentName(Fragment fragment) {
-    _sink._writeOptionalStringReference(fragment.name);
+    _sink.writeOptionalStringReference(fragment.name);
   }
 
   void _writeFragments(List<FragmentImpl> fragments) {
@@ -591,7 +591,7 @@
 
   void _writeMixinFragment(MixinFragmentImpl fragment) {
     _writeTemplateFragment(fragment, () {
-      _sink._writeStringList(fragment.superInvokedNames);
+      _sink.writeStringList(fragment.superInvokedNames);
 
       _writeTypeParameters(fragment.typeParameters, () {
         _resolutionSink._writeMetadata(fragment.metadata);
@@ -611,12 +611,12 @@
       case HideElementCombinator():
         _sink.writeByte(Tag.HideCombinator);
         _sink.writeList<String>(combinator.hiddenNames, (name) {
-          _sink._writeStringReference(name);
+          _sink.writeStringReference(name);
         });
       case ShowElementCombinator():
         _sink.writeByte(Tag.ShowCombinator);
         _sink.writeList<String>(combinator.shownNames, (name) {
-          _sink._writeStringReference(name);
+          _sink.writeStringReference(name);
         });
     }
   }
@@ -868,14 +868,15 @@
   BundleWriterResult({required this.resolutionBytes});
 }
 
-class ResolutionSink extends _SummaryDataWriter {
+class ResolutionSink extends BinaryWriter {
   final _BundleWriterReferences _references;
   final _LocalElementIndexer localElements = _LocalElementIndexer();
 
   ResolutionSink({
     required super.stringIndexer,
     required _BundleWriterReferences references,
-  }) : _references = references;
+  }) : _references = references,
+       super.withStringIndexer();
 
   void withTypeParameters(
     List<TypeParameterElementImpl> typeParameters,
@@ -1010,7 +1011,7 @@
   }
 
   void _writeElementName(Element element) {
-    _writeOptionalStringReference(element.name);
+    writeOptionalStringReference(element.name);
   }
 
   void _writeFormalParameters(
@@ -1058,7 +1059,7 @@
   }
 
   void _writeFragmentName(Fragment fragment) {
-    _writeOptionalStringReference(fragment.name);
+    writeOptionalStringReference(fragment.name);
   }
 
   void _writeFunctionType(FunctionTypeImpl type) {
@@ -1080,7 +1081,7 @@
   }
 
   void _writeNode(AstNode node) {
-    var astWriter = AstBinaryWriter(sink: this, stringIndexer: _stringIndexer);
+    var astWriter = AstBinaryWriter(sink: this);
     node.accept(astWriter);
   }
 
@@ -1105,7 +1106,7 @@
     });
 
     writeList<RecordTypeNamedField>(type.namedFields, (field) {
-      _writeStringReference(field.name);
+      writeStringReference(field.name);
       writeType(field.type);
     });
 
@@ -1266,16 +1267,13 @@
   }
 }
 
-class _SummaryDataWriter extends BinaryWriter {
-  final StringIndexer _stringIndexer;
-
-  _SummaryDataWriter({required StringIndexer stringIndexer})
-    : _stringIndexer = stringIndexer;
-
-  _SummaryDataWriter clone() {
-    return _SummaryDataWriter(stringIndexer: _stringIndexer);
+extension on Map<FragmentImpl, int> {
+  int getId(FragmentImpl fragment) {
+    return this[fragment] ??= length;
   }
+}
 
+extension _BinaryWriterExtension on BinaryWriter {
   void _writeFormalParameterKind(FormalParameterFragmentImpl p) {
     if (p.isRequiredPositional) {
       writeByte(Tag.ParameterKindRequiredPositional);
@@ -1304,36 +1302,12 @@
     }
   }
 
-  void _writeOptionalStringReference(String? value) {
-    if (value != null) {
-      writeBool(true);
-      _writeStringReference(value);
-    } else {
-      writeBool(false);
-    }
-  }
-
-  void _writeStringList(List<String> values) {
-    writeList(values, _writeStringReference);
-  }
-
-  void _writeStringReference(String string) {
-    var index = _stringIndexer[string];
-    writeUint30(index);
-  }
-
   void _writeTopLevelInferenceError(TopLevelInferenceError? error) {
     if (error != null) {
       writeByte(error.kind.index);
-      _writeStringList(error.arguments);
+      writeStringList(error.arguments);
     } else {
       writeByte(TopLevelInferenceErrorKind.none.index);
     }
   }
 }
-
-extension on Map<FragmentImpl, int> {
-  int getId(FragmentImpl fragment) {
-    return this[fragment] ??= length;
-  }
-}
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
index ef744d6..9b1c249 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
@@ -125,7 +125,6 @@
 
 const _Protected protected = _Protected();
 
-@experimental
 const _Redeclare redeclare = _Redeclare();
 
 const _Reopen reopen = _Reopen();
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index d1bf1fa..0f4cd10 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -261,40 +261,36 @@
 @Since("2.1")
 export 'dart:async' show Future, Stream;
 
-const deprecated = const Deprecated("next release");
+const Deprecated deprecated = Deprecated("next release");
 
-const override = const _Override();
+const Object override = _Override();
 
 external bool identical(Object? a, Object? b);
 
 void print(Object? object) {}
 
 class ArgumentError extends Error {
-  ArgumentError([message]);
+  ArgumentError([dynamic message, @Since("2.14") String? name]);
 
-  @Since("2.1")
-  static T checkNotNull<@Since("2.8") T>(T? argument, [String? name]) => argument!;
+  static T checkNotNull<T>(T? argument, [String? name]) => argument!;
 }
 
 abstract final class BigInt implements Comparable<BigInt> {
-  int compareTo(BigInt other) => 0;
-  static BigInt parse(String source, {int? radix}) => throw 0;
+  int compareTo(BigInt other);
+  external static BigInt parse(String source, {int? radix});
 }
 
-abstract final class bool extends Object {
+final class bool {
   external const factory bool.fromEnvironment(String name,
       {bool defaultValue = false});
 
   external const factory bool.hasEnvironment(String name);
 
-  @Since("2.1")
-  bool operator &(bool other);
+  bool operator &(bool other) => throw 0;
 
-  @Since("2.1")
-  bool operator |(bool other);
+  bool operator |(bool other) => throw 0;
 
-  @Since("2.1")
-  bool operator ^(bool other);
+  bool operator ^(bool other) => throw 0;
 }
 
 abstract class Comparable<T> {
@@ -304,14 +300,15 @@
 
 typedef Comparator<T> = int Function(T a, T b);
 
-class DateTime extends Object {
+class DateTime implements Comparable<DateTime> {
   external DateTime._now();
   DateTime.now() : this._now();
+  external int compareTo(DateTime other);
   external bool isBefore(DateTime other);
   external int get millisecondsSinceEpoch;
 }
 
-class Deprecated extends Object {
+class Deprecated {
   final String? message;
   final _DeprecationKind _kind;
   const Deprecated(this.message) : _kind = _DeprecationKind.use;
@@ -329,7 +326,7 @@
   use, implement, extend, subclass, instantiate, mixin, optional;
 }
 
-class pragma {
+final class pragma {
   final String name;
   final Object? options;
   const pragma(this.name, [this.options]);
@@ -404,7 +401,7 @@
   external StackTrace? get stackTrace;
 }
 
-class Exception {
+abstract interface class Exception {
   factory Exception([var message]) {
     throw 0;
   }
@@ -437,8 +434,7 @@
   String toString();
   int truncate();
 
-  external static int parse(String source,
-      {int? radix, @deprecated int onError(String source)?});
+  external static int parse(String source, {int? radix});
 
   external static int? tryParse(String source, {int? radix});
 }
@@ -541,7 +537,7 @@
   V? remove(Object? key);
 }
 
-final class Null extends Object {
+final class Null {
   factory Null._uninstantiable() {
     throw 0;
   }
@@ -636,11 +632,11 @@
       throw '';
 }
 
-abstract class Sink {
+abstract interface class Sink<T> {
   void close();
 }
 
-class StackTrace {}
+abstract interface class StackTrace {}
 
 abstract final class String implements Comparable<String>, Pattern {
   external factory String.fromCharCodes(Iterable<int> charCodes,
@@ -652,9 +648,9 @@
       {String defaultValue = ""});
 
   List<int> get codeUnits;
-  bool get isEmpty => false;
-  bool get isNotEmpty => false;
-  int get length => 0;
+  bool get isEmpty;
+  bool get isNotEmpty;
+  int get length;
 
   bool operator ==(Object other);
   String operator [](int index);
@@ -662,14 +658,14 @@
   String operator *(int times);
 
   int codeUnitAt(int index);
-  bool contains(String other, [int startIndex = 0]);
+  bool contains(Pattern other, [int startIndex = 0]);
   int indexOf(Pattern pattern, [int start = 0]);
   int lastIndexOf(Pattern pattern, [int? start]);
   bool startsWith(Pattern pattern, [int index = 0]);
   List<String> split(Pattern pattern);
   String splitMapJoin(Pattern pattern,
       {String Function(Match)? onMatch, String Function(String)? onNonMatch});
-  String substring(int startIndex, [int? endIndex]);
+  String substring(int start, [int? end]);
   String toLowerCase();
   String toUpperCase();
 }
@@ -684,15 +680,15 @@
   const factory Symbol(String name) = internal.Symbol;
 }
 
-class Type {}
+abstract interface class Type {}
 
 class TypeError extends Error {}
 
-class UnsupportedError {
+class UnsupportedError extends Error {
   UnsupportedError(String message);
 }
 
-class Uri {
+abstract interface class Uri {
   factory Uri({
     String? scheme,
     String? userInfo,
diff --git a/pkg/analyzer_testing/lib/mock_packages/package_content/meta/lib/meta.dart b/pkg/analyzer_testing/lib/mock_packages/package_content/meta/lib/meta.dart
index ca330d7..d4d25ad 100644
--- a/pkg/analyzer_testing/lib/mock_packages/package_content/meta/lib/meta.dart
+++ b/pkg/analyzer_testing/lib/mock_packages/package_content/meta/lib/meta.dart
@@ -434,7 +434,6 @@
 ///   member of an extension type (a method, operator, getter, or setter) or
 /// * is applied to a member that does not redeclare a member from either the
 ///   extended type or a superinterface.
-@experimental
 const _Redeclare redeclare = _Redeclare();
 
 /// Annotation for intentionally loosening restrictions on subtyping that would
diff --git a/pkg/linter/test/rules/avoid_type_to_string_test.dart b/pkg/linter/test/rules/avoid_type_to_string_test.dart
index 53342bb..8ece688 100644
--- a/pkg/linter/test/rules/avoid_type_to_string_test.dart
+++ b/pkg/linter/test/rules/avoid_type_to_string_test.dart
@@ -99,110 +99,110 @@
     );
   }
 
-  test_typeExtendingType_withToStringOverride() async {
+  test_typeImplementsType_withToStringOverride() async {
     await assertNoDiagnostics(r'''
 mixin M {
   @override
   String toString() => '';
 }
-class Type2 extends Type with M {
+class Type2 with M implements Type {
   String get x => toString();
 }
 ''');
   }
 
-  test_typeThatExtendsType() async {
+  test_typeThatExtendsTypeThatImplementsType() async {
     await assertDiagnostics(
       r'''
-var x = Type2().toString();
-class Type2 extends Type {}
+var x = Type3().toString();
+class Type2 implements Type {}
+class Type3 extends Type2 {}
 ''',
       [lint(16, 8)],
     );
   }
 
-  test_typeThatExtendsType_explicitThis() async {
+  test_typeThatImplementsType() async {
     await assertDiagnostics(
       r'''
-class Type2 extends Type {
+var x = Type2().toString();
+class Type2 implements Type {}
+''',
+      [lint(16, 8)],
+    );
+  }
+
+  test_typeThatImplementsType_explicitThis() async {
+    await assertDiagnostics(
+      r'''
+class Type2 implements Type {
   late var x = this.toString();
 }
 ''',
-      [lint(47, 8)],
+      [lint(50, 8)],
     );
   }
 
-  test_typeThatExtendsType_implicitThis() async {
+  test_typeThatImplementsType_implicitThis() async {
     await assertDiagnostics(
       r'''
-class Type2 extends Type {
+class Type2 implements Type {
   late var x = toString();
 }
 ''',
-      [lint(42, 8)],
+      [lint(45, 8)],
     );
   }
 
-  test_typeThatExtendsType_super() async {
+  test_typeThatImplementsType_super() async {
     await assertDiagnostics(
       r'''
-class Type2 extends Type {
+class Type2 implements Type {
   late var x = super.toString();
 }
 ''',
-      [lint(48, 8)],
+      [lint(51, 8)],
     );
   }
 
-  test_typeThatExtendsType_tearoff() async {
+  test_typeThatImplementsType_tearoff() async {
     await assertDiagnostics(
       r'''
-class Type2 extends Type {}
+class Type2 implements Type {}
 void f(Type2 t) {
   foo(t.toString);
 }
 void foo(String Function() p) {}
 ''',
-      [lint(54, 8)],
+      [lint(57, 8)],
     );
   }
 
-  test_typeThatExtendsType_tearoff_explicitThis() async {
+  test_typeThatImplementsType_tearoff_explicitThis() async {
     await assertDiagnostics(
       r'''
-class Type2 extends Type {
+class Type2 implements Type {
   void f() {
     foo(this.toString);
   }
   void foo(String Function() p) {}
 }
 ''',
-      [lint(53, 8)],
+      [lint(56, 8)],
     );
   }
 
-  test_typeThatExtendsType_tearoff_implicitThis() async {
+  test_typeThatImplementsType_tearoff_implicitThis() async {
     await assertDiagnostics(
       r'''
-class Type2 extends Type {
+class Type2 implements Type {
   void f() {
     foo(toString);
   }
   void foo(String Function() p) {}
 }
 ''',
-      [lint(48, 8)],
-    );
-  }
-
-  test_typeThatExtendsTypeThatExtendsType() async {
-    await assertDiagnostics(
-      r'''
-var x = Type3().toString();
-class Type2 extends Type {}
-class Type3 extends Type2 {}
-''',
-      [lint(16, 8)],
+      [lint(51, 8)],
     );
   }
 }
diff --git a/pkg/meta/CHANGELOG.md b/pkg/meta/CHANGELOG.md
index 8032607..3c1326e 100644
--- a/pkg/meta/CHANGELOG.md
+++ b/pkg/meta/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.18.0-dev
+
+- The `@redeclare` annotation is no longer considered experimental.
+
 ## 1.17.0
 
 - Introduce `@awaitNotRequired` to annotate `Future`-returning functions and
diff --git a/pkg/meta/lib/meta.dart b/pkg/meta/lib/meta.dart
index 59faf8a..2a2909d 100644
--- a/pkg/meta/lib/meta.dart
+++ b/pkg/meta/lib/meta.dart
@@ -436,7 +436,6 @@
 ///   member of an extension type (a method, operator, getter, or setter) or
 /// * is applied to a member that does not redeclare a member from either the
 ///   extended type or a superinterface.
-@experimental
 const _Redeclare redeclare = _Redeclare();
 
 /// Annotation for intentionally loosening restrictions on subtyping that would
diff --git a/pkg/meta/pubspec.yaml b/pkg/meta/pubspec.yaml
index 50ac74d..171cb40 100644
--- a/pkg/meta/pubspec.yaml
+++ b/pkg/meta/pubspec.yaml
@@ -1,7 +1,7 @@
 name: meta
 # Note, because version `2.0.0` was mistakenly released,
 # the next major version must be `3.x.y`.
-version: 1.17.0
+version: 1.18.0-dev
 description: >-
  Annotations used to express developer intentions that can't otherwise be
  deduced by statically analyzing source code.
diff --git a/tools/VERSION b/tools/VERSION
index d83511d..f56b642 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 3
 MINOR 10
 PATCH 0
-PRERELEASE 236
+PRERELEASE 237
 PRERELEASE_PATCH 0
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 91c117c..c14ec23 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -1440,12 +1440,17 @@
     {
       "builders": [
         "vm-asan-linux-release-x64",
+        "vm-asan-mac-release-arm64",
         "vm-asan-mac-release-x64",
         "vm-asan-win-release-x64",
         "vm-msan-linux-release-x64",
         "vm-tsan-linux-release-x64",
         "vm-tsan-mac-release-arm64",
-        "vm-ubsan-linux-release-x64"
+        "vm-tsan-mac-release-x64",
+        "vm-ubsan-linux-release-x64",
+        "vm-ubsan-mac-release-arm64",
+        "vm-ubsan-mac-release-x64",
+        "vm-ubsan-win-release-x64"
       ],
       "meta": {
         "description": "This configuration is used by the sanitizers (high capacity machine pools)."