Version 3.9.0-304.0.dev

Merge a3b7c6f7fc9d09c6b70edf725d3b334af4a5998f into dev
diff --git a/DEPS b/DEPS
index 0757614..605b075 100644
--- a/DEPS
+++ b/DEPS
@@ -100,7 +100,7 @@
   "boringssl_rev": "be5be0a4f5ebf00da151a06860deb11a0ffb609f",
   "browser-compat-data_tag": "ac8cae697014da1ff7124fba33b0b4245cc6cd1b", # v1.0.22
   "cpu_features_rev": "936b9ab5515dead115606559502e3864958f7f6e",
-  "devtools_rev": "53b9620798ff824f016add0fa6c25e9cc399ea0b",
+  "devtools_rev": "131c9de7c067973d314b2684939c95e0a82b2bdb",
   # Use the SHA found in `flutter-candidate.txt` in the devtools repo.
   "flutter_rev": "36ea2bdeab611e908967b6fa57659998f600a2cb",
   "icu_rev": "43953f57b037778a1b8005564afabe214834f7bd",
diff --git a/pkg/analysis_server_plugin/tool/api/generate.dart b/pkg/analysis_server_plugin/tool/api/generate.dart
index d820826..4210c01 100644
--- a/pkg/analysis_server_plugin/tool/api/generate.dart
+++ b/pkg/analysis_server_plugin/tool/api/generate.dart
@@ -14,6 +14,10 @@
   await GeneratedContent.generateAll(analyzerTestingPkgPath, allTargets);
 }
 
+/// A list of all targets generated by this code generator.
+final List<GeneratedContent> allTargets =
+    allTargetsForPackage('analysis_server_plugin');
+
 /// The path to the `analyzer_testing` package.
 final String analyzerTestingPkgPath = normalize(
   join(pkg_root.packageRoot, 'analysis_server_plugin'),
diff --git a/pkg/analysis_server_plugin/tool/api/generate_test.dart b/pkg/analysis_server_plugin/tool/api/generate_test.dart
index f873279..510e8ea 100644
--- a/pkg/analysis_server_plugin/tool/api/generate_test.dart
+++ b/pkg/analysis_server_plugin/tool/api/generate_test.dart
@@ -5,7 +5,6 @@
 // This test verifies that all files generated by `generate.dart` are up to
 // date.
 
-import 'package:analyzer_utilities/tool/api.dart';
 import 'package:analyzer_utilities/tools.dart';
 import 'package:path/path.dart';
 
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 9bd4c84..8ad0ee75 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -728,17 +728,6 @@
   }
 }
 
-/// A `LocalVariableElement` for a local 'const' variable that has an
-/// initializer.
-class ConstLocalVariableFragmentImpl extends LocalVariableFragmentImpl {
-  /// Initialize a newly created local variable element to have the given [name]
-  /// and [offset].
-  ConstLocalVariableFragmentImpl({
-    required super.name2,
-    required super.nameOffset,
-  });
-}
-
 class ConstructorElementImpl extends ExecutableElementImpl
     with
         FragmentedExecutableElementMixin<ConstructorFragmentImpl>,
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 2404263..5ca8c03 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -1529,18 +1529,10 @@
       variable as VariableDeclarationImpl;
       var nameToken = variable.name;
 
-      LocalVariableFragmentImpl fragment;
-      if (isConst && variable.initializer != null) {
-        fragment = ConstLocalVariableFragmentImpl(
-          name2: _getFragmentName(nameToken),
-          nameOffset: nameToken.offset,
-        );
-      } else {
-        fragment = LocalVariableFragmentImpl(
-          name2: _getFragmentName(nameToken),
-          nameOffset: nameToken.offset,
-        );
-      }
+      var fragment = LocalVariableFragmentImpl(
+        name2: _getFragmentName(nameToken),
+        nameOffset: nameToken.offset,
+      );
       variable.declaredFragment = fragment;
       _elementHolder.enclose(fragment);
       _define(fragment.element);
diff --git a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
index 6c380f8..b7a5d88 100644
--- a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
@@ -77,7 +77,7 @@
     // Initializers of top-level variables and fields are already included
     // into elements during linking.
     if (element is LocalVariableElementImpl && element.isConst) {
-      var fragment = element.firstFragment as ConstLocalVariableFragmentImpl;
+      var fragment = element.firstFragment;
       fragment.constantInitializer = initializer;
     }
 
diff --git a/pkg/analyzer/tool/api/generate.dart b/pkg/analyzer/tool/api/generate.dart
index d27cdee..2bc86e7 100644
--- a/pkg/analyzer/tool/api/generate.dart
+++ b/pkg/analyzer/tool/api/generate.dart
@@ -14,6 +14,9 @@
   await GeneratedContent.generateAll(analyzerPkgPath, allTargets);
 }
 
+/// A list of all targets generated by this code generator.
+final List<GeneratedContent> allTargets = allTargetsForPackage('analyzer');
+
 /// The path to the `analyzer` package.
 final String analyzerPkgPath = normalize(
   join(pkg_root.packageRoot, 'analyzer'),
diff --git a/pkg/analyzer/tool/api/generate_test.dart b/pkg/analyzer/tool/api/generate_test.dart
index b1275cf..180c11e 100644
--- a/pkg/analyzer/tool/api/generate_test.dart
+++ b/pkg/analyzer/tool/api/generate_test.dart
@@ -5,7 +5,6 @@
 // This test verifies that all files generated by `generate.dart` are up to
 // date.
 
-import 'package:analyzer_utilities/tool/api.dart';
 import 'package:analyzer_utilities/tools.dart';
 import 'package:path/path.dart';
 
diff --git a/pkg/analyzer_testing/tool/api/generate.dart b/pkg/analyzer_testing/tool/api/generate.dart
index 4486f9f..a9a96cc 100644
--- a/pkg/analyzer_testing/tool/api/generate.dart
+++ b/pkg/analyzer_testing/tool/api/generate.dart
@@ -14,6 +14,11 @@
   await GeneratedContent.generateAll(analyzerTestingPkgPath, allTargets);
 }
 
+/// A list of all targets generated by this code generator.
+final List<GeneratedContent> allTargets = allTargetsForPackage(
+  'analyzer_testing',
+);
+
 /// The path to the `analyzer_testing` package.
 final String analyzerTestingPkgPath = normalize(
   join(pkg_root.packageRoot, 'analyzer_testing'),
diff --git a/pkg/analyzer_testing/tool/api/generate_test.dart b/pkg/analyzer_testing/tool/api/generate_test.dart
index f873279..510e8ea 100644
--- a/pkg/analyzer_testing/tool/api/generate_test.dart
+++ b/pkg/analyzer_testing/tool/api/generate_test.dart
@@ -5,7 +5,6 @@
 // This test verifies that all files generated by `generate.dart` are up to
 // date.
 
-import 'package:analyzer_utilities/tool/api.dart';
 import 'package:analyzer_utilities/tools.dart';
 import 'package:path/path.dart';
 
diff --git a/pkg/analyzer_utilities/lib/tool/api.dart b/pkg/analyzer_utilities/lib/tool/api.dart
index b7d61f1..06439bc 100644
--- a/pkg/analyzer_utilities/lib/tool/api.dart
+++ b/pkg/analyzer_utilities/lib/tool/api.dart
@@ -18,27 +18,23 @@
 import 'package:analyzer_utilities/tools.dart';
 import 'package:collection/collection.dart';
 
-/// A list of all targets generated by this code generator.
-final List<GeneratedContent> allTargets = [
-  GeneratedFile('api.txt', computeApiTxtContents),
+/// Computes a list of all targets generated by this code generator for a given
+/// package.
+List<GeneratedContent> allTargetsForPackage(String pkgName) => [
+  GeneratedFile('api.txt', (pkgPath) async {
+    var provider = PhysicalResourceProvider.INSTANCE;
+    var collection = AnalysisContextCollection(
+      includedPaths: [pkgPath],
+      resourceProvider: provider,
+    );
+    var context = collection.contexts.first;
+    var publicApi = ApiDescription(pkgName);
+    var stringBuffer = StringBuffer();
+    _printNodes(stringBuffer, await publicApi.build(context));
+    return stringBuffer.toString();
+  }),
 ];
 
-/// Computes what should be written to the `api.txt` file.
-Future<String> computeApiTxtContents(String pkgPath) async {
-  var provider = PhysicalResourceProvider.INSTANCE;
-  var pathContext = provider.pathContext;
-  var pkgName = pathContext.basename(pkgPath);
-  var collection = AnalysisContextCollection(
-    includedPaths: [pkgPath],
-    resourceProvider: provider,
-  );
-  var context = collection.contexts.first;
-  var publicApi = ApiDescription(pkgName);
-  var stringBuffer = StringBuffer();
-  _printNodes(stringBuffer, await publicApi.build(context));
-  return stringBuffer.toString();
-}
-
 /// Outputs the contents of [nodes] to [sink], prepending [prefix] to every
 /// line.
 void _printNodes<SortKey extends Comparable<SortKey>>(
diff --git a/pkg/wasm_builder/lib/src/builder/types.dart b/pkg/wasm_builder/lib/src/builder/types.dart
index dfe7ac9..6302263 100644
--- a/pkg/wasm_builder/lib/src/builder/types.dart
+++ b/pkg/wasm_builder/lib/src/builder/types.dart
@@ -9,12 +9,20 @@
 import 'builder.dart';
 
 /// The available field values that can be used in brand type StructTypes.
-const List<ir.ValueType> _brandTypeFieldValues = [
+const List<ir.StorageType> _brandTypeFieldValues = [
   ir.NumType.i32,
   ir.NumType.i64,
   ir.NumType.f32,
   ir.NumType.f64,
   ir.NumType.v128,
+  ir.PackedType.i8,
+  ir.PackedType.i16,
+  ir.RefType.i31(nullable: false),
+  ir.RefType.i31(nullable: true),
+  ir.RefType.struct(nullable: false),
+  ir.RefType.struct(nullable: true),
+  ir.RefType.array(nullable: false),
+  ir.RefType.array(nullable: true),
   ir.RefType.extern(nullable: false),
   ir.RefType.extern(nullable: true),
   ir.RefType.any(nullable: false),
@@ -35,22 +43,17 @@
 /// The produced brand type can be added to rec groups that would otherwise be
 /// considered equal by the wasm type system. The brand types break the unwanted
 /// equivalence relation between the groups.
-///
-/// The brand type must contain at least one field because every struct is a
-/// subtype of the empty struct.
 ir.StructType _getBrandType(int index) {
   final brandName = 'brand$index';
   final List<ir.FieldType> fields = [];
   final numDigits = _brandTypeFieldValues.length;
-  do {
-    final modValue = index % numDigits;
-    // It's important that the fields are mutable. This ensures that the
-    // contained StorageTypes must be mutual subtypes (i.e. they must be equal)
-    // in order for them to match. Some of our brand digit options are subtypes
-    // of others so to avoid them matching we need the mutual subtyping.
-    fields.add(ir.FieldType(_brandTypeFieldValues[modValue], mutable: true));
-    index = index ~/ numDigits;
-  } while (index > 0);
+  while (index > 0) {
+    final useMutable = index & 1 == 1;
+    final digitIndex = (index >> 1) % numDigits;
+    fields.add(
+        ir.FieldType(_brandTypeFieldValues[digitIndex], mutable: useMutable));
+    index = index ~/ (numDigits * 2);
+  }
   return ir.StructType(brandName, fields: fields);
 }
 
diff --git a/tools/VERSION b/tools/VERSION
index e5d8767..6a3be66 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 3
 MINOR 9
 PATCH 0
-PRERELEASE 303
+PRERELEASE 304
 PRERELEASE_PATCH 0