Version 2.19.0-279.0.dev

Merge fd39eab463f989153aedfac3972ae0fe24729d8e into dev
diff --git a/BUILD.gn b/BUILD.gn
index 1773913..7c566ef 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -103,12 +103,18 @@
   deps = [ "utils/compiler:dart2js" ]
 }
 
-group("dart2wasm") {
+group("dart2wasm_platform") {
   deps = [
     ":runtime_precompiled",
     "utils/dart2wasm:compile_dart2wasm_platform",
     "utils/dart2wasm:dart2wasm_asserts_snapshot",
     "utils/dart2wasm:dart2wasm_snapshot",
+  ]
+}
+
+group("dart2wasm") {
+  deps = [
+    ":dart2wasm_platform",
     "utils/dart2wasm:test_wasm_modules",
   ]
 }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart
index 2256b88..acdc16e 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart
@@ -6100,26 +6100,27 @@
 
     node.receiver = receiver..parent = node;
 
-    if (receiverType is RecordType) {
+    DartType recordType = resolveTypeParameter(receiverType);
+    if (recordType is RecordType) {
       // TODO(johnniwinther): Handle nullable record types and null shorting.
       String name = node.name.text;
       if (name.startsWith('\$')) {
         int? index = int.tryParse(name.substring(1));
         if (index != null) {
-          if (index < receiverType.positional.length) {
-            DartType fieldType = receiverType.positional[index];
+          if (index < recordType.positional.length) {
+            DartType fieldType = recordType.positional[index];
             return new ExpressionInferenceResult(
                 fieldType,
-                new RecordIndexGet(receiver, receiverType, index)
+                new RecordIndexGet(receiver, recordType, index)
                   ..fileOffset = node.fileOffset);
           }
         }
       }
-      for (NamedType field in receiverType.named) {
+      for (NamedType field in recordType.named) {
         if (field.name == name) {
           return new ExpressionInferenceResult(
               field.type,
-              new RecordNameGet(receiver, receiverType, name)
+              new RecordNameGet(receiver, recordType, name)
                 ..fileOffset = node.fileOffset);
         }
       }
diff --git a/pkg/front_end/testcases/records/access_through_type_variable.dart b/pkg/front_end/testcases/records/access_through_type_variable.dart
new file mode 100644
index 0000000..25e7eef
--- /dev/null
+++ b/pkg/front_end/testcases/records/access_through_type_variable.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2022, 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.
+
+method1a<T extends (int, String)>(T t) => t.$0; // Ok
+method1b<T extends (int, String)>(T t) => t.$1; // Ok
+method1c<T extends (int, String)>(T t) => t.$2; // Error
+method1d<T extends (int, String)>(T t) => t.a; // Error
+
+method2a<T extends (int, {String a})>(T t) => t.$0; // Ok
+method2b<T extends (int, {String a})>(T t) => t.a; // Ok
+method2c<T extends (int, {String a})>(T t) => t.$1; // Error
+method2d<T extends (int, {String a})>(T t) => t.b; // Error
+
+method3a<T extends (int, String), S extends T>(S t) => t.$0; // Ok
+method3b<T extends (int, String), S extends T>(S t) => t.$1; // Ok
+method3c<T extends (int, String), S extends T>(S t) => t.$2; // Error
+method3d<T extends (int, String), S extends T>(S t) => t.a; // Error
+
+void method1<T>(T t) {
+  if (t is (int, String)) t.$0; // Ok
+  if (t is (int, String)) t.$1; // Ok
+  if (t is (int, String))  t.$2; // Error
+  if (t is (int, String))  t.a; // Error
+
+  if (t is (int, {String a})) t.$0; // Ok
+  if (t is (int, {String a})) t.a; // Ok
+  if (t is (int, {String a})) t.$1; // Error
+  if (t is (int, {String a})) t.b; // Error
+}
+
+void method2(Object t) {
+  if (t is (int, String)) t.$0; // Ok
+  if (t is (int, String)) t.$1; // Ok
+  if (t is (int, String))  t.$2; // Error
+  if (t is (int, String))  t.a; // Error
+
+  if (t is (int, {String a})) t.$0; // Ok
+  if (t is (int, {String a})) t.a; // Ok
+  if (t is (int, {String a})) t.$1; // Error
+  if (t is (int, {String a})) t.b; // Error
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/records/access_through_type_variable.dart.strong.expect b/pkg/front_end/testcases/records/access_through_type_variable.dart.strong.expect
new file mode 100644
index 0000000..c6597d3
--- /dev/null
+++ b/pkg/front_end/testcases/records/access_through_type_variable.dart.strong.expect
@@ -0,0 +1,179 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:7:45: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+// method1c<T extends (int, String)>(T t) => t.$2; // Error
+//                                             ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:8:45: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+// method1d<T extends (int, String)>(T t) => t.a; // Error
+//                                             ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:12:49: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+// method2c<T extends (int, {String a})>(T t) => t.$1; // Error
+//                                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:13:49: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+// method2d<T extends (int, {String a})>(T t) => t.b; // Error
+//                                                 ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:17:58: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+// method3c<T extends (int, String), S extends T>(S t) => t.$2; // Error
+//                                                          ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:18:58: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+// method3d<T extends (int, String), S extends T>(S t) => t.a; // Error
+//                                                          ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:23:30: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+//   if (t is (int, String))  t.$2; // Error
+//                              ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:24:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+//   if (t is (int, String))  t.a; // Error
+//                              ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:28:33: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+//   if (t is (int, {String a})) t.$1; // Error
+//                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:29:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+//   if (t is (int, {String a})) t.b; // Error
+//                                 ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:35:30: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+//   if (t is (int, String))  t.$2; // Error
+//                              ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:36:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+//   if (t is (int, String))  t.a; // Error
+//                              ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:40:33: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+//   if (t is (int, {String a})) t.$1; // Error
+//                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:41:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+//   if (t is (int, {String a})) t.b; // Error
+//                                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method method1a<T extends (core::int, core::String)>(self::method1a::T t) → dynamic
+  return t.$0{core::int};
+static method method1b<T extends (core::int, core::String)>(self::method1b::T t) → dynamic
+  return t.$1{core::String};
+static method method1c<T extends (core::int, core::String)>(self::method1c::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:7:45: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+method1c<T extends (int, String)>(T t) => t.\$2; // Error
+                                            ^^" in t{<unresolved>}.$2;
+static method method1d<T extends (core::int, core::String)>(self::method1d::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:8:45: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+method1d<T extends (int, String)>(T t) => t.a; // Error
+                                            ^" in t{<unresolved>}.a;
+static method method2a<T extends (core::int, {required a: core::String})>(self::method2a::T t) → dynamic
+  return t.$0{core::int};
+static method method2b<T extends (core::int, {required a: core::String})>(self::method2b::T t) → dynamic
+  return t.a{core::String};
+static method method2c<T extends (core::int, {required a: core::String})>(self::method2c::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:12:49: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+method2c<T extends (int, {String a})>(T t) => t.\$1; // Error
+                                                ^^" in t{<unresolved>}.$1;
+static method method2d<T extends (core::int, {required a: core::String})>(self::method2d::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:13:49: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+method2d<T extends (int, {String a})>(T t) => t.b; // Error
+                                                ^" in t{<unresolved>}.b;
+static method method3a<T extends (core::int, core::String), S extends self::method3a::T = (core::int, core::String)>(self::method3a::S t) → dynamic
+  return t.$0{core::int};
+static method method3b<T extends (core::int, core::String), S extends self::method3b::T = (core::int, core::String)>(self::method3b::S t) → dynamic
+  return t.$1{core::String};
+static method method3c<T extends (core::int, core::String), S extends self::method3c::T = (core::int, core::String)>(self::method3c::S t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:17:58: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+method3c<T extends (int, String), S extends T>(S t) => t.\$2; // Error
+                                                         ^^" in t{<unresolved>}.$2;
+static method method3d<T extends (core::int, core::String), S extends self::method3d::T = (core::int, core::String)>(self::method3d::S t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:18:58: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+method3d<T extends (int, String), S extends T>(S t) => t.a; // Error
+                                                         ^" in t{<unresolved>}.a;
+static method method1<T extends core::Object? = dynamic>(self::method1::T% t) → void {
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}.$1{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:23:30: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+  if (t is (int, String))  t.\$2; // Error
+                             ^^" in t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}{<unresolved>}.$2;
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:24:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+  if (t is (int, String))  t.a; // Error
+                             ^" in t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}{<unresolved>}.a;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}.a{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:28:33: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+  if (t is (int, {String a})) t.\$1; // Error
+                                ^^" in t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}{<unresolved>}.$1;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:29:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+  if (t is (int, {String a})) t.b; // Error
+                                ^" in t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}{<unresolved>}.b;
+}
+static method method2(core::Object t) → void {
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{(core::int, core::String)}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{(core::int, core::String)}.$1{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:35:30: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+  if (t is (int, String))  t.\$2; // Error
+                             ^^" in t{(core::int, core::String)}{<unresolved>}.$2;
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:36:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+  if (t is (int, String))  t.a; // Error
+                             ^" in t{(core::int, core::String)}{<unresolved>}.a;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{(core::int, {required a: core::String})}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{(core::int, {required a: core::String})}.a{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:40:33: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+  if (t is (int, {String a})) t.\$1; // Error
+                                ^^" in t{(core::int, {required a: core::String})}{<unresolved>}.$1;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:41:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+  if (t is (int, {String a})) t.b; // Error
+                                ^" in t{(core::int, {required a: core::String})}{<unresolved>}.b;
+}
diff --git a/pkg/front_end/testcases/records/access_through_type_variable.dart.strong.transformed.expect b/pkg/front_end/testcases/records/access_through_type_variable.dart.strong.transformed.expect
new file mode 100644
index 0000000..c6597d3
--- /dev/null
+++ b/pkg/front_end/testcases/records/access_through_type_variable.dart.strong.transformed.expect
@@ -0,0 +1,179 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:7:45: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+// method1c<T extends (int, String)>(T t) => t.$2; // Error
+//                                             ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:8:45: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+// method1d<T extends (int, String)>(T t) => t.a; // Error
+//                                             ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:12:49: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+// method2c<T extends (int, {String a})>(T t) => t.$1; // Error
+//                                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:13:49: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+// method2d<T extends (int, {String a})>(T t) => t.b; // Error
+//                                                 ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:17:58: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+// method3c<T extends (int, String), S extends T>(S t) => t.$2; // Error
+//                                                          ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:18:58: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+// method3d<T extends (int, String), S extends T>(S t) => t.a; // Error
+//                                                          ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:23:30: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+//   if (t is (int, String))  t.$2; // Error
+//                              ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:24:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+//   if (t is (int, String))  t.a; // Error
+//                              ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:28:33: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+//   if (t is (int, {String a})) t.$1; // Error
+//                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:29:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+//   if (t is (int, {String a})) t.b; // Error
+//                                 ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:35:30: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+//   if (t is (int, String))  t.$2; // Error
+//                              ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:36:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+//   if (t is (int, String))  t.a; // Error
+//                              ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:40:33: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+//   if (t is (int, {String a})) t.$1; // Error
+//                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:41:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+//   if (t is (int, {String a})) t.b; // Error
+//                                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method method1a<T extends (core::int, core::String)>(self::method1a::T t) → dynamic
+  return t.$0{core::int};
+static method method1b<T extends (core::int, core::String)>(self::method1b::T t) → dynamic
+  return t.$1{core::String};
+static method method1c<T extends (core::int, core::String)>(self::method1c::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:7:45: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+method1c<T extends (int, String)>(T t) => t.\$2; // Error
+                                            ^^" in t{<unresolved>}.$2;
+static method method1d<T extends (core::int, core::String)>(self::method1d::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:8:45: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+method1d<T extends (int, String)>(T t) => t.a; // Error
+                                            ^" in t{<unresolved>}.a;
+static method method2a<T extends (core::int, {required a: core::String})>(self::method2a::T t) → dynamic
+  return t.$0{core::int};
+static method method2b<T extends (core::int, {required a: core::String})>(self::method2b::T t) → dynamic
+  return t.a{core::String};
+static method method2c<T extends (core::int, {required a: core::String})>(self::method2c::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:12:49: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+method2c<T extends (int, {String a})>(T t) => t.\$1; // Error
+                                                ^^" in t{<unresolved>}.$1;
+static method method2d<T extends (core::int, {required a: core::String})>(self::method2d::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:13:49: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+method2d<T extends (int, {String a})>(T t) => t.b; // Error
+                                                ^" in t{<unresolved>}.b;
+static method method3a<T extends (core::int, core::String), S extends self::method3a::T = (core::int, core::String)>(self::method3a::S t) → dynamic
+  return t.$0{core::int};
+static method method3b<T extends (core::int, core::String), S extends self::method3b::T = (core::int, core::String)>(self::method3b::S t) → dynamic
+  return t.$1{core::String};
+static method method3c<T extends (core::int, core::String), S extends self::method3c::T = (core::int, core::String)>(self::method3c::S t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:17:58: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+method3c<T extends (int, String), S extends T>(S t) => t.\$2; // Error
+                                                         ^^" in t{<unresolved>}.$2;
+static method method3d<T extends (core::int, core::String), S extends self::method3d::T = (core::int, core::String)>(self::method3d::S t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:18:58: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+method3d<T extends (int, String), S extends T>(S t) => t.a; // Error
+                                                         ^" in t{<unresolved>}.a;
+static method method1<T extends core::Object? = dynamic>(self::method1::T% t) → void {
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}.$1{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:23:30: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+  if (t is (int, String))  t.\$2; // Error
+                             ^^" in t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}{<unresolved>}.$2;
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:24:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+  if (t is (int, String))  t.a; // Error
+                             ^" in t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}{<unresolved>}.a;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}.a{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:28:33: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+  if (t is (int, {String a})) t.\$1; // Error
+                                ^^" in t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}{<unresolved>}.$1;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:29:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+  if (t is (int, {String a})) t.b; // Error
+                                ^" in t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}{<unresolved>}.b;
+}
+static method method2(core::Object t) → void {
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{(core::int, core::String)}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{(core::int, core::String)}.$1{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:35:30: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+  if (t is (int, String))  t.\$2; // Error
+                             ^^" in t{(core::int, core::String)}{<unresolved>}.$2;
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:36:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+  if (t is (int, String))  t.a; // Error
+                             ^" in t{(core::int, core::String)}{<unresolved>}.a;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{(core::int, {required a: core::String})}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{(core::int, {required a: core::String})}.a{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:40:33: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+  if (t is (int, {String a})) t.\$1; // Error
+                                ^^" in t{(core::int, {required a: core::String})}{<unresolved>}.$1;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:41:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+  if (t is (int, {String a})) t.b; // Error
+                                ^" in t{(core::int, {required a: core::String})}{<unresolved>}.b;
+}
diff --git a/pkg/front_end/testcases/records/access_through_type_variable.dart.textual_outline.expect b/pkg/front_end/testcases/records/access_through_type_variable.dart.textual_outline.expect
new file mode 100644
index 0000000..75fe143
--- /dev/null
+++ b/pkg/front_end/testcases/records/access_through_type_variable.dart.textual_outline.expect
@@ -0,0 +1,14 @@
+method1a<T extends (int, String)>(T t) => t.$0;
+method1b<T extends (int, String)>(T t) => t.$1;
+method1c<T extends (int, String)>(T t) => t.$2;
+method1d<T extends (int, String)>(T t) => t.a;
+method2a<T extends (int, {String a})>(T t) => t.$0;
+method2b<T extends (int, {String a})>(T t) => t.a;
+method2c<T extends (int, {String a})>(T t) => t.$1;
+method2d<T extends (int, {String a})>(T t) => t.b;
+method3a<T extends (int, String), S extends T>(S t) => t.$0;
+method3b<T extends (int, String), S extends T>(S t) => t.$1;
+method3c<T extends (int, String), S extends T>(S t) => t.$2;
+method3d<T extends (int, String), S extends T>(S t) => t.a;
+void method1<T>(T t) {}
+void method2(Object t) {}
diff --git a/pkg/front_end/testcases/records/access_through_type_variable.dart.weak.expect b/pkg/front_end/testcases/records/access_through_type_variable.dart.weak.expect
new file mode 100644
index 0000000..c6597d3
--- /dev/null
+++ b/pkg/front_end/testcases/records/access_through_type_variable.dart.weak.expect
@@ -0,0 +1,179 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:7:45: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+// method1c<T extends (int, String)>(T t) => t.$2; // Error
+//                                             ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:8:45: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+// method1d<T extends (int, String)>(T t) => t.a; // Error
+//                                             ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:12:49: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+// method2c<T extends (int, {String a})>(T t) => t.$1; // Error
+//                                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:13:49: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+// method2d<T extends (int, {String a})>(T t) => t.b; // Error
+//                                                 ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:17:58: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+// method3c<T extends (int, String), S extends T>(S t) => t.$2; // Error
+//                                                          ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:18:58: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+// method3d<T extends (int, String), S extends T>(S t) => t.a; // Error
+//                                                          ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:23:30: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+//   if (t is (int, String))  t.$2; // Error
+//                              ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:24:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+//   if (t is (int, String))  t.a; // Error
+//                              ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:28:33: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+//   if (t is (int, {String a})) t.$1; // Error
+//                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:29:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+//   if (t is (int, {String a})) t.b; // Error
+//                                 ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:35:30: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+//   if (t is (int, String))  t.$2; // Error
+//                              ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:36:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+//   if (t is (int, String))  t.a; // Error
+//                              ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:40:33: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+//   if (t is (int, {String a})) t.$1; // Error
+//                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:41:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+//   if (t is (int, {String a})) t.b; // Error
+//                                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method method1a<T extends (core::int, core::String)>(self::method1a::T t) → dynamic
+  return t.$0{core::int};
+static method method1b<T extends (core::int, core::String)>(self::method1b::T t) → dynamic
+  return t.$1{core::String};
+static method method1c<T extends (core::int, core::String)>(self::method1c::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:7:45: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+method1c<T extends (int, String)>(T t) => t.\$2; // Error
+                                            ^^" in t{<unresolved>}.$2;
+static method method1d<T extends (core::int, core::String)>(self::method1d::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:8:45: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+method1d<T extends (int, String)>(T t) => t.a; // Error
+                                            ^" in t{<unresolved>}.a;
+static method method2a<T extends (core::int, {required a: core::String})>(self::method2a::T t) → dynamic
+  return t.$0{core::int};
+static method method2b<T extends (core::int, {required a: core::String})>(self::method2b::T t) → dynamic
+  return t.a{core::String};
+static method method2c<T extends (core::int, {required a: core::String})>(self::method2c::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:12:49: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+method2c<T extends (int, {String a})>(T t) => t.\$1; // Error
+                                                ^^" in t{<unresolved>}.$1;
+static method method2d<T extends (core::int, {required a: core::String})>(self::method2d::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:13:49: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+method2d<T extends (int, {String a})>(T t) => t.b; // Error
+                                                ^" in t{<unresolved>}.b;
+static method method3a<T extends (core::int, core::String), S extends self::method3a::T = (core::int, core::String)>(self::method3a::S t) → dynamic
+  return t.$0{core::int};
+static method method3b<T extends (core::int, core::String), S extends self::method3b::T = (core::int, core::String)>(self::method3b::S t) → dynamic
+  return t.$1{core::String};
+static method method3c<T extends (core::int, core::String), S extends self::method3c::T = (core::int, core::String)>(self::method3c::S t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:17:58: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+method3c<T extends (int, String), S extends T>(S t) => t.\$2; // Error
+                                                         ^^" in t{<unresolved>}.$2;
+static method method3d<T extends (core::int, core::String), S extends self::method3d::T = (core::int, core::String)>(self::method3d::S t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:18:58: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+method3d<T extends (int, String), S extends T>(S t) => t.a; // Error
+                                                         ^" in t{<unresolved>}.a;
+static method method1<T extends core::Object? = dynamic>(self::method1::T% t) → void {
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}.$1{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:23:30: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+  if (t is (int, String))  t.\$2; // Error
+                             ^^" in t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}{<unresolved>}.$2;
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:24:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+  if (t is (int, String))  t.a; // Error
+                             ^" in t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}{<unresolved>}.a;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}.a{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:28:33: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+  if (t is (int, {String a})) t.\$1; // Error
+                                ^^" in t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}{<unresolved>}.$1;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:29:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+  if (t is (int, {String a})) t.b; // Error
+                                ^" in t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}{<unresolved>}.b;
+}
+static method method2(core::Object t) → void {
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{(core::int, core::String)}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{(core::int, core::String)}.$1{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:35:30: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+  if (t is (int, String))  t.\$2; // Error
+                             ^^" in t{(core::int, core::String)}{<unresolved>}.$2;
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:36:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+  if (t is (int, String))  t.a; // Error
+                             ^" in t{(core::int, core::String)}{<unresolved>}.a;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{(core::int, {required a: core::String})}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{(core::int, {required a: core::String})}.a{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:40:33: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+  if (t is (int, {String a})) t.\$1; // Error
+                                ^^" in t{(core::int, {required a: core::String})}{<unresolved>}.$1;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:41:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+  if (t is (int, {String a})) t.b; // Error
+                                ^" in t{(core::int, {required a: core::String})}{<unresolved>}.b;
+}
diff --git a/pkg/front_end/testcases/records/access_through_type_variable.dart.weak.modular.expect b/pkg/front_end/testcases/records/access_through_type_variable.dart.weak.modular.expect
new file mode 100644
index 0000000..c6597d3
--- /dev/null
+++ b/pkg/front_end/testcases/records/access_through_type_variable.dart.weak.modular.expect
@@ -0,0 +1,179 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:7:45: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+// method1c<T extends (int, String)>(T t) => t.$2; // Error
+//                                             ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:8:45: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+// method1d<T extends (int, String)>(T t) => t.a; // Error
+//                                             ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:12:49: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+// method2c<T extends (int, {String a})>(T t) => t.$1; // Error
+//                                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:13:49: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+// method2d<T extends (int, {String a})>(T t) => t.b; // Error
+//                                                 ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:17:58: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+// method3c<T extends (int, String), S extends T>(S t) => t.$2; // Error
+//                                                          ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:18:58: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+// method3d<T extends (int, String), S extends T>(S t) => t.a; // Error
+//                                                          ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:23:30: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+//   if (t is (int, String))  t.$2; // Error
+//                              ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:24:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+//   if (t is (int, String))  t.a; // Error
+//                              ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:28:33: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+//   if (t is (int, {String a})) t.$1; // Error
+//                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:29:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+//   if (t is (int, {String a})) t.b; // Error
+//                                 ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:35:30: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+//   if (t is (int, String))  t.$2; // Error
+//                              ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:36:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+//   if (t is (int, String))  t.a; // Error
+//                              ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:40:33: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+//   if (t is (int, {String a})) t.$1; // Error
+//                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:41:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+//   if (t is (int, {String a})) t.b; // Error
+//                                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method method1a<T extends (core::int, core::String)>(self::method1a::T t) → dynamic
+  return t.$0{core::int};
+static method method1b<T extends (core::int, core::String)>(self::method1b::T t) → dynamic
+  return t.$1{core::String};
+static method method1c<T extends (core::int, core::String)>(self::method1c::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:7:45: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+method1c<T extends (int, String)>(T t) => t.\$2; // Error
+                                            ^^" in t{<unresolved>}.$2;
+static method method1d<T extends (core::int, core::String)>(self::method1d::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:8:45: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+method1d<T extends (int, String)>(T t) => t.a; // Error
+                                            ^" in t{<unresolved>}.a;
+static method method2a<T extends (core::int, {required a: core::String})>(self::method2a::T t) → dynamic
+  return t.$0{core::int};
+static method method2b<T extends (core::int, {required a: core::String})>(self::method2b::T t) → dynamic
+  return t.a{core::String};
+static method method2c<T extends (core::int, {required a: core::String})>(self::method2c::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:12:49: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+method2c<T extends (int, {String a})>(T t) => t.\$1; // Error
+                                                ^^" in t{<unresolved>}.$1;
+static method method2d<T extends (core::int, {required a: core::String})>(self::method2d::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:13:49: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+method2d<T extends (int, {String a})>(T t) => t.b; // Error
+                                                ^" in t{<unresolved>}.b;
+static method method3a<T extends (core::int, core::String), S extends self::method3a::T = (core::int, core::String)>(self::method3a::S t) → dynamic
+  return t.$0{core::int};
+static method method3b<T extends (core::int, core::String), S extends self::method3b::T = (core::int, core::String)>(self::method3b::S t) → dynamic
+  return t.$1{core::String};
+static method method3c<T extends (core::int, core::String), S extends self::method3c::T = (core::int, core::String)>(self::method3c::S t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:17:58: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+method3c<T extends (int, String), S extends T>(S t) => t.\$2; // Error
+                                                         ^^" in t{<unresolved>}.$2;
+static method method3d<T extends (core::int, core::String), S extends self::method3d::T = (core::int, core::String)>(self::method3d::S t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:18:58: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+method3d<T extends (int, String), S extends T>(S t) => t.a; // Error
+                                                         ^" in t{<unresolved>}.a;
+static method method1<T extends core::Object? = dynamic>(self::method1::T% t) → void {
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}.$1{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:23:30: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+  if (t is (int, String))  t.\$2; // Error
+                             ^^" in t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}{<unresolved>}.$2;
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:24:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+  if (t is (int, String))  t.a; // Error
+                             ^" in t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}{<unresolved>}.a;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}.a{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:28:33: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+  if (t is (int, {String a})) t.\$1; // Error
+                                ^^" in t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}{<unresolved>}.$1;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:29:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+  if (t is (int, {String a})) t.b; // Error
+                                ^" in t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}{<unresolved>}.b;
+}
+static method method2(core::Object t) → void {
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{(core::int, core::String)}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{(core::int, core::String)}.$1{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:35:30: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+  if (t is (int, String))  t.\$2; // Error
+                             ^^" in t{(core::int, core::String)}{<unresolved>}.$2;
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:36:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+  if (t is (int, String))  t.a; // Error
+                             ^" in t{(core::int, core::String)}{<unresolved>}.a;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{(core::int, {required a: core::String})}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{(core::int, {required a: core::String})}.a{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:40:33: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+  if (t is (int, {String a})) t.\$1; // Error
+                                ^^" in t{(core::int, {required a: core::String})}{<unresolved>}.$1;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:41:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+  if (t is (int, {String a})) t.b; // Error
+                                ^" in t{(core::int, {required a: core::String})}{<unresolved>}.b;
+}
diff --git a/pkg/front_end/testcases/records/access_through_type_variable.dart.weak.outline.expect b/pkg/front_end/testcases/records/access_through_type_variable.dart.weak.outline.expect
new file mode 100644
index 0000000..e1b0bb0
--- /dev/null
+++ b/pkg/front_end/testcases/records/access_through_type_variable.dart.weak.outline.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method method1a<T extends (core::int, core::String)>(self::method1a::T t) → dynamic
+  ;
+static method method1b<T extends (core::int, core::String)>(self::method1b::T t) → dynamic
+  ;
+static method method1c<T extends (core::int, core::String)>(self::method1c::T t) → dynamic
+  ;
+static method method1d<T extends (core::int, core::String)>(self::method1d::T t) → dynamic
+  ;
+static method method2a<T extends (core::int, {required a: core::String})>(self::method2a::T t) → dynamic
+  ;
+static method method2b<T extends (core::int, {required a: core::String})>(self::method2b::T t) → dynamic
+  ;
+static method method2c<T extends (core::int, {required a: core::String})>(self::method2c::T t) → dynamic
+  ;
+static method method2d<T extends (core::int, {required a: core::String})>(self::method2d::T t) → dynamic
+  ;
+static method method3a<T extends (core::int, core::String), S extends self::method3a::T = (core::int, core::String)>(self::method3a::S t) → dynamic
+  ;
+static method method3b<T extends (core::int, core::String), S extends self::method3b::T = (core::int, core::String)>(self::method3b::S t) → dynamic
+  ;
+static method method3c<T extends (core::int, core::String), S extends self::method3c::T = (core::int, core::String)>(self::method3c::S t) → dynamic
+  ;
+static method method3d<T extends (core::int, core::String), S extends self::method3d::T = (core::int, core::String)>(self::method3d::S t) → dynamic
+  ;
+static method method1<T extends core::Object? = dynamic>(self::method1::T% t) → void
+  ;
+static method method2(core::Object t) → void
+  ;
diff --git a/pkg/front_end/testcases/records/access_through_type_variable.dart.weak.transformed.expect b/pkg/front_end/testcases/records/access_through_type_variable.dart.weak.transformed.expect
new file mode 100644
index 0000000..c6597d3
--- /dev/null
+++ b/pkg/front_end/testcases/records/access_through_type_variable.dart.weak.transformed.expect
@@ -0,0 +1,179 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:7:45: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+// method1c<T extends (int, String)>(T t) => t.$2; // Error
+//                                             ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:8:45: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+// method1d<T extends (int, String)>(T t) => t.a; // Error
+//                                             ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:12:49: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+// method2c<T extends (int, {String a})>(T t) => t.$1; // Error
+//                                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:13:49: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+// method2d<T extends (int, {String a})>(T t) => t.b; // Error
+//                                                 ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:17:58: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+// method3c<T extends (int, String), S extends T>(S t) => t.$2; // Error
+//                                                          ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:18:58: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+// method3d<T extends (int, String), S extends T>(S t) => t.a; // Error
+//                                                          ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:23:30: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+//   if (t is (int, String))  t.$2; // Error
+//                              ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:24:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+//   if (t is (int, String))  t.a; // Error
+//                              ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:28:33: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+//   if (t is (int, {String a})) t.$1; // Error
+//                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:29:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+//   if (t is (int, {String a})) t.b; // Error
+//                                 ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:35:30: Error: The getter '$2' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$2'.
+//   if (t is (int, String))  t.$2; // Error
+//                              ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:36:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+//   if (t is (int, String))  t.a; // Error
+//                              ^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:40:33: Error: The getter '$1' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named '$1'.
+//   if (t is (int, {String a})) t.$1; // Error
+//                                 ^^
+//
+// pkg/front_end/testcases/records/access_through_type_variable.dart:41:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+//   if (t is (int, {String a})) t.b; // Error
+//                                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method method1a<T extends (core::int, core::String)>(self::method1a::T t) → dynamic
+  return t.$0{core::int};
+static method method1b<T extends (core::int, core::String)>(self::method1b::T t) → dynamic
+  return t.$1{core::String};
+static method method1c<T extends (core::int, core::String)>(self::method1c::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:7:45: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+method1c<T extends (int, String)>(T t) => t.\$2; // Error
+                                            ^^" in t{<unresolved>}.$2;
+static method method1d<T extends (core::int, core::String)>(self::method1d::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:8:45: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+method1d<T extends (int, String)>(T t) => t.a; // Error
+                                            ^" in t{<unresolved>}.a;
+static method method2a<T extends (core::int, {required a: core::String})>(self::method2a::T t) → dynamic
+  return t.$0{core::int};
+static method method2b<T extends (core::int, {required a: core::String})>(self::method2b::T t) → dynamic
+  return t.a{core::String};
+static method method2c<T extends (core::int, {required a: core::String})>(self::method2c::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:12:49: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+method2c<T extends (int, {String a})>(T t) => t.\$1; // Error
+                                                ^^" in t{<unresolved>}.$1;
+static method method2d<T extends (core::int, {required a: core::String})>(self::method2d::T t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:13:49: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+method2d<T extends (int, {String a})>(T t) => t.b; // Error
+                                                ^" in t{<unresolved>}.b;
+static method method3a<T extends (core::int, core::String), S extends self::method3a::T = (core::int, core::String)>(self::method3a::S t) → dynamic
+  return t.$0{core::int};
+static method method3b<T extends (core::int, core::String), S extends self::method3b::T = (core::int, core::String)>(self::method3b::S t) → dynamic
+  return t.$1{core::String};
+static method method3c<T extends (core::int, core::String), S extends self::method3c::T = (core::int, core::String)>(self::method3c::S t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:17:58: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+method3c<T extends (int, String), S extends T>(S t) => t.\$2; // Error
+                                                         ^^" in t{<unresolved>}.$2;
+static method method3d<T extends (core::int, core::String), S extends self::method3d::T = (core::int, core::String)>(self::method3d::S t) → dynamic
+  return invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:18:58: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+method3d<T extends (int, String), S extends T>(S t) => t.a; // Error
+                                                         ^" in t{<unresolved>}.a;
+static method method1<T extends core::Object? = dynamic>(self::method1::T% t) → void {
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}.$1{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:23:30: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+  if (t is (int, String))  t.\$2; // Error
+                             ^^" in t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}{<unresolved>}.$2;
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:24:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+  if (t is (int, String))  t.a; // Error
+                             ^" in t{self::method1::T% & (core::int, core::String) /* '%' & '!' = '!' */}{<unresolved>}.a;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}.a{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:28:33: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+  if (t is (int, {String a})) t.\$1; // Error
+                                ^^" in t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}{<unresolved>}.$1;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:29:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+  if (t is (int, {String a})) t.b; // Error
+                                ^" in t{self::method1::T% & (core::int, {required a: core::String}) /* '%' & '!' = '!' */}{<unresolved>}.b;
+}
+static method method2(core::Object t) → void {
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{(core::int, core::String)}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    t{(core::int, core::String)}.$1{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:35:30: Error: The getter '\$2' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$2'.
+  if (t is (int, String))  t.\$2; // Error
+                             ^^" in t{(core::int, core::String)}{<unresolved>}.$2;
+  if(t is{ForNonNullableByDefault} (core::int, core::String))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:36:30: Error: The getter 'a' isn't defined for the class '(int, String)'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'a'.
+  if (t is (int, String))  t.a; // Error
+                             ^" in t{(core::int, core::String)}{<unresolved>}.a;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{(core::int, {required a: core::String})}.$0{core::int};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    t{(core::int, {required a: core::String})}.a{core::String};
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:40:33: Error: The getter '\$1' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+  if (t is (int, {String a})) t.\$1; // Error
+                                ^^" in t{(core::int, {required a: core::String})}{<unresolved>}.$1;
+  if(t is{ForNonNullableByDefault} (core::int, {required a: core::String}))
+    invalid-expression "pkg/front_end/testcases/records/access_through_type_variable.dart:41:33: Error: The getter 'b' isn't defined for the class '(int, {String a})'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'b'.
+  if (t is (int, {String a})) t.b; // Error
+                                ^" in t{(core::int, {required a: core::String})}{<unresolved>}.b;
+}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 34a457f..5d764df 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -144,6 +144,7 @@
 rasta/issue_000047: FormatterCrash
 rasta/malformed_const_constructor: FormatterCrash
 rasta/mandatory_parameter_initializer: FormatterCrash
+records/access_through_type_variable: FormatterCrash
 records/const_record_literal: FormatterCrash
 records/record_literal_errors: FormatterCrash
 records/record_type: FormatterCrash
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 3fda91d..c3efa67 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -4222,10 +4222,8 @@
 
   @override
   DartType getStaticTypeInternal(StaticTypeContext context) {
-    DartType receiverType = receiver.getStaticType(context);
-    assert(
-        receiverType is RecordType && index < receiverType.positional.length);
-    return (receiverType as RecordType).positional[index];
+    assert(index < receiverType.positional.length);
+    return receiverType.positional[index];
   }
 
   @override
@@ -4275,12 +4273,8 @@
 
   @override
   DartType getStaticTypeInternal(StaticTypeContext context) {
-    DartType receiverType = receiver.getStaticType(context);
-    assert(receiverType is RecordType);
-
-    RecordType recordType = receiverType as RecordType;
     DartType? result;
-    for (NamedType namedType in recordType.named) {
+    for (NamedType namedType in receiverType.named) {
       if (namedType.name == name) {
         result = namedType.type;
         break;
@@ -12796,6 +12790,8 @@
       return true;
     } else if (other is RecordType) {
       if (nullability != other.nullability) return false;
+      if (positional.length != other.positional.length) return false;
+      if (named.length != other.named.length) return false;
       for (int index = 0; index < positional.length; index++) {
         if (!positional[index].equals(other.positional[index], assumptions)) {
           return false;
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index f0368bd..feebcf4 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -841,12 +841,8 @@
 
   @override
   DartType visitRecordIndexGet(RecordIndexGet node) {
-    DartType receiverType = visitExpression(node.receiver);
-    assert(
-        receiverType is RecordType,
-        "Encountered RecordIndexGet with non-record receiver: "
-        "'${receiverType.runtimeType}'.");
-    RecordType recordType = receiverType as RecordType;
+    visitExpression(node.receiver);
+    RecordType recordType = node.receiverType;
     assert(
         node.index < recordType.positional.length,
         "Encountered RecordIndexGet with index out of range: "
@@ -856,13 +852,9 @@
 
   @override
   DartType visitRecordNameGet(RecordNameGet node) {
-    DartType recordType = visitExpression(node.receiver);
-    assert(
-        recordType is RecordType,
-        "Encountered RecordNameGet with non-record receiver: "
-        "'${recordType.runtimeType}'.");
+    visitExpression(node.receiver);
     DartType? result;
-    for (NamedType namedType in (recordType as RecordType).named) {
+    for (NamedType namedType in node.receiverType.named) {
       if (namedType.name == node.name) {
         result = namedType.type;
       }
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 63ff6ff..f33fb05 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -38,10 +38,12 @@
 # ......dartaotruntime or dartaotruntime.exe (executable)
 # ......dart2js
 # ......dartdevc
+# ......run_wasm.js (if not on ia32)
 # ......utils/gen_snapshot or utils/gen_snapshot.exe (if not on ia32)
 # ......snapshots/
 # ........analysis_server.dart.snapshot
 # ........dart2js.dart.snapshot
+# ........dart2wasm.dart.snapshot (if not on ia32)
 # ........dartdev.dart.snapshot
 # ........dartdev.dill
 # ........dartdevc.dart.snapshot
@@ -67,6 +69,8 @@
 # ........dart2js_platform_unsound.dill
 # ........dart2js_server_platform.dill
 # ........dart2js_server_platform_unsound.dill
+# ........dart2wasm_platform.dill (if not on ia32)
+# ........dart2wasm_outline.dill (if not on ia32)
 # ........vm_platform_strong.dill
 # ........dev_compiler/
 # ......async/
@@ -481,6 +485,37 @@
       [ "$root_out_dir/$dart_sdk_output/lib/_internal/{{source_file_part}}" ]
 }
 
+copy("copy_dart2wasm_platform") {
+  visibility = [ ":create_full_sdk" ]
+  deps = [
+    ":copy_libraries",
+    "../:dart2wasm_platform",
+    "../utils/dart2wasm:compile_dart2wasm_platform",
+  ]
+  sources = [
+    "$root_out_dir/dart2wasm_outline.dill",
+    "$root_out_dir/dart2wasm_platform.dill",
+  ]
+  outputs =
+      [ "$root_out_dir/$dart_sdk_output/lib/_internal/{{source_file_part}}" ]
+}
+
+copy("copy_dart2wasm_runtime") {
+  visibility = [ ":create_full_sdk" ]
+  sources = [ "../pkg/dart2wasm/bin/run_wasm.js" ]
+  outputs = [ "$root_out_dir/$dart_sdk_output/bin/{{source_file_part}}" ]
+}
+
+copy("copy_dart2wasm_snapshot") {
+  visibility = [ ":create_full_sdk" ]
+  deps = [
+    ":copy_libraries",
+    "../utils/dart2wasm:dart2wasm_snapshot",
+  ]
+  sources = [ "$root_out_dir/dart2wasm.snapshot" ]
+  outputs = [ "$root_out_dir/$dart_sdk_output/snapshots/{{source_file_part}}" ]
+}
+
 # Copies DDC's SDK weak outline .dill to lib/_internal
 # TODO(nshahan) Fix the outline to be consistent and merge with below as a
 # breaking change.
@@ -775,6 +810,14 @@
     ":copy_full_sdk_scripts",
     ":copy_full_sdk_snapshots",
   ]
+
+  if (dart_target_arch != "ia32" && dart_target_arch != "x86") {
+    public_deps += [
+      ":copy_dart2wasm_platform",
+      ":copy_dart2wasm_runtime",
+      ":copy_dart2wasm_snapshot",
+    ]
+  }
 }
 
 # Build a SDK with less stuff. It excludes dart2js, ddc, and web libraries.
diff --git a/tools/VERSION b/tools/VERSION
index 3136cd6..2f95c15 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 19
 PATCH 0
-PRERELEASE 278
+PRERELEASE 279
 PRERELEASE_PATCH 0