Version 2.13.0-56.0.dev

Merge commit '32fe29617ef6e56bb00d48db0bb2a8f67e1eff16' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index bfcdff4..2545c3a 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -3857,6 +3857,30 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
+    Message Function(String name)> templateFfiFieldNull = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Field '#name' cannot have type 'Null', it must be `int`, `double`, `Pointer`, or a subtype of `Struct`.""",
+    withArguments: _withArgumentsFfiFieldNull);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeFfiFieldNull =
+    const Code<Message Function(String name)>(
+  "FfiFieldNull",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiFieldNull(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFfiFieldNull,
+      message:
+          """Field '${name}' cannot have type 'Null', it must be `int`, `double`, `Pointer`, or a subtype of `Struct`.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
     Message Function(String name)> templateFfiNotStatic = const Template<
         Message Function(String name)>(
     messageTemplate:
diff --git a/pkg/analysis_server/lib/src/cider/assists.dart b/pkg/analysis_server/lib/src/cider/assists.dart
new file mode 100644
index 0000000..ba46cce
--- /dev/null
+++ b/pkg/analysis_server/lib/src/cider/assists.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/assist_internal.dart';
+import 'package:analysis_server/src/services/correction/change_workspace.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/instrumentation/service.dart';
+import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/micro/resolve_file.dart';
+
+class CiderAssistsComputer {
+  final PerformanceLog _logger;
+  final FileResolver _fileResolver;
+
+  CiderAssistsComputer(this._logger, this._fileResolver);
+
+  /// Compute quick assists on the line and character position.
+  Future<List<Assist>> compute(
+      String path, int lineNumber, int colNumber, int length) async {
+    var result = <Assist>[];
+    var resolvedUnit = _fileResolver.resolve(path: path);
+    var lineInfo = resolvedUnit.lineInfo;
+    var offset = lineInfo.getOffsetOfLine(lineNumber) + colNumber;
+
+    await _logger.runAsync('Compute assists', () async {
+      try {
+        var workspace = DartChangeWorkspace([resolvedUnit.session]);
+        var context = DartAssistContextImpl(
+          InstrumentationService.NULL_SERVICE,
+          workspace,
+          resolvedUnit,
+          offset,
+          length,
+        );
+        final processor = AssistProcessor(context);
+        final assists = await processor.compute();
+        assists.sort(Assist.SORT_BY_RELEVANCE);
+        result.addAll(assists);
+      } on InconsistentAnalysisException {
+        // If an InconsistentAnalysisException occurs, it's likely the user modified
+        // the source and therefore is no longer interested in the results.
+      }
+    });
+    return result;
+  }
+}
diff --git a/pkg/analysis_server/test/src/cider/assists_test.dart b/pkg/analysis_server/test/src/cider/assists_test.dart
new file mode 100644
index 0000000..aa1fc47
--- /dev/null
+++ b/pkg/analysis_server/test/src/cider/assists_test.dart
@@ -0,0 +1,123 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
+import 'package:analysis_server/src/cider/assists.dart';
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceEdit;
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'cider_service.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(CiderAssistsComputerTest);
+  });
+}
+
+@reflectiveTest
+class CiderAssistsComputerTest extends CiderServiceTest {
+  _CorrectionContext _correctionContext;
+  List<Assist> _assists;
+
+  void assertHasAssist(AssistKind kind, String expected) {
+    var assist = _getAssist(kind);
+
+    var fileEdits = assist.change.edits;
+    expect(fileEdits, hasLength(1));
+
+    var resultContent = SourceEdit.applySequence(
+      _correctionContext.content,
+      fileEdits.single.edits,
+    );
+    expect(resultContent, expected);
+  }
+
+  Future<void> test_addReturnType() async {
+    await _compute(r'''
+void m() {
+  ^f() {
+    return '';
+  }
+}
+''');
+
+    assertHasAssist(DartAssistKind.ADD_RETURN_TYPE, r'''
+void m() {
+  String f() {
+    return '';
+  }
+}
+''');
+  }
+
+  Future<void> test_assignToLocalVariable() async {
+    await _compute(r'''
+main() {
+  12^345;
+}
+''');
+
+    assertHasAssist(DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE, r'''
+main() {
+  var i = 12345;
+}
+''');
+  }
+
+  Future<void> _compute(String content) async {
+    _updateFile(content);
+
+    var result = await CiderAssistsComputer(
+      logger,
+      fileResolver,
+    ).compute(
+      convertPath(testPath),
+      _correctionContext.line,
+      _correctionContext.character,
+      0,
+    );
+    _assists = result;
+  }
+
+  Assist _getAssist(AssistKind kind) {
+    for (var assist in _assists) {
+      if (assist.kind == kind) {
+        return assist;
+      }
+    }
+    fail('No assist $kind');
+  }
+
+  void _updateFile(String content) {
+    var offset = content.indexOf('^');
+    expect(offset, isPositive, reason: 'Expected to find ^');
+    expect(content.indexOf('^', offset + 1), -1, reason: 'Expected only one ^');
+
+    var lineInfo = LineInfo.fromContent(content);
+    var location = lineInfo.getLocation(offset);
+
+    content = content.substring(0, offset) + content.substring(offset + 1);
+    newFile(testPath, content: content);
+
+    _correctionContext = _CorrectionContext(
+      content,
+      offset,
+      location.lineNumber - 1,
+      location.columnNumber - 1,
+    );
+  }
+}
+
+class _CorrectionContext {
+  final String content;
+  final int offset;
+  final int line;
+  final int character;
+
+  _CorrectionContext(this.content, this.offset, this.line, this.character);
+}
diff --git a/pkg/analysis_server/test/src/cider/test_all.dart b/pkg/analysis_server/test/src/cider/test_all.dart
index 9aea1f0..524383b 100644
--- a/pkg/analysis_server/test/src/cider/test_all.dart
+++ b/pkg/analysis_server/test/src/cider/test_all.dart
@@ -4,11 +4,13 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'assists_test.dart' as assists;
 import 'completion_test.dart' as completion;
 import 'fixes_test.dart' as fixes;
 
 void main() {
   defineReflectiveSuite(() {
+    assists.main();
     completion.main();
     fixes.main();
   });
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
index 69ebea3..5a01ac9 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
@@ -106,7 +106,7 @@
     isExpired: IsExpired.extension_types,
     documentation: 'Extension Types',
     experimentalReleaseVersion: null,
-    releaseVersion: Version.parse('2.13.0'),
+    releaseVersion: null,
   );
 
   static final generic_metadata = ExperimentalFeature(
@@ -204,7 +204,7 @@
   static const bool extension_methods = true;
 
   /// Default state of the experiment "extension-types"
-  static const bool extension_types = true;
+  static const bool extension_types = false;
 
   /// Default state of the experiment "generic-metadata"
   static const bool generic_metadata = false;
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index 8d44190..41413ee 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -772,11 +772,25 @@
       return result;
     } else {
       var firstAccessor = first as PropertyAccessorElement;
-      var result = PropertyAccessorElementImpl(firstAccessor.name, -1);
+      var variableName = firstAccessor.displayName;
+
+      var result = PropertyAccessorElementImpl(variableName, -1);
       result.enclosingElement = targetClass;
       result.isGetter = firstAccessor.isGetter;
+      result.isSetter = firstAccessor.isSetter;
       result.returnType = resultType.returnType;
       result.parameters = resultType.parameters;
+
+      var field = FieldElementImpl(variableName, -1);
+      if (firstAccessor.isGetter) {
+        field.getter = result;
+        field.type = result.returnType;
+      } else {
+        field.setter = result;
+        field.type = result.parameters[0].type;
+      }
+      result.variable = field;
+
       return result;
     }
   }
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
index d584afe..7e56db3 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
@@ -1140,7 +1140,7 @@
     );
   }
 
-  test_getMember_optIn_topMerge_getter() async {
+  test_getMember_optIn_topMerge_getter_existing() async {
     await resolveTestCode('''
 class A {
   dynamic get foo => 0;
@@ -1160,6 +1160,26 @@
     );
   }
 
+  test_getMember_optIn_topMerge_getter_synthetic() async {
+    await resolveTestCode('''
+abstract class A {
+  Future<void> get foo;
+}
+
+abstract class B {
+  Future<dynamic> get foo;
+}
+
+abstract class X extends A implements B {}
+''');
+
+    _assertGetMember(
+      className: 'X',
+      name: 'foo',
+      expected: 'X.foo: Future<Object?> Function()',
+    );
+  }
+
   test_getMember_optIn_topMerge_method() async {
     await resolveTestCode('''
 class A {
@@ -1180,7 +1200,7 @@
     );
   }
 
-  test_getMember_optIn_topMerge_setter() async {
+  test_getMember_optIn_topMerge_setter_existing() async {
     await resolveTestCode('''
 class A {
   set foo(dynamic _) {}
@@ -1200,6 +1220,26 @@
     );
   }
 
+  test_getMember_optIn_topMerge_setter_synthetic() async {
+    await resolveTestCode('''
+abstract class A {
+  set foo(Future<void> _);
+}
+
+abstract class B {
+  set foo(Future<dynamic> _);
+}
+
+abstract class X extends A implements B {}
+''');
+
+    _assertGetMember(
+      className: 'X',
+      name: 'foo=',
+      expected: 'X.foo=: void Function(Future<Object?>)',
+    );
+  }
+
   test_getMember_optOut_inheritsOptIn() async {
     newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
@@ -1299,6 +1339,16 @@
 
       var actual = '${enclosingElement.name}.${element.name}: $typeStr';
       expect(actual, expected);
+
+      if (element is PropertyAccessorElement) {
+        var variable = element.variable;
+        expect(variable.name, element.displayName);
+        if (element.isGetter) {
+          expect(variable.type, element.returnType);
+        } else {
+          expect(variable.type, element.parameters[0].type);
+        }
+      }
     } else {
       expect(element, isNull);
     }
diff --git a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
index 87b8431..1581d51 100644
--- a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
@@ -135,6 +135,55 @@
     );
   }
 
+  test_indexExpression_instance_compound_double_num() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  num operator[](int index) => 0;
+  operator[]=(int index, num _) {}
+}
+
+void f(A a) {
+  a[0] += 2.0;
+}
+''');
+
+    assertAssignment(
+      findNode.assignment('[0] += 2.0'),
+      readElement: findElement.method('[]'),
+      readType: 'num',
+      writeElement: findElement.method('[]='),
+      writeType: 'num',
+      operatorElement: elementMatcher(
+        numElement.getMethod('+'),
+        isLegacy: isNullSafetySdkAndLegacyLibrary,
+      ),
+      type: 'double',
+    );
+  }
+
+  test_indexExpression_instance_ifNull() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int? operator[](int? index) => 0;
+  operator[]=(int? index, num? _) {}
+}
+
+void f(A a) {
+  a[0] ??= 2;
+}
+''');
+
+    assertAssignment(
+      findNode.assignment('[0] ??= 2'),
+      readElement: findElement.method('[]'),
+      readType: 'int?',
+      writeElement: findElement.method('[]='),
+      writeType: 'num?',
+      operatorElement: null,
+      type: 'int',
+    );
+  }
+
   test_indexExpression_instance_simple() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -697,6 +746,37 @@
     assertType(assignment.rightHandSide, 'int');
   }
 
+  test_prefixedIdentifier_instance_ifNull() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int? get x => 0;
+  set x(num? _) {}
+}
+
+void f(A a) {
+  a.x ??= 2;
+}
+''');
+
+    var assignment = findNode.assignment('x ??= 2');
+    assertAssignment(
+      assignment,
+      readElement: findElement.getter('x'),
+      readType: 'int?',
+      writeElement: findElement.setter('x'),
+      writeType: 'num?',
+      operatorElement: null,
+      type: 'int',
+    );
+
+    var prefixed = assignment.leftHandSide as PrefixedIdentifier;
+    assertSimpleIdentifierAssignmentTarget(
+      prefixed.identifier,
+    );
+
+    assertType(assignment.rightHandSide, 'int');
+  }
+
   test_prefixedIdentifier_instance_simple() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -1104,6 +1184,37 @@
     assertType(assignment.rightHandSide, 'int');
   }
 
+  test_propertyAccess_instance_ifNull() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int? get x => 0;
+  set x(num? _) {}
+}
+
+void f(A a) {
+  (a).x ??= 2;
+}
+''');
+
+    var assignment = findNode.assignment('x ??= 2');
+    assertAssignment(
+      assignment,
+      readElement: findElement.getter('x'),
+      readType: 'int?',
+      writeElement: findElement.setter('x'),
+      writeType: 'num?',
+      operatorElement: null,
+      type: 'int',
+    );
+
+    var propertyAccess = assignment.leftHandSide as PropertyAccess;
+    assertSimpleIdentifierAssignmentTarget(
+      propertyAccess.propertyName,
+    );
+
+    assertType(assignment.rightHandSide, 'int');
+  }
+
   test_propertyAccess_instance_simple() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -2085,6 +2196,36 @@
     assertType(assignment.rightHandSide, 'int');
   }
 
+  test_simpleIdentifier_thisGetter_thisSetter_ifNull() async {
+    await assertNoErrorsInCode('''
+class C {
+  int? get x => 0;
+  set x(num? _) {}
+
+  void f() {
+    x ??= 2;
+  }
+}
+''');
+
+    var assignment = findNode.assignment('x ??= 2');
+    assertAssignment(
+      assignment,
+      readElement: findElement.getter('x'),
+      readType: 'int?',
+      writeElement: findElement.setter('x'),
+      writeType: 'num?',
+      operatorElement: null,
+      type: 'int',
+    );
+
+    assertSimpleIdentifierAssignmentTarget(
+      assignment.leftHandSide,
+    );
+
+    assertType(assignment.rightHandSide, 'int');
+  }
+
   test_simpleIdentifier_topGetter_superSetter_simple() async {
     await assertErrorsInCode('''
 class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/for_statement_test.dart b/pkg/analyzer/test/src/dart/resolution/for_statement_test.dart
index 0796c45..aab1ca9 100644
--- a/pkg/analyzer/test/src/dart/resolution/for_statement_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/for_statement_test.dart
@@ -17,6 +17,27 @@
 /// TODO(scheglov) Move other for-in tests here.
 @reflectiveTest
 class ForEachStatementResolutionTest extends PubPackageResolutionTest {
+  test_forIn_variable() async {
+    var code = r'''
+T f<T>() => null;
+
+void test(Iterable<num> iter) {
+  for (var w in f()) {} // 1
+  for (var x in iter) {} // 2
+  for (num y in f()) {} // 3
+}
+''';
+    await resolveTestCode(code);
+
+    assertType(findElement.localVar('w').type, 'Object?');
+    assertType(findNode.methodInvocation('f()) {} // 1'), 'Iterable<Object?>');
+
+    assertType(findElement.localVar('x').type, 'num');
+
+    assertType(findElement.localVar('y').type, 'num');
+    assertType(findNode.methodInvocation('f()) {} // 3'), 'Iterable<num>');
+  }
+
   test_iterable_missing() async {
     await assertErrorsInCode(r'''
 void f() {
diff --git a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
index d2ec94b..e7b1ac5 100644
--- a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
+++ b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
@@ -22,10 +22,7 @@
 ///
 /// https://github.com/dart-lang/sdk/issues/31638
 @reflectiveTest
-class Dart2InferenceTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
-  // TODO(https://github.com/dart-lang/sdk/issues/44666): Use null safety in
-  //  test cases.
+class Dart2InferenceTest extends PubPackageResolutionTest {
   test_bool_assert() async {
     var code = r'''
 T f<T>(int _) => null;
@@ -134,536 +131,6 @@
     assertType(closure, 'List<int> Function()');
   }
 
-  test_compoundAssignment_index() async {
-    await resolveTestCode(r'''
-int getInt() => 0;
-num getNum() => 0;
-double getDouble() => 0.0;
-
-abstract class Test<T, U> {
-  T operator [](String s);
-  void operator []=(String s, U v);
-}
-
-void test1(Test<int, int> t) {
-  var /*@type=int*/ v1 = t['x'] = getInt();
-  var /*@type=num*/ v2 = t['x'] = getNum();
-  var /*@type=int*/ v4 = t['x'] ??= getInt();
-  var /*@type=num*/ v5 = t['x'] ??= getNum();
-  var /*@type=int*/ v7 = t['x'] += getInt();
-  var /*@type=num*/ v8 = t['x'] += getNum();
-  var /*@type=int*/ v10 = ++t['x'];
-  var /*@type=int*/ v11 = t['x']++;
-}
-
-void test2(Test<int, num> t) {
-  var /*@type=int*/ v1 = t['x'] = getInt();
-  var /*@type=num*/ v2 = t['x'] = getNum();
-  var /*@type=double*/ v3 = t['x'] = getDouble();
-  var /*@type=int*/ v4 = t['x'] ??= getInt();
-  var /*@type=num*/ v5 = t['x'] ??= getNum();
-  var /*@type=num*/ v6 = t['x'] ??= getDouble();
-  var /*@type=int*/ v7 = t['x'] += getInt();
-  var /*@type=num*/ v8 = t['x'] += getNum();
-  var /*@type=double*/ v9 = t['x'] += getDouble();
-  var /*@type=int*/ v10 = ++t['x'];
-  var /*@type=int*/ v11 = t['x']++;
-}
-
-void test3(Test<int, double> t) {
-  var /*@type=num*/ v2 = t['x'] = getNum();
-  var /*@type=double*/ v3 = t['x'] = getDouble();
-  var /*@type=num*/ v5 = t['x'] ??= getNum();
-  var /*@type=num*/ v6 = t['x'] ??= getDouble();
-  var /*@type=int*/ v7 = t['x'] += getInt();
-  var /*@type=num*/ v8 = t['x'] += getNum();
-  var /*@type=double*/ v9 = t['x'] += getDouble();
-  var /*@type=int*/ v10 = ++t['x'];
-  var /*@type=int*/ v11 = t['x']++;
-}
-
-void test4(Test<num, int> t) {
-  var /*@type=int*/ v1 = t['x'] = getInt();
-  var /*@type=num*/ v2 = t['x'] = getNum();
-  var /*@type=num*/ v4 = t['x'] ??= getInt();
-  var /*@type=num*/ v5 = t['x'] ??= getNum();
-  var /*@type=num*/ v7 = t['x'] += getInt();
-  var /*@type=num*/ v8 = t['x'] += getNum();
-  var /*@type=num*/ v10 = ++t['x'];
-  var /*@type=num*/ v11 = t['x']++;
-}
-
-void test5(Test<num, num> t) {
-  var /*@type=int*/ v1 = t['x'] = getInt();
-  var /*@type=num*/ v2 = t['x'] = getNum();
-  var /*@type=double*/ v3 = t['x'] = getDouble();
-  var /*@type=num*/ v4 = t['x'] ??= getInt();
-  var /*@type=num*/ v5 = t['x'] ??= getNum();
-  var /*@type=num*/ v6 = t['x'] ??= getDouble();
-  var /*@type=num*/ v7 = t['x'] += getInt();
-  var /*@type=num*/ v8 = t['x'] += getNum();
-  var /*@type=num*/ v9 = t['x'] += getDouble();
-  var /*@type=num*/ v10 = ++t['x'];
-  var /*@type=num*/ v11 = t['x']++;
-}
-
-void test6(Test<num, double> t) {
-  var /*@type=num*/ v2 = t['x'] = getNum();
-  var /*@type=double*/ v3 = t['x'] = getDouble();
-  var /*@type=num*/ v5 = t['x'] ??= getNum();
-  var /*@type=num*/ v6 = t['x'] ??= getDouble();
-  var /*@type=num*/ v7 = t['x'] += getInt();
-  var /*@type=num*/ v8 = t['x'] += getNum();
-  var /*@type=num*/ v9 = t['x'] += getDouble();
-  var /*@type=num*/ v10 = ++t['x'];
-  var /*@type=num*/ v11 = t['x']++;
-}
-
-void test7(Test<double, int> t) {
-  var /*@type=int*/ v1 = t['x'] = getInt();
-  var /*@type=num*/ v2 = t['x'] = getNum();
-  var /*@type=num*/ v4 = t['x'] ??= getInt();
-  var /*@type=num*/ v5 = t['x'] ??= getNum();
-  var /*@type=double*/ v7 = t['x'] += getInt();
-  var /*@type=double*/ v8 = t['x'] += getNum();
-  var /*@type=double*/ v10 = ++t['x'];
-  var /*@type=double*/ v11 = t['x']++;
-}
-
-void test8(Test<double, num> t) {
-  var /*@type=int*/ v1 = t['x'] = getInt();
-  var /*@type=num*/ v2 = t['x'] = getNum();
-  var /*@type=double*/ v3 = t['x'] = getDouble();
-  var /*@type=num*/ v4 = t['x'] ??= getInt();
-  var /*@type=num*/ v5 = t['x'] ??= getNum();
-  var /*@type=double*/ v6 = t['x'] ??= getDouble();
-  var /*@type=double*/ v7 = t['x'] += getInt();
-  var /*@type=double*/ v8 = t['x'] += getNum();
-  var /*@type=double*/ v9 = t['x'] += getDouble();
-  var /*@type=double*/ v10 = ++t['x'];
-  var /*@type=double*/ v11 = t['x']++;
-}
-
-void test9(Test<double, double> t) {
-  var /*@type=num*/ v2 = t['x'] = getNum();
-  var /*@type=double*/ v3 = t['x'] = getDouble();
-  var /*@type=num*/ v5 = t['x'] ??= getNum();
-  var /*@type=double*/ v6 = t['x'] ??= getDouble();
-  var /*@type=double*/ v7 = t['x'] += getInt();
-  var /*@type=double*/ v8 = t['x'] += getNum();
-  var /*@type=double*/ v9 = t['x'] += getDouble();
-  var /*@type=double*/ v10 = ++t['x'];
-  var /*@type=double*/ v11 = t['x']++;
-}
-''');
-    _assertTypeAnnotations();
-  }
-
-  test_compoundAssignment_prefixedIdentifier() async {
-    await assertErrorsInCode(r'''
-int getInt() => 0;
-num getNum() => 0;
-double getDouble() => 0.0;
-
-class Test<T extends U, U> {
-  T get x => null;
-  void set x(U _) {}
-}
-
-void test1(Test<int, int> t) {
-  var /*@type=int*/ v1 = t.x = getInt();
-  var /*@type=num*/ v2 = t.x = getNum();
-  var /*@type=int*/ v4 = t.x ??= getInt();
-  var /*@type=num*/ v5 = t.x ??= getNum();
-  var /*@type=int*/ v7 = t.x += getInt();
-  var /*@type=num*/ v8 = t.x += getNum();
-  var /*@type=int*/ v10 = ++t.x;
-  var /*@type=int*/ v11 = t.x++;
-}
-
-void test2(Test<int, num> t) {
-  var /*@type=int*/ v1 = t.x = getInt();
-  var /*@type=num*/ v2 = t.x = getNum();
-  var /*@type=double*/ v3 = t.x = getDouble();
-  var /*@type=int*/ v4 = t.x ??= getInt();
-  var /*@type=num*/ v5 = t.x ??= getNum();
-  var /*@type=num*/ v6 = t.x ??= getDouble();
-  var /*@type=int*/ v7 = t.x += getInt();
-  var /*@type=num*/ v8 = t.x += getNum();
-  var /*@type=double*/ v9 = t.x += getDouble();
-  var /*@type=int*/ v10 = ++t.x;
-  var /*@type=int*/ v11 = t.x++;
-}
-
-void test5(Test<num, num> t) {
-  var /*@type=int*/ v1 = t.x = getInt();
-  var /*@type=num*/ v2 = t.x = getNum();
-  var /*@type=double*/ v3 = t.x = getDouble();
-  var /*@type=num*/ v4 = t.x ??= getInt();
-  var /*@type=num*/ v5 = t.x ??= getNum();
-  var /*@type=num*/ v6 = t.x ??= getDouble();
-  var /*@type=num*/ v7 = t.x += getInt();
-  var /*@type=num*/ v8 = t.x += getNum();
-  var /*@type=num*/ v9 = t.x += getDouble();
-  var /*@type=num*/ v10 = ++t.x;
-  var /*@type=num*/ v11 = t.x++;
-}
-
-void test8(Test<double, num> t) {
-  var /*@type=int*/ v1 = t.x = getInt();
-  var /*@type=num*/ v2 = t.x = getNum();
-  var /*@type=double*/ v3 = t.x = getDouble();
-  var /*@type=num*/ v4 = t.x ??= getInt();
-  var /*@type=num*/ v5 = t.x ??= getNum();
-  var /*@type=double*/ v6 = t.x ??= getDouble();
-  var /*@type=double*/ v7 = t.x += getInt();
-  var /*@type=double*/ v8 = t.x += getNum();
-  var /*@type=double*/ v9 = t.x += getDouble();
-  var /*@type=double*/ v10 = ++t.x;
-  var /*@type=double*/ v11 = t.x++;
-}
-
-void test9(Test<double, double> t) {
-  var /*@type=num*/ v2 = t.x = getNum();
-  var /*@type=double*/ v3 = t.x = getDouble();
-  var /*@type=num*/ v5 = t.x ??= getNum();
-  var /*@type=double*/ v6 = t.x ??= getDouble();
-  var /*@type=double*/ v7 = t.x += getInt();
-  var /*@type=double*/ v8 = t.x += getNum();
-  var /*@type=double*/ v9 = t.x += getDouble();
-  var /*@type=double*/ v10 = ++t.x;
-  var /*@type=double*/ v11 = t.x++;
-}
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 189, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 230, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 271, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 314, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 357, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 399, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 441, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 474, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 541, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 582, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 626, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 670, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 713, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 756, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 802, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 844, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 889, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 934, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 967, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1034, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1075, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1119, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1163, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1206, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1249, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1295, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1337, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1379, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1424, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1457, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1527, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1568, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1612, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1656, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1699, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1745, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1794, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1839, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1884, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1932, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1968, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2041, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2085, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2129, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2175, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2224, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2269, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2314, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2362, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2398, 3),
-    ]);
-    _assertTypeAnnotations();
-  }
-
-  test_compoundAssignment_propertyAccess() async {
-    var t1 = 'new Test<int, int>()';
-    var t2 = 'new Test<int, num>()';
-    var t5 = 'new Test<num, num>()';
-    var t8 = 'new Test<double, num>()';
-    var t9 = 'new Test<double, double>()';
-    await assertErrorsInCode('''
-int getInt() => 0;
-num getNum() => 0;
-double getDouble() => 0.0;
-
-class Test<T extends U, U> {
-  T get x => null;
-  void set x(U _) {}
-}
-
-void test1() {
-  var /*@type=int*/ v1 = $t1.x = getInt();
-  var /*@type=num*/ v2 = $t1.x = getNum();
-  var /*@type=int*/ v4 = $t1.x ??= getInt();
-  var /*@type=num*/ v5 = $t1.x ??= getNum();
-  var /*@type=int*/ v7 = $t1.x += getInt();
-  var /*@type=num*/ v8 = $t1.x += getNum();
-  var /*@type=int*/ v10 = ++$t1.x;
-  var /*@type=int*/ v11 = $t1.x++;
-}
-
-void test2() {
-  var /*@type=int*/ v1 = $t2.x = getInt();
-  var /*@type=num*/ v2 = $t2.x = getNum();
-  var /*@type=double*/ v3 = $t2.x = getDouble();
-  var /*@type=int*/ v4 = $t2.x ??= getInt();
-  var /*@type=num*/ v5 = $t2.x ??= getNum();
-  var /*@type=num*/ v6 = $t2.x ??= getDouble();
-  var /*@type=int*/ v7 = $t2.x += getInt();
-  var /*@type=num*/ v8 = $t2.x += getNum();
-  var /*@type=double*/ v9 = $t2.x += getDouble();
-  var /*@type=int*/ v10 = ++$t2.x;
-  var /*@type=int*/ v11 = $t2.x++;
-}
-
-void test5() {
-  var /*@type=int*/ v1 = $t5.x = getInt();
-  var /*@type=num*/ v2 = $t5.x = getNum();
-  var /*@type=double*/ v3 = $t5.x = getDouble();
-  var /*@type=num*/ v4 = $t5.x ??= getInt();
-  var /*@type=num*/ v5 = $t5.x ??= getNum();
-  var /*@type=num*/ v6 = $t5.x ??= getDouble();
-  var /*@type=num*/ v7 = $t5.x += getInt();
-  var /*@type=num*/ v8 = $t5.x += getNum();
-  var /*@type=num*/ v9 = $t5.x += getDouble();
-  var /*@type=num*/ v10 = ++$t5.x;
-  var /*@type=num*/ v11 = $t5.x++;
-}
-
-void test8() {
-  var /*@type=int*/ v1 = $t8.x = getInt();
-  var /*@type=num*/ v2 = $t8.x = getNum();
-  var /*@type=double*/ v3 = $t8.x = getDouble();
-  var /*@type=num*/ v4 = $t8.x ??= getInt();
-  var /*@type=num*/ v5 = $t8.x ??= getNum();
-  var /*@type=double*/ v6 = $t8.x ??= getDouble();
-  var /*@type=double*/ v7 = $t8.x += getInt();
-  var /*@type=double*/ v8 = $t8.x += getNum();
-  var /*@type=double*/ v9 = $t8.x += getDouble();
-  var /*@type=double*/ v10 = ++$t8.x;
-  var /*@type=double*/ v11 = $t8.x++;
-}
-
-void test9() {
-  var /*@type=num*/ v2 = $t9.x = getNum();
-  var /*@type=double*/ v3 = $t9.x = getDouble();
-  var /*@type=num*/ v5 = $t9.x ??= getNum();
-  var /*@type=double*/ v6 = $t9.x ??= getDouble();
-  var /*@type=double*/ v7 = $t9.x += getInt();
-  var /*@type=double*/ v8 = $t9.x += getNum();
-  var /*@type=double*/ v9 = $t9.x += getDouble();
-  var /*@type=double*/ v10 = ++$t9.x;
-  var /*@type=double*/ v11 = $t9.x++;
-}
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 173, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 233, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 293, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 355, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 417, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 478, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 539, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 591, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 661, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 721, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 784, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 847, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 909, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 971, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1036, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1097, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1161, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1225, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1277, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1347, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1407, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1470, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1533, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1595, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1657, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1722, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1783, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1844, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1908, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1960, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2030, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2093, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2159, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2225, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2290, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2358, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2429, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2496, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2563, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2633, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2691, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2764, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2833, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2902, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2973, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 3047, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 3117, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 3187, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 3260, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 3321, 3),
-    ]);
-    _assertTypeAnnotations();
-  }
-
-  test_compoundAssignment_simpleIdentifier() async {
-    await assertErrorsInCode(r'''
-int getInt() => 0;
-num getNum() => 0;
-double getDouble() => 0.0;
-
-class Test<T extends U, U> {
-  T get x => null;
-  void set x(U _) {}
-}
-
-class Test1 extends Test<int, int> {
-  void test1() {
-    var /*@type=int*/ v1 = x = getInt();
-    var /*@type=num*/ v2 = x = getNum();
-    var /*@type=int*/ v4 = x ??= getInt();
-    var /*@type=num*/ v5 = x ??= getNum();
-    var /*@type=int*/ v7 = x += getInt();
-    var /*@type=num*/ v8 = x += getNum();
-    var /*@type=int*/ v10 = ++x;
-    var /*@type=int*/ v11 = x++;
-  }
-}
-
-class Test2 extends Test<int, num> {
-  void test2() {
-    var /*@type=int*/ v1 = x = getInt();
-    var /*@type=num*/ v2 = x = getNum();
-    var /*@type=double*/ v3 = x = getDouble();
-    var /*@type=int*/ v4 = x ??= getInt();
-    var /*@type=num*/ v5 = x ??= getNum();
-    var /*@type=num*/ v6 = x ??= getDouble();
-    var /*@type=int*/ v7 = x += getInt();
-    var /*@type=num*/ v8 = x += getNum();
-    var /*@type=double*/ v9 = x += getDouble();
-    var /*@type=int*/ v10 = ++x;
-    var /*@type=int*/ v11 = x++;
-  }
-}
-
-class Test5 extends Test<num, num> {
-  void test5() {
-    var /*@type=int*/ v1 = x = getInt();
-    var /*@type=num*/ v2 = x = getNum();
-    var /*@type=double*/ v3 = x = getDouble();
-    var /*@type=num*/ v4 = x ??= getInt();
-    var /*@type=num*/ v5 = x ??= getNum();
-    var /*@type=num*/ v6 = x ??= getDouble();
-    var /*@type=num*/ v7 = x += getInt();
-    var /*@type=num*/ v8 = x += getNum();
-    var /*@type=num*/ v9 = x += getDouble();
-    var /*@type=num*/ v10 = ++x;
-    var /*@type=num*/ v11 = x++;
-  }
-}
-
-class Test8 extends Test<double, num> {
-  void test8() {
-    var /*@type=int*/ v1 = x = getInt();
-    var /*@type=num*/ v2 = x = getNum();
-    var /*@type=double*/ v3 = x = getDouble();
-    var /*@type=num*/ v4 = x ??= getInt();
-    var /*@type=num*/ v5 = x ??= getNum();
-    var /*@type=double*/ v6 = x ??= getDouble();
-    var /*@type=double*/ v7 = x += getInt();
-    var /*@type=double*/ v8 = x += getNum();
-    var /*@type=double*/ v9 = x += getDouble();
-    var /*@type=double*/ v10 = ++x;
-    var /*@type=double*/ v11 = x++;
-  }
-}
-
-class Test9 extends Test<double, double> {
-  void test9() {
-    var /*@type=num*/ v2 = x = getNum();
-    var /*@type=double*/ v3 = x = getDouble();
-    var /*@type=num*/ v5 = x ??= getNum();
-    var /*@type=double*/ v6 = x ??= getDouble();
-    var /*@type=double*/ v7 = x += getInt();
-    var /*@type=double*/ v8 = x += getNum();
-    var /*@type=double*/ v9 = x += getDouble();
-    var /*@type=double*/ v10 = ++x;
-    var /*@type=double*/ v11 = x++;
-  }
-}
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 214, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 255, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 296, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 339, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 382, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 424, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 466, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 499, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 593, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 634, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 678, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 722, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 765, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 808, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 854, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 896, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 941, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 986, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1019, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1113, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1154, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1198, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1242, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1285, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1328, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1374, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1416, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1458, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1503, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1536, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1633, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1674, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1718, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1762, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1805, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1851, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1900, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1945, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 1990, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2038, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2074, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2174, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2218, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2262, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2308, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2357, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2402, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2447, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2495, 3),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 2531, 3),
-    ]);
-    _assertTypeAnnotations();
-  }
-
   test_compoundAssignment_simpleIdentifier_topLevel() async {
     await assertErrorsInCode(r'''
 class A {}
@@ -719,46 +186,6 @@
     assertInvocationType('f()) {} // top setter');
   }
 
-  test_forIn_variable() async {
-    var code = r'''
-T f<T>() => null;
-
-void test(Iterable<num> iter) {
-  for (var w in f()) {} // 1
-  for (var x in iter) {} // 2
-  for (num y in f()) {} // 3
-}
-''';
-    await resolveTestCode(code);
-    {
-      var node = findNode.simple('w in');
-      var element = node.staticElement as VariableElement;
-      expect(node.staticType, isNull);
-      expect(element.type, typeProvider.dynamicType);
-
-      var invocation = findNode.methodInvocation('f()) {} // 1');
-      assertType(invocation, 'Iterable<dynamic>');
-    }
-
-    {
-      var node = findNode.simple('x in');
-      var element = node.staticElement as VariableElement;
-      expect(node.staticType, isNull);
-      expect(element.type, typeProvider.numType);
-    }
-
-    {
-      var node = findNode.simple('y in');
-      var element = node.staticElement as VariableElement;
-
-      expect(node.staticType, isNull);
-      expect(element.type, typeProvider.numType);
-
-      var invocation = findNode.methodInvocation('f()) {} // 3');
-      assertType(invocation, 'Iterable<num>');
-    }
-  }
-
   test_forIn_variable_implicitlyTyped() async {
     var code = r'''
 class A {}
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
index 699e59c..2c56811 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
@@ -79,7 +79,7 @@
   ExperimentalFlag.constantUpdate2018: true,
   ExperimentalFlag.controlFlowCollections: true,
   ExperimentalFlag.extensionMethods: true,
-  ExperimentalFlag.extensionTypes: true,
+  ExperimentalFlag.extensionTypes: false,
   ExperimentalFlag.genericMetadata: false,
   ExperimentalFlag.nonNullable: true,
   ExperimentalFlag.nonfunctionTypeAliases: false,
diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart
index 33b9faa..1b23da1 100644
--- a/pkg/front_end/lib/src/api_unstable/vm.dart
+++ b/pkg/front_end/lib/src/api_unstable/vm.dart
@@ -62,6 +62,7 @@
         templateFfiFieldCyclic,
         templateFfiFieldInitializer,
         templateFfiFieldNoAnnotation,
+        templateFfiFieldNull,
         templateFfiNotStatic,
         templateFfiStructGeneric,
         templateFfiTypeInvalid,
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 90141d2..725ff20 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -61,6 +61,8 @@
 
 import '../type_inference/type_schema.dart' show UnknownType;
 
+import '../util/helpers.dart' show DelayedActionPerformer;
+
 import 'builder.dart';
 import 'constructor_builder.dart';
 import 'constructor_reference_builder.dart';
@@ -122,7 +124,8 @@
 
   List<ConstructorReferenceBuilder> get constructorReferences;
 
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes);
+  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers);
 
   /// Registers a constructor redirection for this class and returns true if
   /// this redirection gives rise to a cycle that has not been reported before.
@@ -349,10 +352,12 @@
   }
 
   @override
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {
+  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers) {
     void build(String ignore, Builder declaration) {
       MemberBuilder member = declaration;
-      member.buildOutlineExpressions(library, coreTypes);
+      member.buildOutlineExpressions(
+          library, coreTypes, delayedActionPerformers);
     }
 
     MetadataBuilder.buildAnnotations(
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
index 432df8c..1b544eb 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -36,6 +36,7 @@
 
 import '../source/source_class_builder.dart';
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+import '../util/helpers.dart' show DelayedActionPerformer;
 
 import 'builder.dart';
 import 'class_builder.dart';
@@ -239,8 +240,9 @@
   }
 
   @override
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {
-    super.buildOutlineExpressions(library, coreTypes);
+  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers) {
+    super.buildOutlineExpressions(library, coreTypes, delayedActionPerformers);
 
     // For modular compilation purposes we need to include initializers
     // for const constructors into the outline.
@@ -451,10 +453,13 @@
         super(constructor, parent);
 
   void buildOutlineExpressions(
-      LibraryBuilder libraryBuilder, CoreTypes coreTypes) {
+      LibraryBuilder libraryBuilder,
+      CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers) {
     if (_origin != null) {
       // Ensure that default value expressions have been created for [_origin].
-      _origin.buildOutlineExpressions(libraryBuilder, coreTypes);
+      _origin.buildOutlineExpressions(
+          libraryBuilder, coreTypes, delayedActionPerformers);
       _clonedFunctionNode.cloneDefaultValues();
       _clonedFunctionNode = null;
       _origin = null;
diff --git a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
index 79c6bc6..5c150ad 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -10,6 +10,7 @@
 import '../fasta_codes.dart' show templateInternalProblemNotFoundIn;
 import '../scope.dart';
 import '../problems.dart';
+import '../util/helpers.dart';
 
 import 'builder.dart';
 import 'library_builder.dart';
@@ -27,7 +28,8 @@
   /// Return the [Extension] built by this builder.
   Extension get extension;
 
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes);
+  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers);
 
   /// Looks up extension member by [name] taking privacy into account.
   ///
@@ -145,10 +147,12 @@
   String get debugName => "ExtensionBuilder";
 
   @override
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {
+  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers) {
     void build(String ignore, Builder declaration) {
       MemberBuilder member = declaration;
-      member.buildOutlineExpressions(library, coreTypes);
+      member.buildOutlineExpressions(
+          library, coreTypes, delayedActionPerformers);
     }
 
     // TODO(johnniwinther): Handle annotations on the extension declaration.
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 1fe24be..da7aea2 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -35,6 +35,8 @@
 import '../type_inference/type_inference_engine.dart'
     show IncludesTypeParametersNonCovariantly;
 
+import '../util/helpers.dart' show DelayedActionPerformer;
+
 import 'class_builder.dart';
 import 'extension_builder.dart';
 import 'library_builder.dart';
@@ -376,7 +378,8 @@
   }
 
   @override
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {
+  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers) {
     _fieldEncoding.completeSignature(coreTypes);
 
     ClassBuilder classBuilder = isClassMember ? parent : null;
@@ -417,6 +420,9 @@
       }
       buildBody(coreTypes, initializer);
       bodyBuilder.resolveRedirectingFactoryTargets();
+      if (bodyBuilder.hasDelayedActions) {
+        delayedActionPerformers.add(bodyBuilder);
+      }
     }
     constInitializerToken = null;
   }
diff --git a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
index 3b8fe9b..1b034996 100644
--- a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
@@ -37,6 +37,8 @@
 
 import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
 
+import '../util/helpers.dart' show DelayedActionPerformer;
+
 import 'builder.dart';
 import 'class_builder.dart';
 import 'constructor_builder.dart';
@@ -177,7 +179,8 @@
 
   /// Builds the default value from this [initializerToken] if this is a
   /// formal parameter on a const constructor or instance method.
-  void buildOutlineExpressions(LibraryBuilder library) {
+  void buildOutlineExpressions(LibraryBuilder library,
+      List<DelayedActionPerformer> delayedActionPerformers) {
     if (initializerToken != null) {
       // For modular compilation we need to include initializers for optional
       // and named parameters of const constructors into the outline - to enable
@@ -213,6 +216,9 @@
         }
         initializerWasInferred = true;
         bodyBuilder.resolveRedirectingFactoryTargets();
+        if (bodyBuilder.hasDelayedActions) {
+          delayedActionPerformers.add(bodyBuilder);
+        }
       }
     }
     initializerToken = null;
diff --git a/pkg/front_end/lib/src/fasta/builder/function_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
index b938323..8477784 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
@@ -37,6 +37,8 @@
 import '../type_inference/type_inference_engine.dart'
     show IncludesTypeParametersNonCovariantly;
 
+import '../util/helpers.dart' show DelayedActionPerformer;
+
 import 'builder.dart';
 import 'class_builder.dart';
 import 'extension_builder.dart';
@@ -501,7 +503,8 @@
   bool _hasBuiltOutlineExpressions = false;
 
   @override
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {
+  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers) {
     if (!_hasBuiltOutlineExpressions) {
       MetadataBuilder.buildAnnotations(
           member, metadata, library, isClassMember ? parent : null, this);
@@ -512,7 +515,7 @@
         // buildOutlineExpressions to clear initializerToken to prevent
         // consuming too much memory.
         for (FormalParameterBuilder formal in formals) {
-          formal.buildOutlineExpressions(library);
+          formal.buildOutlineExpressions(library, delayedActionPerformers);
         }
       }
       _hasBuiltOutlineExpressions = true;
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 51ee376..070d275 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -16,6 +16,7 @@
 import '../problems.dart' show unsupported;
 import '../type_inference/type_inference_engine.dart'
     show InferenceDataForTesting;
+import '../util/helpers.dart' show DelayedActionPerformer;
 
 import 'builder.dart';
 import 'class_builder.dart';
@@ -72,7 +73,8 @@
   /// setter of a field.
   bool get isConflictingSetter;
 
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes);
+  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers);
 
   /// Returns the [ClassMember]s for the non-setter members created for this
   /// member builder.
@@ -171,7 +173,8 @@
   ProcedureKind get kind => unsupported("kind", charOffset, fileUri);
 
   @override
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {}
+  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers) {}
 
   /// Builds the core AST structures for this member as needed for the outline.
   void buildMembers(
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index c7b250b..4c89f92 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -28,6 +28,8 @@
 import '../type_inference/type_inferrer.dart';
 import '../type_inference/type_schema.dart';
 
+import '../util/helpers.dart';
+
 import 'builder.dart';
 import 'constructor_reference_builder.dart';
 import 'extension_builder.dart';
@@ -762,8 +764,9 @@
   }
 
   @override
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {
-    super.buildOutlineExpressions(library, coreTypes);
+  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers) {
+    super.buildOutlineExpressions(library, coreTypes, delayedActionPerformers);
     LibraryBuilder thisLibrary = this.library;
     if (thisLibrary is SourceLibraryBuilder) {
       RedirectingFactoryBody redirectingFactoryBody = procedure.function.body;
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 92a5cab..ec1a7ec 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -113,6 +113,10 @@
 import '../type_inference/type_promotion.dart'
     show TypePromoter, TypePromotionFact, TypePromotionScope;
 
+import '../type_inference/type_schema.dart' show UnknownType;
+
+import '../util/helpers.dart' show DelayedActionPerformer;
+
 import 'collections.dart';
 
 import 'constness.dart' show Constness;
@@ -151,7 +155,7 @@
 const Object invalidCollectionElement = const Object();
 
 class BodyBuilder extends ScopeListener<JumpTarget>
-    implements ExpressionGeneratorHelper, EnsureLoaded {
+    implements ExpressionGeneratorHelper, EnsureLoaded, DelayedActionPerformer {
   final Forest forest;
 
   // TODO(ahe): Rename [library] to 'part'.
@@ -313,6 +317,13 @@
   /// invocations are to be resolved in a separate step.
   final List<Expression> redirectingFactoryInvocations = <Expression>[];
 
+  /// List of redirecting factory invocations delayed for resolution.
+  ///
+  /// A resolution of a redirecting factory invocation can be delayed because
+  /// the inference in the declaration of the redirecting factory isn't done
+  /// yet.
+  final List<Expression> delayedRedirectingFactoryInvocations = <Expression>[];
+
   /// List of built type aliased generative constructor invocations that
   /// require unaliasing.
   final List<TypeAliasedConstructorInvocationJudgment>
@@ -1160,7 +1171,8 @@
   void resolveRedirectingFactoryTargets() {
     _unaliasTypeAliasedConstructorInvocations();
     _unaliasTypeAliasedFactoryInvocations();
-    _resolveRedirectingFactoryTargets();
+    _resolveRedirectingFactoryTargets(
+        redirectingFactoryInvocations, delayedRedirectingFactoryInvocations);
   }
 
   /// Return an [Expression] resolving the argument invocation.
@@ -1168,6 +1180,7 @@
   /// The arguments specify the [StaticInvocation] whose `.target` is
   /// [target], `.arguments` is [arguments], `.fileOffset` is [fileOffset],
   /// and `.isConst` is [isConst].
+  /// Returns null if the invocation can't be resolved.
   Expression _resolveRedirectingFactoryTarget(
       Procedure target, Arguments arguments, int fileOffset, bool isConst) {
     Procedure initialTarget = target;
@@ -1176,6 +1189,10 @@
     RedirectionTarget redirectionTarget =
         getRedirectionTarget(initialTarget, this);
     Member resolvedTarget = redirectionTarget?.target;
+    if (redirectionTarget != null &&
+        redirectionTarget.typeArguments.any((type) => type is UnknownType)) {
+      return null;
+    }
 
     if (resolvedTarget == null) {
       String name = constructorNameForDiagnostics(initialTarget.name.text,
@@ -1233,7 +1250,9 @@
     return replacementNode;
   }
 
-  void _resolveRedirectingFactoryTargets() {
+  void _resolveRedirectingFactoryTargets(
+      List<Expression> redirectingFactoryInvocations,
+      List<Expression> delayedRedirectingFactoryInvocations) {
     for (StaticInvocation invocation in redirectingFactoryInvocations) {
       // If the invocation was invalid, it or its parent has already been
       // desugared into an exception throwing expression.  There is nothing to
@@ -1254,8 +1273,16 @@
         }
         if (parent == null) continue;
       }
-      invocation.replaceWith(_resolveRedirectingFactoryTarget(invocation.target,
-          invocation.arguments, invocation.fileOffset, invocation.isConst));
+      Expression replacement = _resolveRedirectingFactoryTarget(
+          invocation.target,
+          invocation.arguments,
+          invocation.fileOffset,
+          invocation.isConst);
+      if (replacement == null) {
+        delayedRedirectingFactoryInvocations?.add(invocation);
+      } else {
+        invocation.replaceWith(replacement);
+      }
     }
     redirectingFactoryInvocations.clear();
   }
@@ -1306,6 +1333,33 @@
     typeAliasedFactoryInvocations.clear();
   }
 
+  /// Perform actions that were delayed
+  ///
+  /// An action can be delayed, for instance, because it depends on some
+  /// calculations in another library.  For example, a resolution of a
+  /// redirecting factory invocation depends on the type inference in the
+  /// redirecting factory.
+  void performDelayedActions() {
+    if (delayedRedirectingFactoryInvocations.isNotEmpty) {
+      _resolveRedirectingFactoryTargets(
+          delayedRedirectingFactoryInvocations, null);
+      if (delayedRedirectingFactoryInvocations.isNotEmpty) {
+        for (StaticInvocation invocation
+            in delayedRedirectingFactoryInvocations) {
+          internalProblem(
+              fasta.templateInternalProblemUnhandled.withArguments(
+                  invocation.target.name.text, 'performDelayedActions'),
+              invocation.fileOffset,
+              uri);
+        }
+      }
+    }
+  }
+
+  bool get hasDelayedActions {
+    return delayedRedirectingFactoryInvocations.isNotEmpty;
+  }
+
   void finishVariableMetadata() {
     List<VariableDeclaration> variablesWithMetadata =
         this.variablesWithMetadata;
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index 004901a..62852fb 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -17,6 +17,7 @@
 import 'builder/type_variable_builder.dart';
 import 'kernel/body_builder.dart' show JumpTarget;
 import 'kernel/class_hierarchy_builder.dart' show ClassMember;
+import 'util/helpers.dart' show DelayedActionPerformer;
 
 import 'fasta_codes.dart'
     show
@@ -799,7 +800,8 @@
   ProcedureKind get kind => null;
 
   @override
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {
+  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers) {
     throw new UnsupportedError(
         'AmbiguousMemberBuilder.buildOutlineExpressions');
   }
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 153430d6..ac98e95 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -110,6 +110,8 @@
 
 import '../type_inference/type_inferrer.dart';
 
+import '../util/helpers.dart';
+
 import 'diet_listener.dart' show DietListener;
 
 import 'diet_parser.dart' show DietParser;
@@ -1134,6 +1136,8 @@
   }
 
   void buildOutlineExpressions(CoreTypes coreTypes) {
+    List<DelayedActionPerformer> delayedActionPerformers =
+        <DelayedActionPerformer>[];
     for (LibraryBuilder library in builders.values) {
       if (library.loader == this) {
         library.buildOutlineExpressions();
@@ -1141,15 +1145,22 @@
         while (iterator.moveNext()) {
           Builder declaration = iterator.current;
           if (declaration is ClassBuilder) {
-            declaration.buildOutlineExpressions(library, coreTypes);
+            declaration.buildOutlineExpressions(
+                library, coreTypes, delayedActionPerformers);
           } else if (declaration is ExtensionBuilder) {
-            declaration.buildOutlineExpressions(library, coreTypes);
+            declaration.buildOutlineExpressions(
+                library, coreTypes, delayedActionPerformers);
           } else if (declaration is MemberBuilder) {
-            declaration.buildOutlineExpressions(library, coreTypes);
+            declaration.buildOutlineExpressions(
+                library, coreTypes, delayedActionPerformers);
           }
         }
       }
     }
+    for (DelayedActionPerformer delayedActionPerformer
+        in delayedActionPerformers) {
+      delayedActionPerformer.performDelayedActions();
+    }
     ticker.logMs("Build outline expressions");
   }
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index a61e28f..3acf8bb 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -2788,6 +2788,13 @@
               fileOffset,
               noLength);
         } else {
+          // Handles cases like:
+          //   int? i;
+          //   i.methodOnNonNullInt();
+          // where `methodOnNonNullInt` is declared in an extension:
+          //   extension on int {
+          //     void methodOnNonNullInt() {}
+          //   }
           replacement = helper.wrapInProblem(
               replacement,
               templateNullableMethodCallError.withArguments(
@@ -2866,6 +2873,9 @@
             fileOffset,
             noLength);
       } else {
+        // Handles cases like:
+        //   void Function()? f;
+        //   f.call();
         replacement = helper.wrapInProblem(
             replacement,
             templateNullableMethodCallError.withArguments(
@@ -3029,6 +3039,9 @@
             fileOffset,
             noLength);
       } else {
+        // Handles cases like:
+        //   int? i;
+        //   i.abs();
         replacement = helper.wrapInProblem(
             replacement,
             templateNullableMethodCallError.withArguments(
diff --git a/pkg/front_end/lib/src/fasta/util/helpers.dart b/pkg/front_end/lib/src/fasta/util/helpers.dart
new file mode 100644
index 0000000..0e41efc
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/util/helpers.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class DelayedActionPerformer {
+  bool get hasDelayedActions;
+  void performDelayedActions();
+}
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index e07a53f..1124364 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -327,6 +327,7 @@
 FfiFieldCyclic/analyzerCode: Fail
 FfiFieldInitializer/analyzerCode: Fail
 FfiFieldNoAnnotation/analyzerCode: Fail
+FfiFieldNull/analyzerCode: Fail
 FfiNotStatic/analyzerCode: Fail
 FfiStructAnnotation/analyzerCode: Fail
 FfiStructGeneric/analyzerCode: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 5a98676..3c647b29 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -4225,6 +4225,11 @@
   template: "Expected type '#type' to be a valid and instantiated subtype of 'NativeType'."
   external: test/ffi_test.dart
 
+FfiFieldNull:
+  # Used by dart:ffi
+  template: "Field '#name' cannot have type 'Null', it must be `int`, `double`, `Pointer`, or a subtype of `Struct`."
+  external: test/ffi_test.dart
+
 FfiFieldAnnotation:
   # Used by dart:ffi
   template: "Field '#name' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields."
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 9601042..9a5012d 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -2164,6 +2164,8 @@
 perform
 performance
 performed
+performer
+performers
 performing
 performs
 perhaps
diff --git a/pkg/front_end/testcases/general/issue45003/bar_lib.dart b/pkg/front_end/testcases/general/issue45003/bar_lib.dart
new file mode 100644
index 0000000..15f7c60
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003/bar_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import './foo_lib.dart';
+
+class Bar<T> extends Foo {
+  const Bar();
+}
diff --git a/pkg/front_end/testcases/general/issue45003/foo_lib.dart b/pkg/front_end/testcases/general/issue45003/foo_lib.dart
new file mode 100644
index 0000000..3a7afdf
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003/foo_lib.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import './bar_lib.dart';
+
+export './bar_lib.dart';
+
+abstract class Foo {
+  const Foo();
+  const factory Foo.bar() = Bar;
+}
diff --git a/pkg/front_end/testcases/general/issue45003/main.dart b/pkg/front_end/testcases/general/issue45003/main.dart
new file mode 100644
index 0000000..47bbc28
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003/main.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import './foo_lib.dart';
+
+const Set<Foo> foo = <Foo>{Foo.bar()};
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue45003/main.dart.outline.expect b/pkg/front_end/testcases/general/issue45003/main.dart.outline.expect
new file mode 100644
index 0000000..7e18438
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003/main.dart.outline.expect
@@ -0,0 +1,57 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "foo_lib.dart" as foo;
+import "bar_lib.dart" as bar;
+
+import "org-dartlang-testcase:///foo_lib.dart";
+
+static const field core::Set<foo::Foo*>* foo = const <foo::Foo*>{const bar::Bar::•<dynamic>()};
+static method main() → dynamic
+  ;
+
+library;
+import self as foo;
+import "dart:core" as core;
+import "bar_lib.dart" as bar;
+additionalExports = (bar::Bar)
+
+import "org-dartlang-testcase:///bar_lib.dart";
+export "org-dartlang-testcase:///bar_lib.dart";
+
+abstract class Foo extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[foo::Foo::bar];
+  const constructor •() → foo::Foo*
+    : super core::Object::•()
+    ;
+  static factory bar() → foo::Foo*
+    let dynamic #redirecting_factory = bar::Bar::• in let dynamic #typeArg0 = null in invalid-expression;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+
+library;
+import self as bar;
+import "dart:core" as core;
+import "foo_lib.dart" as foo;
+
+import "org-dartlang-testcase:///foo_lib.dart";
+
+class Bar<T extends core::Object* = dynamic> extends foo::Foo /*hasConstConstructor*/  {
+  const constructor •() → bar::Bar<bar::Bar::T*>*
+    : super foo::Foo::•()
+    ;
+}
+
+
+Extra constant evaluation status:
+Evaluated: SetLiteral @ org-dartlang-testcase:///main.dart:7:27 -> InstanceConstant(const _UnmodifiableSet<Foo*>{_UnmodifiableSet._map: const _ImmutableMap<Foo*, Null>{_ImmutableMap._kvPairs: const <dynamic>[const Bar<dynamic>{}, null]}})
+Extra constant evaluation: evaluated: 6, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/issue45003/main.dart.strong.expect b/pkg/front_end/testcases/general/issue45003/main.dart.strong.expect
new file mode 100644
index 0000000..95d101a
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003/main.dart.strong.expect
@@ -0,0 +1,69 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "foo_lib.dart" as foo;
+
+import "org-dartlang-testcase:///foo_lib.dart";
+
+static const field core::Set<foo::Foo*>* foo = #C5;
+static method main() → dynamic {}
+
+library;
+import self as foo;
+import "dart:core" as core;
+import "bar_lib.dart" as bar;
+additionalExports = (bar::Bar)
+
+import "org-dartlang-testcase:///bar_lib.dart";
+export "org-dartlang-testcase:///bar_lib.dart";
+
+abstract class Foo extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[foo::Foo::bar];
+  const constructor •() → foo::Foo*
+    : super core::Object::•()
+    ;
+  static factory bar() → foo::Foo*
+    let dynamic #redirecting_factory = bar::Bar::• in let dynamic #typeArg0 = null in invalid-expression;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+
+library;
+import self as bar;
+import "dart:core" as core;
+import "foo_lib.dart" as foo;
+
+import "org-dartlang-testcase:///foo_lib.dart";
+
+class Bar<T extends core::Object* = dynamic> extends foo::Foo /*hasConstConstructor*/  {
+  const constructor •() → bar::Bar<bar::Bar::T*>*
+    : super foo::Foo::•()
+    ;
+}
+
+constants  {
+  #C1 = bar::Bar<dynamic> {}
+  #C2 = null
+  #C3 = <dynamic>[#C1, #C2]
+  #C4 = core::_ImmutableMap<foo::Foo*, Null> {_kvPairs:#C3}
+  #C5 = col::_UnmodifiableSet<foo::Foo*> {_map:#C4}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///main.dart:
+- Bar. (from org-dartlang-testcase:///bar_lib.dart:8:9)
+
+org-dartlang-testcase:///foo_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+
+org-dartlang-testcase:///bar_lib.dart:
+- Foo. (from org-dartlang-testcase:///foo_lib.dart:10:9)
diff --git a/pkg/front_end/testcases/general/issue45003/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue45003/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..bfa7543
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003/main.dart.strong.transformed.expect
@@ -0,0 +1,69 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "foo_lib.dart" as foo;
+
+import "org-dartlang-testcase:///foo_lib.dart";
+
+static const field core::Set<foo::Foo*>* foo = #C5;
+static method main() → dynamic {}
+
+library;
+import self as foo;
+import "dart:core" as core;
+import "bar_lib.dart" as bar;
+additionalExports = (bar::Bar)
+
+import "org-dartlang-testcase:///bar_lib.dart";
+export "org-dartlang-testcase:///bar_lib.dart";
+
+abstract class Foo extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[foo::Foo::bar];
+  const constructor •() → foo::Foo*
+    : super core::Object::•()
+    ;
+  static factory bar() → foo::Foo*
+    let<BottomType> #redirecting_factory = bar::Bar::• in let<BottomType> #typeArg0 = null in invalid-expression;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+
+library;
+import self as bar;
+import "dart:core" as core;
+import "foo_lib.dart" as foo;
+
+import "org-dartlang-testcase:///foo_lib.dart";
+
+class Bar<T extends core::Object* = dynamic> extends foo::Foo /*hasConstConstructor*/  {
+  const constructor •() → bar::Bar<bar::Bar::T*>*
+    : super foo::Foo::•()
+    ;
+}
+
+constants  {
+  #C1 = bar::Bar<dynamic> {}
+  #C2 = null
+  #C3 = <dynamic>[#C1, #C2]
+  #C4 = core::_ImmutableMap<foo::Foo*, Null> {_kvPairs:#C3}
+  #C5 = col::_UnmodifiableSet<foo::Foo*> {_map:#C4}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///main.dart:
+- Bar. (from org-dartlang-testcase:///bar_lib.dart:8:9)
+
+org-dartlang-testcase:///foo_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+
+org-dartlang-testcase:///bar_lib.dart:
+- Foo. (from org-dartlang-testcase:///foo_lib.dart:10:9)
diff --git a/pkg/front_end/testcases/general/issue45003/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue45003/main.dart.textual_outline.expect
new file mode 100644
index 0000000..c7dc4d4
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003/main.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+import './foo_lib.dart';
+
+const Set<Foo> foo = <Foo>{Foo.bar()};
+main() {}
diff --git a/pkg/front_end/testcases/general/issue45003/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue45003/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c7dc4d4
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,4 @@
+import './foo_lib.dart';
+
+const Set<Foo> foo = <Foo>{Foo.bar()};
+main() {}
diff --git a/pkg/front_end/testcases/general/issue45003/main.dart.weak.expect b/pkg/front_end/testcases/general/issue45003/main.dart.weak.expect
new file mode 100644
index 0000000..ba331a8
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003/main.dart.weak.expect
@@ -0,0 +1,59 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "foo_lib.dart" as foo;
+
+import "org-dartlang-testcase:///foo_lib.dart";
+
+static const field core::Set<foo::Foo> foo = #C5;
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as foo;
+import "dart:core" as core;
+import "bar_lib.dart" as bar;
+additionalExports = (bar::Bar)
+
+import "org-dartlang-testcase:///bar_lib.dart";
+export "org-dartlang-testcase:///bar_lib.dart";
+
+abstract class Foo extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[foo::Foo::bar]/*isLegacy*/;
+  const constructor •() → foo::Foo
+    : super core::Object::•()
+    ;
+  static factory bar() → foo::Foo
+    let dynamic #redirecting_factory = bar::Bar::• in let dynamic #typeArg0 = null in invalid-expression;
+}
+
+library /*isNonNullableByDefault*/;
+import self as bar;
+import "dart:core" as core;
+import "foo_lib.dart" as foo;
+
+import "org-dartlang-testcase:///foo_lib.dart";
+
+class Bar<T extends core::Object? = dynamic> extends foo::Foo /*hasConstConstructor*/  {
+  const constructor •() → bar::Bar<bar::Bar::T%>
+    : super foo::Foo::•()
+    ;
+}
+
+constants  {
+  #C1 = bar::Bar<dynamic> {}
+  #C2 = null
+  #C3 = <dynamic>[#C1, #C2]
+  #C4 = core::_ImmutableMap<foo::Foo*, Null> {_kvPairs:#C3}
+  #C5 = col::_UnmodifiableSet<foo::Foo*> {_map:#C4}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///main.dart:
+- Bar. (from org-dartlang-testcase:///bar_lib.dart:8:9)
+
+org-dartlang-testcase:///foo_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+
+org-dartlang-testcase:///bar_lib.dart:
+- Foo. (from org-dartlang-testcase:///foo_lib.dart:10:9)
diff --git a/pkg/front_end/testcases/general/issue45003/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue45003/main.dart.weak.outline.expect
new file mode 100644
index 0000000..e71f7a0
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003/main.dart.weak.outline.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "foo_lib.dart" as foo;
+import "bar_lib.dart" as bar;
+
+import "org-dartlang-testcase:///foo_lib.dart";
+
+static const field core::Set<foo::Foo> foo = const <foo::Foo>{const bar::Bar::•<dynamic>()};
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as foo;
+import "dart:core" as core;
+import "bar_lib.dart" as bar;
+additionalExports = (bar::Bar)
+
+import "org-dartlang-testcase:///bar_lib.dart";
+export "org-dartlang-testcase:///bar_lib.dart";
+
+abstract class Foo extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[foo::Foo::bar]/*isLegacy*/;
+  const constructor •() → foo::Foo
+    : super core::Object::•()
+    ;
+  static factory bar() → foo::Foo
+    let dynamic #redirecting_factory = bar::Bar::• in let dynamic #typeArg0 = null in invalid-expression;
+}
+
+library /*isNonNullableByDefault*/;
+import self as bar;
+import "dart:core" as core;
+import "foo_lib.dart" as foo;
+
+import "org-dartlang-testcase:///foo_lib.dart";
+
+class Bar<T extends core::Object? = dynamic> extends foo::Foo /*hasConstConstructor*/  {
+  const constructor •() → bar::Bar<bar::Bar::T%>
+    : super foo::Foo::•()
+    ;
+}
+
+
+Extra constant evaluation status:
+Evaluated: SetLiteral @ org-dartlang-testcase:///main.dart:7:27 -> InstanceConstant(const _UnmodifiableSet<Foo*>{_UnmodifiableSet._map: const _ImmutableMap<Foo*, Null>{_ImmutableMap._kvPairs: const <dynamic>[const Bar<dynamic>{}, null]}})
+Extra constant evaluation: evaluated: 6, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/issue45003/main.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue45003/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..c2de772
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003/main.dart.weak.transformed.expect
@@ -0,0 +1,59 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "foo_lib.dart" as foo;
+
+import "org-dartlang-testcase:///foo_lib.dart";
+
+static const field core::Set<foo::Foo> foo = #C5;
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as foo;
+import "dart:core" as core;
+import "bar_lib.dart" as bar;
+additionalExports = (bar::Bar)
+
+import "org-dartlang-testcase:///bar_lib.dart";
+export "org-dartlang-testcase:///bar_lib.dart";
+
+abstract class Foo extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[foo::Foo::bar]/*isLegacy*/;
+  const constructor •() → foo::Foo
+    : super core::Object::•()
+    ;
+  static factory bar() → foo::Foo
+    let<BottomType> #redirecting_factory = bar::Bar::• in let<BottomType> #typeArg0 = null in invalid-expression;
+}
+
+library /*isNonNullableByDefault*/;
+import self as bar;
+import "dart:core" as core;
+import "foo_lib.dart" as foo;
+
+import "org-dartlang-testcase:///foo_lib.dart";
+
+class Bar<T extends core::Object? = dynamic> extends foo::Foo /*hasConstConstructor*/  {
+  const constructor •() → bar::Bar<bar::Bar::T%>
+    : super foo::Foo::•()
+    ;
+}
+
+constants  {
+  #C1 = bar::Bar<dynamic> {}
+  #C2 = null
+  #C3 = <dynamic>[#C1, #C2]
+  #C4 = core::_ImmutableMap<foo::Foo*, Null> {_kvPairs:#C3}
+  #C5 = col::_UnmodifiableSet<foo::Foo*> {_map:#C4}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///main.dart:
+- Bar. (from org-dartlang-testcase:///bar_lib.dart:8:9)
+
+org-dartlang-testcase:///foo_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+
+org-dartlang-testcase:///bar_lib.dart:
+- Foo. (from org-dartlang-testcase:///foo_lib.dart:10:9)
diff --git a/pkg/front_end/testcases/general/issue45003_2.dart b/pkg/front_end/testcases/general/issue45003_2.dart
new file mode 100644
index 0000000..d93da65
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003_2.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class C {
+  const C({dynamic x = const A.foo()});
+}
+
+class B<X> extends A {
+  const B();
+}
+
+abstract class A {
+  const A();
+  const factory A.foo() = B;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue45003_2.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue45003_2.dart.textual_outline.expect
new file mode 100644
index 0000000..6ceb0af
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003_2.dart.textual_outline.expect
@@ -0,0 +1,14 @@
+class C {
+  const C({dynamic x = const A.foo()});
+}
+
+class B<X> extends A {
+  const B();
+}
+
+abstract class A {
+  const A();
+  const factory A.foo() = B;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue45003_2.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue45003_2.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2a57c83
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003_2.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+abstract class A {
+  const A();
+  const factory A.foo() = B;
+}
+
+class B<X> extends A {
+  const B();
+}
+
+class C {
+  const C({dynamic x = const A.foo()});
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue45003_2.dart.weak.expect b/pkg/front_end/testcases/general/issue45003_2.dart.weak.expect
new file mode 100644
index 0000000..05d8566
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003_2.dart.weak.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = #C1}) → self::C
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object? = dynamic> extends self::A /*hasConstConstructor*/  {
+  const constructor •() → self::B<self::B::X%>
+    : super self::A::•()
+    ;
+}
+abstract class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[self::A::foo]/*isLegacy*/;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory foo() → self::A
+    let dynamic #redirecting_factory = self::B::• in let dynamic #typeArg0 = null in invalid-expression;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = self::B<dynamic> {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue45003_2.dart:
+- B. (from org-dartlang-testcase:///issue45003_2.dart:10:9)
+- A. (from org-dartlang-testcase:///issue45003_2.dart:14:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/issue45003_2.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue45003_2.dart.weak.outline.expect
new file mode 100644
index 0000000..25cabc79
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003_2.dart.weak.outline.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = const self::B::•<dynamic>()}) → self::C
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object? = dynamic> extends self::A /*hasConstConstructor*/  {
+  const constructor •() → self::B<self::B::X%>
+    : super self::A::•()
+    ;
+}
+abstract class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[self::A::foo]/*isLegacy*/;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory foo() → self::A
+    let dynamic #redirecting_factory = self::B::• in let dynamic #typeArg0 = null in invalid-expression;
+}
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue45003_2.dart:6:30 -> InstanceConstant(const B<dynamic>{})
+Extra constant evaluation: evaluated: 6, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/issue45003_2.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue45003_2.dart.weak.transformed.expect
new file mode 100644
index 0000000..6b11962
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45003_2.dart.weak.transformed.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = #C1}) → self::C
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object? = dynamic> extends self::A /*hasConstConstructor*/  {
+  const constructor •() → self::B<self::B::X%>
+    : super self::A::•()
+    ;
+}
+abstract class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[self::A::foo]/*isLegacy*/;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory foo() → self::A
+    let<BottomType> #redirecting_factory = self::B::• in let<BottomType> #typeArg0 = null in invalid-expression;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = self::B<dynamic> {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue45003_2.dart:
+- B. (from org-dartlang-testcase:///issue45003_2.dart:10:9)
+- A. (from org-dartlang-testcase:///issue45003_2.dart:14:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index a2daadf..586d009 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -10,6 +10,7 @@
     show
         templateFfiEmptyStruct,
         templateFfiFieldAnnotation,
+        templateFfiFieldNull,
         templateFfiFieldCyclic,
         templateFfiFieldNoAnnotation,
         templateFfiTypeMismatch,
@@ -227,6 +228,14 @@
     if (type is InvalidType) {
       return false;
     }
+    if (type is NullType) {
+      return false;
+    }
+    if (type is InterfaceType) {
+      if (type.classNode == structClass) {
+        return false;
+      }
+    }
     return env.isSubtypeOf(type, InterfaceType(structClass, Nullability.legacy),
         SubtypeCheckMode.ignoringNullabilities);
   }
@@ -279,7 +288,15 @@
       }
       final nativeTypeAnnos = _getNativeTypeAnnotations(f).toList();
       final type = _structFieldMemberType(f);
-      if (_isPointerType(type) || _isStructSubtype(type)) {
+      if (type is NullType) {
+        diagnosticReporter.report(
+            templateFfiFieldNull.withArguments(f.name.text),
+            f.fileOffset,
+            f.name.text.length,
+            f.fileUri);
+        // This class is invalid, but continue reporting other errors on it.
+        success = false;
+      } else if (_isPointerType(type) || _isStructSubtype(type)) {
         if (nativeTypeAnnos.length != 0) {
           diagnosticReporter.report(
               templateFfiFieldNoAnnotation.withArguments(f.name.text),
diff --git a/runtime/vm/experimental_features.cc b/runtime/vm/experimental_features.cc
index 12b02ef..e341195 100644
--- a/runtime/vm/experimental_features.cc
+++ b/runtime/vm/experimental_features.cc
@@ -18,7 +18,7 @@
 
 bool GetExperimentalFeatureDefault(ExperimentalFeature feature) {
   constexpr bool kFeatureValues[] = {
-      true, true, true, true, true, true, true,
+      true, true, true, true, true, true,
   };
   ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureValues));
   return kFeatureValues[static_cast<int>(feature)];
@@ -26,10 +26,9 @@
 
 const char* GetExperimentalFeatureName(ExperimentalFeature feature) {
   constexpr const char* kFeatureNames[] = {
-      "extension-types",          "non-nullable",
-      "extension-methods",        "constant-update-2018",
-      "control-flow-collections", "set-literals",
-      "spread-collections",
+      "non-nullable",         "extension-methods",
+      "constant-update-2018", "control-flow-collections",
+      "set-literals",         "spread-collections",
   };
   ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureNames));
   return kFeatureNames[static_cast<int>(feature)];
diff --git a/runtime/vm/experimental_features.h b/runtime/vm/experimental_features.h
index 6418be6..8efd29e 100644
--- a/runtime/vm/experimental_features.h
+++ b/runtime/vm/experimental_features.h
@@ -14,7 +14,6 @@
 namespace dart {
 
 enum class ExperimentalFeature {
-  extension_types,
   non_nullable,
   extension_methods,
   constant_update_2018,
diff --git a/tests/ffi/regress_44985_test.dart b/tests/ffi/regress_44985_test.dart
new file mode 100644
index 0000000..6ef8da6
--- /dev/null
+++ b/tests/ffi/regress_44985_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:ffi";
+
+class S2 extends Struct {
+  external Pointer<Int8> notEmpty;
+
+  external Struct? s; //# 01: compile-time error
+}
+
+void main() {
+  S2? s2;
+}
diff --git a/tests/ffi/regress_44986_test.dart b/tests/ffi/regress_44986_test.dart
new file mode 100644
index 0000000..2736deb
--- /dev/null
+++ b/tests/ffi/regress_44986_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:ffi";
+
+class S2 extends Struct {
+  external Pointer<Int8> notEmpty;
+
+  external Null s; //# 01: compile-time error
+}
+
+void main() {
+  S2? s2;
+}
diff --git a/tests/ffi_2/regress_44985_test.dart b/tests/ffi_2/regress_44985_test.dart
new file mode 100644
index 0000000..b63931f
--- /dev/null
+++ b/tests/ffi_2/regress_44985_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:ffi";
+
+class S2 extends Struct {
+  Pointer<Int8> notEmpty;
+
+  Struct s; //# 01: compile-time error
+}
+
+void main() {
+  S2 s2;
+}
diff --git a/tests/ffi_2/regress_44986_test.dart b/tests/ffi_2/regress_44986_test.dart
new file mode 100644
index 0000000..7395880
--- /dev/null
+++ b/tests/ffi_2/regress_44986_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:ffi";
+
+class S2 extends Struct {
+  Pointer<Int8> notEmpty;
+
+  Null s; //# 01: compile-time error
+}
+
+void main() {
+  S2 s2;
+}
diff --git a/tests/language/generic/generic_function_type_argument_test.dart b/tests/language/generic/generic_function_type_argument_test.dart
new file mode 100644
index 0000000..c51c674
--- /dev/null
+++ b/tests/language/generic/generic_function_type_argument_test.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=generic-metadata
+
+import "package:expect/expect.dart";
+import "../static_type_helper.dart";
+
+// Check that generic function types can be used as type arguments.
+
+typedef F = T Function<T>(T);
+
+class C<T> {
+  final T value;
+  const C(this.value);
+}
+
+T f<T>(T value) => value;
+
+extension E<T> on T {
+  T get extensionValue => this;
+}
+
+// A generic function type can be a type parameter bound.
+
+// For a type alias:
+typedef FB<T extends F> = S Function<S extends T>(S);
+
+// For a class:
+class CB<T extends F> {
+  final T function;
+  const CB(this.function);
+}
+
+// For a function:
+T fb<T extends F>(T value) => value;
+
+extension EB<T extends F> on T {
+  T get boundExtensionValue => this;
+
+  // Any function type has a `call` of its own type?
+  T get boundCall => this.call;
+}
+
+// Can be used as arguments to metadata too.
+@C<F>(f)
+@CB<FB<F>>(fb)
+void main() {
+  // Sanity checks.
+  Expect.type<F>(f);
+  Expect.type<FB<F>>(fb);
+
+  // A generic function type can be the argument to a generic class.
+  var list = [f]; // Inferred from content.
+  Expect.type<List<F>>(list);
+  list = []; // Inferred from context.
+  list.add(f);
+  list = <F>[]; // Explicit.
+  list.add(f);
+
+  // Also if the type has a bound.
+  var list2 = [fb];
+  Expect.type<List<FB<F>>>(list2);
+
+  // The instance is a subtype of its supertypes.
+  Expect.type<List<Function>>(list);
+  Expect.type<List<Object? Function<T>(Never)>>(list);
+  Expect.notType<List<Object? Function(Never)>>(list);
+
+  // A generic function type can be the argument to a generic function.
+  var g1 = f(f); // inferred from argument.
+  g1 = f(f); // Inferred from context.
+  g1 = f<F>(f); // Explicit.
+  g1.expectStaticType<Exactly<F>>();
+
+  // Extensions can match generic function types.
+  list.add(f.extensionValue);
+  list.add(E(f).extensionValue);
+  list.add(E<F>(f).extensionValue);
+  list.add(f.boundExtensionValue);
+  list.add(EB(f).boundExtensionValue);
+  list.add(EB<F>(f).boundExtensionValue);
+  list.add(f.boundCall);
+  list.add(EB(f).boundCall);
+  list.add(EB<F>(f).boundCall);
+  list2.add(fb.extensionValue);
+  list2.add(E(fb).extensionValue);
+  list2.add(E<FB<F>>(fb).extensionValue);
+}
diff --git a/tests/standalone/io/https_connection_closed_during_handshake_test.dart b/tests/standalone/io/https_connection_closed_during_handshake_test.dart
index eed79c2..ca22cb0 100644
--- a/tests/standalone/io/https_connection_closed_during_handshake_test.dart
+++ b/tests/standalone/io/https_connection_closed_during_handshake_test.dart
@@ -11,6 +11,7 @@
 import 'dart:convert';
 import 'dart:io';
 
+import "package:async_helper/async_helper.dart";
 import "package:expect/expect.dart";
 
 String getFilename(String path) => Platform.script.resolve(path).toFilePath();
@@ -45,6 +46,8 @@
     exit(1);
   }
 
+  asyncStart();
+
   final serverProcess = await Process.start(
       Platform.executable, [Platform.script.toFilePath(), 'server']);
   final serverPortCompleter = Completer<int>();
@@ -65,17 +68,20 @@
 
   int port = await serverPortCompleter.future;
 
-  var thrownException;
-  try {
-    print('client connecting...');
-    await SecureSocket.connect('localhost', port,
+  final errorCompleter = Completer();
+  await runZoned(() async {
+    var socket = await SecureSocket.connect('localhost', port,
         context: clientSecurityContext);
-    print('client connected.');
-  } catch (e) {
-    thrownException = e;
-  } finally {
-    await serverProcess.kill();
-  }
-  print('thrownException: $thrownException');
-  Expect.isTrue(thrownException is HandshakeException);
+    socket.write(<int>[1, 2, 3]);
+  }, onError: (e) async {
+    // Even if server disconnects during later parts of handshake, since
+    // TLS v1.3 client might not notice it until attempt to communicate with
+    // the server.
+    print('thrownException: $e');
+    errorCompleter.complete(e);
+  });
+  Expect.isTrue((await errorCompleter.future) is SocketException);
+  await serverProcess.kill();
+
+  asyncEnd();
 }
diff --git a/tests/standalone_2/io/https_connection_closed_during_handshake_test.dart b/tests/standalone_2/io/https_connection_closed_during_handshake_test.dart
index eed79c2..4ef2fef 100644
--- a/tests/standalone_2/io/https_connection_closed_during_handshake_test.dart
+++ b/tests/standalone_2/io/https_connection_closed_during_handshake_test.dart
@@ -11,6 +11,7 @@
 import 'dart:convert';
 import 'dart:io';
 
+import "package:async_helper/async_helper.dart";
 import "package:expect/expect.dart";
 
 String getFilename(String path) => Platform.script.resolve(path).toFilePath();
@@ -44,6 +45,7 @@
     print('server: exiting');
     exit(1);
   }
+  asyncStart();
 
   final serverProcess = await Process.start(
       Platform.executable, [Platform.script.toFilePath(), 'server']);
@@ -65,17 +67,20 @@
 
   int port = await serverPortCompleter.future;
 
-  var thrownException;
-  try {
-    print('client connecting...');
-    await SecureSocket.connect('localhost', port,
+  final errorCompleter = Completer();
+  await runZoned(() async {
+    var socket = await SecureSocket.connect('localhost', port,
         context: clientSecurityContext);
-    print('client connected.');
-  } catch (e) {
-    thrownException = e;
-  } finally {
-    await serverProcess.kill();
-  }
-  print('thrownException: $thrownException');
-  Expect.isTrue(thrownException is HandshakeException);
+    socket.write(<int>[1, 2, 3]);
+  }, onError: (e) async {
+    // Even if server disconnects during later parts of handshake, since
+    // TLS v1.3 client might not notice it until attempt to communicate with
+    // the server.
+    print('thrownException: $e');
+    errorCompleter.complete(e);
+  });
+  Expect.isTrue((await errorCompleter.future) is SocketException);
+  await serverProcess.kill();
+
+  asyncEnd();
 }
diff --git a/tools/VERSION b/tools/VERSION
index df8e394..c32fee5 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 55
+PRERELEASE 56
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml
index e97a0a3..8e83f80 100644
--- a/tools/experimental_features.yaml
+++ b/tools/experimental_features.yaml
@@ -119,15 +119,14 @@
   generic-metadata:
     help: "Allow annotations to accept type arguments; also allow generic function types as type arguments"
 
+  extension-types:
+    help: "Extension Types"
+
 #
 # Flags below this line are shipped, retired, or rejected, cannot be specified
 # on the command line, and will eventually be removed.
 #
 
-  extension-types:
-    help: "Extension Types"
-    enabledIn: '2.13.0'
-
   non-nullable:
     help: "Non Nullable by default"
     experimentalReleaseVersion: '2.10.0'