Version 2.10.0-70.0.dev

Merge commit '366a3f37c6a30532a30682c1b115ffb7ecd4564d' into 'dev'
diff --git a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
index 617a6f6..ad70fb7 100644
--- a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
+++ b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
@@ -92,7 +92,7 @@
   final LspAnalysisServer _server;
 
   /// Map from method name to current registration data.
-  Map<String, Registration> _currentRegistrations = {};
+  Map<String, Registration> currentRegistrations = {};
   var _lastRegistrationId = 0;
 
   ServerCapabilitiesComputer(this._server);
@@ -373,7 +373,7 @@
     // compute a diff of old and new registrations to send the unregister or
     // another register request. We assume that we'll only ever have one
     // registration per LSP method name.
-    for (final entry in _currentRegistrations.entries) {
+    for (final entry in currentRegistrations.entries) {
       final method = entry.key;
       final registration = entry.value;
 
@@ -393,7 +393,7 @@
       }
     }
 
-    _currentRegistrations = newRegistrationsByMethod;
+    currentRegistrations = newRegistrationsByMethod;
 
     if (removedRegistrations.isNotEmpty) {
       await _server.sendRequest(Method.client_unregisterCapability,
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index b99d5c2..d2680b1 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -984,7 +984,13 @@
     } else {
       prettyJson(server.capabilities.toJson());
     }
-    buf.writeln('</div>');
+    buf.writeln('</div>'); // half for server capabilities
+    buf.writeln('</div>'); // columns
+
+    h3('Current registrations');
+    p('Showing the LSP method name and the registration params sent to the '
+        'client.');
+    prettyJson(server.capabilitiesComputer.currentRegistrations);
   }
 }
 
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index f528230..2c91951 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -285,7 +285,10 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class AssignmentExpression
-    implements NullShortableExpression, MethodReferenceExpression {
+    implements
+        NullShortableExpression,
+        MethodReferenceExpression,
+        CompoundAssignmentExpression {
   /// Return the expression used to compute the left hand side.
   Expression get leftHandSide;
 
@@ -1274,6 +1277,65 @@
 /// Clients may not extend, implement or mix-in this class.
 abstract class CompilationUnitMember implements Declaration {}
 
+/// A potentially compound assignment.
+///
+/// A compound assignment is any node in which a single expression is used to
+/// specify both where to access a value to be operated on (the "read") and to
+/// specify where to store the result of the operation (the "write"). This
+/// happens in an [AssignmentExpression] when the assignment operator is a
+/// compound assignment operator, and in a [PrefixExpression] or
+/// [PostfixExpression] when the operator is an increment operator.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class CompoundAssignmentExpression {
+  /// The element that is used to read the value.
+  ///
+  /// If this node is not a compound assignment, this element is `null`.
+  ///
+  /// In valid code this element can be a [LocalVariableElement], a
+  /// [ParameterElement], or a [PropertyAccessorElement] getter.
+  ///
+  /// In invalid code this element is `null`, for example `int += 2`. For
+  /// recovery [writeElement] is filled, and can be used for navigation.
+  ///
+  /// This element is `null` if the AST structure has not been resolved, or
+  /// if the target could not be resolved.
+  Element get readElement;
+
+  /// The type of the value read with the [readElement].
+  ///
+  /// If this node is not a compound assignment, this type is `null`.
+  ///
+  /// In invalid code, e.g. `int += 2`, this type is `dynamic`.
+  ///
+  /// This type is `null` if the AST structure has not been resolved.
+  ///
+  /// If the target could not be resolved, this type is `dynamic`.
+  DartType get readType;
+
+  /// The element that is used to write the result.
+  ///
+  /// In valid code this is a [LocalVariableElement], [ParameterElement], or a
+  /// [PropertyAccessorElement] setter.
+  ///
+  /// In invalid code, for recovery, we might use other elements, for example a
+  /// [PropertyAccessorElement] getter `myGetter = 0` even though the getter
+  /// cannot be used to write a value. We do this to help the user to navigate
+  /// to the getter, and maybe add the corresponding setter.
+  ///
+  /// If this node is a compound assignment, e. g. `x += 2`, both [readElement]
+  /// and [writeElement] could be not `null`.
+  ///
+  /// This element is `null` if the AST structure has not been resolved, or
+  /// if the target could not be resolved.
+  Element get writeElement;
+
+  /// The types of assigned values must be subtypes of this type.
+  ///
+  /// If the target could not be resolved, this type is `dynamic`.
+  DartType get writeType;
+}
+
 /// A conditional expression.
 ///
 ///    conditionalExpression ::=
@@ -4192,7 +4254,11 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class PostfixExpression
-    implements Expression, NullShortableExpression, MethodReferenceExpression {
+    implements
+        Expression,
+        NullShortableExpression,
+        MethodReferenceExpression,
+        CompoundAssignmentExpression {
   /// Return the expression computing the operand for the operator.
   Expression get operand;
 
@@ -4252,7 +4318,11 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class PrefixExpression
-    implements Expression, NullShortableExpression, MethodReferenceExpression {
+    implements
+        Expression,
+        NullShortableExpression,
+        MethodReferenceExpression,
+        CompoundAssignmentExpression {
   /// Return the expression computing the operand for the operator.
   Expression get operand;
 
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 5fdf7bf..f58b06e 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -16,6 +16,7 @@
 import 'package:analyzer/src/dart/ast/to_source_visitor.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/fasta/token_utils.dart' as util show findPrevious;
 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
 import 'package:analyzer/src/generated/engine.dart';
@@ -612,7 +613,7 @@
 ///    assignmentExpression ::=
 ///        [Expression] operator [Expression]
 class AssignmentExpressionImpl extends ExpressionImpl
-    with NullShortableExpressionImpl
+    with NullShortableExpressionImpl, CompoundAssignmentExpressionImpl
     implements AssignmentExpression {
   /// The expression used to compute the left hand side.
   ExpressionImpl _leftHandSide;
@@ -2155,6 +2156,20 @@
       : super(comment, metadata);
 }
 
+mixin CompoundAssignmentExpressionImpl implements CompoundAssignmentExpression {
+  @override
+  Element readElement;
+
+  @override
+  Element writeElement;
+
+  @override
+  DartType readType;
+
+  @override
+  DartType writeType = DynamicTypeImpl.instance;
+}
+
 /// A conditional expression.
 ///
 ///    conditionalExpression ::=
@@ -8010,7 +8025,7 @@
 ///    postfixExpression ::=
 ///        [Expression] [Token]
 class PostfixExpressionImpl extends ExpressionImpl
-    with NullShortableExpressionImpl
+    with NullShortableExpressionImpl, CompoundAssignmentExpressionImpl
     implements PostfixExpression {
   /// The expression computing the operand for the operator.
   ExpressionImpl _operand;
@@ -8180,7 +8195,7 @@
 ///    prefixExpression ::=
 ///        [Token] [Expression]
 class PrefixExpressionImpl extends ExpressionImpl
-    with NullShortableExpressionImpl
+    with NullShortableExpressionImpl, CompoundAssignmentExpressionImpl
     implements PrefixExpression {
   /// The prefix operator being applied to the operand.
   @override
@@ -8849,38 +8864,6 @@
   @override
   Precedence get precedence => Precedence.primary;
 
-  /// If this identifier is used as an expression to read a value, this
-  /// is the element that provides the value.
-  ///
-  /// In valid code this can be almost any element, usually a
-  /// [LocalVariableElement], a [ParameterElement], or a
-  /// [PropertyAccessorElement] getter.
-  ///
-  /// In invalid code, for recovery, we might use a [PropertyAccessorElement]
-  /// setter `print(mySetter)` even though the setter cannot be used to read a
-  /// value. We do this to help the user to navigate to the setter, and maybe
-  /// add the corresponding getter.
-  ///
-  /// Return `null` if this identifier is not used to read a value, or the
-  /// AST structure has not been resolved, or if this identifier could not be
-  /// resolved.
-  ///
-  /// If this identifier is used as the target for a compound assignment
-  /// `x += 2`, both [readElement] and [writeElement] could be not `null`.
-  ///
-  /// If [referenceElement] is not `null`, then both [readElement] and
-  /// [writeElement] are `null`, because the identifier is not being used to
-  /// read or write a value.
-  ///
-  /// If either [readElement] or [writeElement] are not `null`, the
-  /// [referenceElement] is `null`, because the identifier is being used to
-  /// read or write a value.
-  ///
-  /// All three [readElement], [writeElement], and [referenceElement] can be
-  /// `null` when the AST structure has not been resolved, or this identifier
-  /// could not be resolved.
-  Element get readElement => null;
-
   /// This element is set when this identifier is used not as an expression,
   /// but just to reference some element.
   ///
@@ -8916,39 +8899,6 @@
     _staticElement = element;
   }
 
-  /// If this identifier is used as a target to assign a value, explicitly
-  /// using an [AssignmentExpression], or implicitly using a [PrefixExpression]
-  /// or [PostfixExpression], this is the element that is used to write the
-  /// value.
-  ///
-  /// In valid code this is a [LocalVariableElement], [ParameterElement], or a
-  /// [PropertyAccessorElement] setter.
-  ///
-  /// In invalid code, for recovery, we might use other elements, for example a
-  /// [PropertyAccessorElement] getter `myGetter = 0` even though the getter
-  /// cannot be used to write a value. We do this to help the user to navigate
-  /// to the getter, and maybe add the corresponding setter.
-  ///
-  /// Return `null` if this identifier is not used to write a value, or the
-  /// AST structure has not been resolved, or if this identifier could not be
-  /// resolved.
-  ///
-  /// If this identifier is used as the target for a compound assignment
-  /// `x += 2`, both [readElement] and [writeElement] could be not `null`.
-  ///
-  /// If [referenceElement] is not `null`, then both [readElement] and
-  /// [writeElement] are `null`, because the identifier is not being used to
-  /// read or write a value.
-  ///
-  /// If either [readElement] or [writeElement] are not `null`, the
-  /// [referenceElement] is `null`, because the identifier is being used to
-  /// read or write a value.
-  ///
-  /// All three [readElement], [writeElement], and [referenceElement] can be
-  /// `null` when the AST structure has not been resolved, or this identifier
-  /// could not be resolved.
-  Element get writeElement => null;
-
   @override
   E accept<E>(AstVisitor<E> visitor) => visitor.visitSimpleIdentifier(this);
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
index 1de4308..3711c65 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -77,8 +77,18 @@
     left?.accept(_resolver);
     left = node.leftHandSide;
 
-    _resolve1(node);
     TokenType operator = node.operator.type;
+    if (left is! IndexExpression &&
+        left is! PrefixedIdentifier &&
+        left is! PropertyAccess &&
+        left is! SimpleIdentifier) {
+      if (operator != TokenType.EQ) {
+        _resolver.setReadElement(left, null);
+      }
+      _resolver.setWriteElement(left, null);
+    }
+
+    _resolve1(node);
     _setRhsContext(node, left.staticType, operator, right);
 
     _flowAnalysis?.assignmentExpression(node);
@@ -282,13 +292,18 @@
     VariableElement leftElement,
     Expression right,
   ) {
+    var operator = node.operator.type;
+
     left.staticElement = leftElement;
+    if (operator != TokenType.EQ) {
+      _resolver.setReadElement(left, leftElement);
+    }
+    _resolver.setWriteElement(left, leftElement);
 
     var leftType = _resolver.localVariableTypeProvider.getType(left);
     // TODO(scheglov) Set the type only when `operator != TokenType.EQ`.
     _recordStaticType(left, leftType);
 
-    var operator = node.operator.type;
     if (operator != TokenType.EQ) {
       _resolver.checkReadOfNotAssignedLocalVariable(left);
     }
diff --git a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
index b934ae0..6942809 100644
--- a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
@@ -40,6 +40,15 @@
   }
 
   @override
+  void visitAssignmentExpression(AssignmentExpression node) {
+    _assertLegacyElement(node.readElement);
+    _assertLegacyElement(node.writeElement);
+    _assertLegacyType(node.readType);
+    _assertLegacyType(node.writeType);
+    super.visitAssignmentExpression(node);
+  }
+
+  @override
   void visitClassMember(ClassMember node) {
     final element = node.declaredElement;
     if (element is ExecutableElement) {
@@ -105,6 +114,14 @@
     super.visitVariableDeclaration(node);
   }
 
+  void _assertLegacyElement(Element element) {
+    if (element is ExecutableElement) {
+      _assertLegacyType(element.type);
+    } else if (element is VariableElement) {
+      _assertLegacyType(element.type);
+    }
+  }
+
   void _assertLegacyType(DartType type) {
     if (type == null) {
       return;
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index 993020d..a0725e4 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -372,8 +372,10 @@
 
     if (node.isCascaded) {
       // Report this error and recover by treating it like a non-cascade.
-      _resolver.errorReporter.reportErrorForToken(
-          CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, node.operator);
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE,
+        override.extensionName,
+      );
     }
 
     nameNode.staticElement = member;
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 82bacc5..8b3ae89 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -432,10 +432,14 @@
     if (isInGetterContext && isInSetterContext) {
       node.staticElement = result.setter;
       node.auxiliaryElements = AuxiliaryElements(result.getter);
+      _resolver.setReadElement(node, result.getter);
+      _resolver.setWriteElement(node, result.setter);
     } else if (isInGetterContext) {
       node.staticElement = result.getter;
+      _resolver.setReadElement(node, result.getter);
     } else if (isInSetterContext) {
       node.staticElement = result.setter;
+      _resolver.setWriteElement(node, result.setter);
     }
 
     if (isInGetterContext) {
@@ -559,6 +563,7 @@
     // identifier and this is really equivalent to a property access node.
     //
     _resolvePropertyAccess(
+      node,
       prefix,
       identifier,
       isCascaded: false,
@@ -573,11 +578,12 @@
         SuperContext.of(target) != SuperContext.valid) {
       return;
     } else if (target is ExtensionOverride) {
-      if (node.isCascaded) {
+      if (target.parent is CascadeExpression) {
         // Report this error and recover by treating it like a non-cascade.
-        _errorReporter.reportErrorForToken(
-            CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE,
-            node.operator);
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE,
+          target.extensionName,
+        );
       }
       ExtensionElement element = target.extensionName.staticElement;
       SimpleIdentifier propertyName = node.propertyName;
@@ -585,6 +591,7 @@
       ExecutableElement member;
       var result = _extensionResolver.getOverrideMember(target, memberName);
       if (propertyName.inSetterContext()) {
+        _resolver.setWriteElement(node, result.setter);
         member = result.setter;
         if (member == null) {
           _errorReporter.reportErrorForNode(
@@ -593,6 +600,7 @@
               [memberName, element.name]);
         }
         if (propertyName.inGetterContext()) {
+          _resolver.setReadElement(node, result.getter);
           ExecutableElement getter = result.getter;
           if (getter == null) {
             _errorReporter.reportErrorForNode(
@@ -603,6 +611,7 @@
           propertyName.auxiliaryElements = AuxiliaryElements(getter);
         }
       } else if (propertyName.inGetterContext()) {
+        _resolver.setReadElement(node, result.getter);
         member = result.getter;
         if (member == null) {
           _errorReporter.reportErrorForNode(
@@ -622,6 +631,7 @@
     }
     SimpleIdentifier propertyName = node.propertyName;
     _resolvePropertyAccess(
+      node,
       target,
       propertyName,
       isCascaded: node.isCascaded,
@@ -734,8 +744,21 @@
       }
     }
     node.staticElement = element;
+
+    _resolver.setWriteElement(node, element);
+
+    var inGetterContext = node.inGetterContext();
+    if (inGetterContext) {
+      if (element is PropertyAccessorElement &&
+          element.enclosingElement is CompilationUnitElement) {
+        _resolver.setReadElement(node, element.variable.getter);
+      } else {
+        _resolver.setReadElement(node, null);
+      }
+    }
+
     if (node.inSetterContext() &&
-        node.inGetterContext() &&
+        inGetterContext &&
         enclosingClass != null) {
       InterfaceType enclosingType = enclosingClass.thisType;
       var result = _typePropertyResolver.resolve(
@@ -748,6 +771,7 @@
       node.auxiliaryElements = AuxiliaryElements(
         result.getter,
       );
+      _resolver.setReadElement(node, result.getter);
     }
     //
     // Validate annotation element.
@@ -1243,6 +1267,7 @@
   }
 
   void _resolvePropertyAccess(
+    Expression node,
     Expression target,
     SimpleIdentifier propertyName, {
     @required bool isCascaded,
@@ -1323,8 +1348,10 @@
           }
         }
 
+        element = _resolver.toLegacyElement(element);
+        _resolver.setReadElement(node, element);
+
         if (element != null) {
-          element = _resolver.toLegacyElement(element);
           propertyName.staticElement = element;
           _checkForStaticAccessToInstanceMember(propertyName, element);
         } else {
@@ -1343,6 +1370,10 @@
         ExecutableElement element;
 
         var setter = typeReference.getSetter(propertyName.name);
+        setter = _resolver.toLegacyElement(setter);
+
+        _resolver.setWriteElement(node, setter);
+
         if (setter != null) {
           element = setter;
           if (!setter.isAccessibleIn(_definingLibrary)) {
@@ -1355,7 +1386,6 @@
         }
 
         if (element != null) {
-          element = _resolver.toLegacyElement(element);
           propertyName.staticElement = element;
           _checkForStaticAccessToInstanceMember(propertyName, element);
         } else {
@@ -1382,6 +1412,7 @@
           var name = Name(_definingLibrary.source.uri, propertyName.name);
           var element = _resolver.inheritance
               .getMember2(staticType.element, name, forSuper: true);
+          _resolver.setReadElement(node, element);
 
           if (element != null) {
             element = _resolver.toLegacyElement(element);
@@ -1416,6 +1447,7 @@
             concrete: true,
             inherited: true,
           );
+          _resolver.setWriteElement(node, element);
 
           if (element != null) {
             element = _resolver.toLegacyElement(element);
@@ -1479,6 +1511,7 @@
     );
 
     if (propertyName.inGetterContext()) {
+      _resolver.setReadElement(node, result.getter);
       var shouldReportUndefinedGetter = false;
       if (result.isSingle) {
         var getter = result.getter;
@@ -1511,6 +1544,7 @@
     }
 
     if (propertyName.inSetterContext()) {
+      _resolver.setWriteElement(node, result.setter);
       if (result.isSingle) {
         var setter = result.setter;
         if (setter != null) {
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 0a9d266..c37e6c6 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -1685,6 +1685,7 @@
       _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, expression);
     } else if (element is ClassElement ||
+        element is DynamicElementImpl ||
         element is FunctionTypeAliasElement ||
         element is TypeParameterElement) {
       _errorReporter.reportErrorForNode(
@@ -2955,10 +2956,16 @@
       return;
     }
 
-    VariableElement leftVariableElement = getVariableElement(lhs);
-    DartType leftType = (leftVariableElement == null)
-        ? getStaticType(lhs)
-        : leftVariableElement.type;
+    DartType leftType;
+    var parent = lhs.parent;
+    if (parent is AssignmentExpression && parent.leftHandSide == lhs) {
+      leftType = parent.writeType;
+    } else {
+      VariableElement leftVariableElement = getVariableElement(lhs);
+      leftType = (leftVariableElement == null)
+          ? getStaticType(lhs)
+          : leftVariableElement.type;
+    }
 
     if (!leftType.isVoid && _checkForUseOfVoidResult(rhs)) {
       return;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index ab23325..6038680 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -21,6 +21,7 @@
     show ConstructorMember, Member;
 import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
 import 'package:analyzer/src/dart/element/scope.dart';
+import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
@@ -571,11 +572,67 @@
     }
   }
 
+  void setReadElement(Expression node, Element element) {
+    var parent = node.parent;
+    if (parent is AssignmentExpressionImpl && parent.leftHandSide == node) {
+      parent.readElement = element;
+
+      DartType readType = DynamicTypeImpl.instance;
+      if (node is IndexExpression) {
+        if (element is MethodElement) {
+          readType = element.returnType;
+        }
+      } else if (node is PrefixedIdentifier ||
+          node is PropertyAccess ||
+          node is SimpleIdentifier) {
+        if (element is PropertyAccessorElement && element.isGetter) {
+          readType = element.returnType;
+        } else if (element is VariableElement) {
+          readType = localVariableTypeProvider.getType(node);
+        }
+      }
+      parent.readType = readType;
+    }
+  }
+
   @visibleForTesting
   void setThisInterfaceType(InterfaceType thisType) {
     _thisType = thisType;
   }
 
+  void setWriteElement(Expression node, Element element) {
+    var parent = node.parent;
+    if (parent is AssignmentExpressionImpl && parent.leftHandSide == node) {
+      parent.writeElement = element;
+
+      DartType writeType = DynamicTypeImpl.instance;
+      if (node is IndexExpression) {
+        if (element is MethodElement) {
+          var parameters = element.parameters;
+          if (parameters.length == 2) {
+            writeType = parameters[1].type;
+          }
+        }
+      } else if (node is PrefixedIdentifier ||
+          node is PropertyAccess ||
+          node is SimpleIdentifier) {
+        if (element is PropertyAccessorElement && element.isSetter) {
+          if (element.isSynthetic) {
+            writeType = element.variable.type;
+          } else {
+            var parameters = element.parameters;
+            if (parameters.length == 1) {
+              writeType = parameters[0].type;
+            }
+          }
+        } else if (element is VariableElement) {
+          writeType = element.type;
+        }
+      }
+      parent.writeType = writeType;
+    }
+  }
+
   /// If in a legacy library, return the legacy view on the [element].
   /// Otherwise, return the original element.
   T toLegacyElement<T extends Element>(T element) {
diff --git a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
index 98c2d91..7aed8b1 100644
--- a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
@@ -204,26 +204,75 @@
     assertType(indexed, 'double');
   }
 
-  test_notLValue_parenthesized() async {
-    await resolveTestCode(r'''
-int a, b;
-double c = 0.0;
-main() {
-  (a + b) = c;
+  test_notLValue_parenthesized_compound() async {
+    await assertErrorsInCode(r'''
+void f(int a, int b, double c) {
+  (a + b) += c;
 }
-''');
-    expect(result.errors, isNotEmpty);
-
-    var parenthesized = findNode.parenthesized('(a + b)');
-    assertType(parenthesized, 'int');
-
-    assertTopGetRef('a + b', 'a');
-    assertTopGetRef('b)', 'b');
-    assertTopGetRef('c;', 'c');
+''', [
+      error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 35, 7),
+      error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 35, 7),
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 46, 1),
+    ]);
 
     var assignment = findNode.assignment('= c');
-    assertElementNull(assignment);
-    assertType(assignment, 'double');
+    assertAssignment(
+      assignment,
+      readElement: null,
+      readType: 'dynamic',
+      writeElement: null,
+      writeType: 'dynamic',
+      operatorElement: elementMatcher(
+        numElement.getMethod('+'),
+        isLegacy: isNullSafetySdkAndLegacyLibrary,
+      ),
+      type: 'double',
+    );
+  }
+
+  test_notLValue_parenthesized_simple() async {
+    await assertErrorsInCode(r'''
+void f(int a, int b, double c) {
+  (a + b) = c;
+}
+''', [
+      error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 35, 7),
+      error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 35, 7),
+    ]);
+
+    var assignment = findNode.assignment('= c');
+    assertAssignment(
+      assignment,
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: 'dynamic',
+      operatorElement: null,
+      type: 'double',
+    );
+
+    assertType(assignment.leftHandSide, 'int');
+
+    assertSimpleIdentifier(
+      findNode.simple('a + b'),
+      readElement: findElement.parameter('a'),
+      writeElement: null,
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      findNode.simple('b)'),
+      readElement: findElement.parameter('b'),
+      writeElement: null,
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      findNode.simple('c;'),
+      readElement: findElement.parameter('c'),
+      writeElement: null,
+      type: 'double',
+    );
   }
 
   test_nullAware_context() async {
@@ -458,12 +507,15 @@
 }
 ''', [
       error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 25, 1),
-      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 29, 1),
     ]);
 
     var assignment = findNode.assignment('C = 0');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.class_('C'),
+      writeType: 'dynamic',
       operatorElement: null,
       type: 'int',
     );
@@ -492,6 +544,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.setter('x'),
+      writeType: 'num',
       operatorElement: null,
       type: 'int',
     );
@@ -520,6 +576,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.setter('x'),
+      writeType: 'num',
       operatorElement: null,
       type: 'int',
     );
@@ -550,6 +610,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.getter('x'),
+      writeType: 'dynamic',
       operatorElement: null,
       type: 'int',
     );
@@ -580,6 +644,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.getter('x'),
+      writeType: 'dynamic',
       operatorElement: null,
       type: 'int',
     );
@@ -608,6 +676,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.topGet('x'),
+      writeType: 'dynamic',
       operatorElement: null,
       type: 'int',
     );
@@ -636,6 +708,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.prefix('x'),
+      writeType: 'dynamic',
       operatorElement: null,
       type: 'int',
     );
@@ -662,6 +738,10 @@
     var assignment = findNode.assignment('x += 3');
     assertAssignment(
       assignment,
+      readElement: findElement.localVar('x'),
+      readType: 'num',
+      writeElement: findElement.localVar('x'),
+      writeType: 'num',
       operatorElement: elementMatcher(
         numElement.getMethod('+'),
         isLegacy: isNullSafetySdkAndLegacyLibrary,
@@ -691,6 +771,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.localVar('x'),
+      writeType: 'num',
       operatorElement: null,
       type: 'int',
     );
@@ -719,6 +803,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.localVar('x'),
+      writeType: 'num',
       operatorElement: null,
       type: 'int',
     );
@@ -747,6 +835,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.localVar('x'),
+      writeType: 'num',
       operatorElement: null,
       type: 'int',
     );
@@ -772,6 +864,10 @@
     var assignment = findNode.assignment('x ??=');
     assertAssignment(
       assignment,
+      readElement: findElement.parameter('x'),
+      readType: 'num$question',
+      writeElement: findElement.parameter('x'),
+      writeType: 'num$question',
       operatorElement: null,
       type: 'num',
     );
@@ -800,6 +896,10 @@
     var assignment = findNode.assignment('a ??=');
     assertAssignment(
       assignment,
+      readElement: findElement.parameter('a'),
+      readType: 'double$question',
+      writeElement: findElement.parameter('a'),
+      writeType: 'double$question',
       operatorElement: null,
       type: 'num',
     );
@@ -866,6 +966,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.parameter('x'),
+      writeType: 'num',
       operatorElement: null,
       type: 'int',
     );
@@ -892,6 +996,10 @@
     var assignment = findNode.assignment('x = true');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.parameter('x'),
+      writeType: 'int',
       operatorElement: null,
       type: 'bool',
     );
@@ -918,6 +1026,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.parameter('x'),
+      writeType: 'int',
       operatorElement: null,
       type: 'int',
     );
@@ -944,6 +1056,10 @@
     var assignment = findNode.assignment('= y');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: 'dynamic',
       operatorElement: null,
       type: 'int',
     );
@@ -963,6 +1079,76 @@
     );
   }
 
+  test_simpleIdentifier_thisGetter_thisSetter_compound() 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: elementMatcher(
+        numElement.getMethod('+'),
+        isLegacy: isNullSafetySdkAndLegacyLibrary,
+      ),
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      assignment.leftHandSide,
+      readElement: findElement.getter('x'),
+      writeElement: findElement.setter('x'),
+      type: 'num',
+    );
+
+    assertType(assignment.rightHandSide, 'int');
+  }
+
+  test_simpleIdentifier_topGetter_topSetter_compound() async {
+    await assertNoErrorsInCode('''
+int get x => 0;
+set x(num _) {}
+
+void f() {
+  x += 2;
+}
+''');
+
+    var assignment = findNode.assignment('x += 2');
+    assertAssignment(
+      assignment,
+      readElement: findElement.topGet('x'),
+      readType: 'int',
+      writeElement: findElement.topSet('x'),
+      writeType: 'num',
+      operatorElement: elementMatcher(
+        numElement.getMethod('+'),
+        isLegacy: isNullSafetySdkAndLegacyLibrary,
+      ),
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      assignment.leftHandSide,
+      readElement: findElement.topGet('x'),
+      writeElement: findElement.topSet('x'),
+      type: 'num',
+    );
+
+    assertType(assignment.rightHandSide, 'int');
+  }
+
   test_simpleIdentifier_topLevelVariable_simple() async {
     await assertNoErrorsInCode(r'''
 num x = 0;
@@ -975,6 +1161,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.topSet('x'),
+      writeType: 'num',
       operatorElement: null,
       type: 'int',
     );
@@ -1003,6 +1193,10 @@
     var assignment = findNode.assignment('x = true');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.topSet('x'),
+      writeType: 'int',
       operatorElement: null,
       type: 'bool',
     );
@@ -1031,6 +1225,10 @@
     var assignment = findNode.assignment('x = 2');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.topGet('x'),
+      writeType: 'dynamic',
       operatorElement: null,
       type: 'int',
     );
@@ -1045,6 +1243,97 @@
     assertType(assignment.rightHandSide, 'int');
   }
 
+  test_simpleIdentifier_typeLiteral_compound() async {
+    await assertErrorsInCode(r'''
+void f() {
+  int += 3;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 13, 3),
+      error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 17, 2),
+    ]);
+
+    var assignment = findNode.assignment('int += 3');
+    assertAssignment(
+      assignment,
+      readElement: null,
+      readType: 'dynamic',
+      writeElement: intElement,
+      writeType: 'dynamic',
+      operatorElement: null,
+      type: 'dynamic',
+    );
+
+    assertSimpleIdentifier(
+      assignment.leftHandSide,
+      readElement: null,
+      writeElement: intElement,
+      type: 'Type',
+    );
+
+    assertType(assignment.rightHandSide, 'int');
+  }
+
+  test_simpleIdentifier_typeLiteral_simple() async {
+    await assertErrorsInCode(r'''
+void f() {
+  int = 0;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 13, 3),
+    ]);
+
+    var assignment = findNode.assignment('int = 0');
+    assertAssignment(
+      assignment,
+      readElement: null,
+      readType: null,
+      writeElement: intElement,
+      writeType: 'dynamic',
+      operatorElement: null,
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      assignment.leftHandSide,
+      readElement: null,
+      writeElement: intElement,
+      type: 'Type',
+    );
+
+    assertType(assignment.rightHandSide, 'int');
+  }
+
+  test_simpleIdentifier_unresolved_compound() async {
+    await assertErrorsInCode(r'''
+void f() {
+  x += 1;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 13, 1),
+    ]);
+
+    var assignment = findNode.assignment('x += 1');
+    assertAssignment(
+      assignment,
+      readElement: null,
+      readType: 'dynamic',
+      writeElement: null,
+      writeType: 'dynamic',
+      operatorElement: null,
+      type: 'dynamic',
+    );
+
+    assertSimpleIdentifier(
+      assignment.leftHandSide,
+      readElement: null,
+      writeElement: null,
+      type: 'dynamic',
+    );
+
+    assertType(assignment.rightHandSide, 'int');
+  }
+
   test_simpleIdentifier_unresolved_simple() async {
     await assertErrorsInCode(r'''
 void f(int a) {
@@ -1057,6 +1346,10 @@
     var assignment = findNode.assignment('x = a');
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: 'dynamic',
       operatorElement: null,
       type: 'int',
     );
diff --git a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
index 0ea4180..a297211 100644
--- a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
@@ -71,7 +71,7 @@
     );
   }
 
-  test_readWrite() async {
+  test_readWrite_assignment() async {
     await assertNoErrorsInCode(r'''
 class A {
   num operator[](int index) => 0;
@@ -102,6 +102,10 @@
     var assignment = indexExpression.parent as AssignmentExpression;
     assertAssignment(
       assignment,
+      readElement: indexElement,
+      readType: 'num',
+      writeElement: indexEqElement,
+      writeType: 'num',
       operatorElement: elementMatcher(
         numPlusElement,
         isLegacy: isNullSafetySdkAndLegacyLibrary,
@@ -114,7 +118,7 @@
     );
   }
 
-  test_readWrite_generic() async {
+  test_readWrite_assignment_generic() async {
     await assertNoErrorsInCode(r'''
 class A<T> {
   T operator[](int index) => throw 42;
@@ -151,6 +155,16 @@
     var assignment = indexExpression.parent as AssignmentExpression;
     assertAssignment(
       assignment,
+      readElement: elementMatcher(
+        indexElement,
+        substitution: {'T': 'double'},
+      ),
+      readType: 'double',
+      writeElement: elementMatcher(
+        indexEqElement,
+        substitution: {'T': 'double'},
+      ),
+      writeType: 'double',
       operatorElement: elementMatcher(
         doublePlusElement,
         isLegacy: isNullSafetySdkAndLegacyLibrary,
@@ -191,6 +205,10 @@
     var assignment = indexExpression.parent as AssignmentExpression;
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: indexEqElement,
+      writeType: 'num',
       operatorElement: null,
       type: 'double',
     );
@@ -228,6 +246,13 @@
     var assignment = indexExpression.parent as AssignmentExpression;
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: elementMatcher(
+        indexEqElement,
+        substitution: {'T': 'double'},
+      ),
+      writeType: 'double',
       operatorElement: null,
       type: 'double',
     );
@@ -321,6 +346,10 @@
     var assignment = indexExpression.parent as AssignmentExpression;
     assertAssignment(
       assignment,
+      readElement: indexElement,
+      readType: 'num',
+      writeElement: indexEqElement,
+      writeType: 'num',
       operatorElement: numPlusElement,
       type: 'double?',
     );
@@ -388,6 +417,10 @@
     var assignment = indexExpression.parent as AssignmentExpression;
     assertAssignment(
       assignment,
+      readElement: null,
+      readType: null,
+      writeElement: indexEqElement,
+      writeType: 'num',
       operatorElement: null,
       type: 'double?',
     );
diff --git a/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart b/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart
index 382928b..a6aa5f6 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart
@@ -2,6 +2,7 @@
 // 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:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -55,6 +56,130 @@
     );
     assertType(identifier, 'A');
   }
+
+  test_read() async {
+    await assertNoErrorsInCode('''
+class A {
+  int foo = 0;
+}
+
+void f(A a) {
+  a.foo;
+}
+''');
+
+    var prefixed = findNode.prefixed('a.foo');
+    assertPrefixedIdentifier(
+      prefixed,
+      element: findElement.getter('foo'),
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      prefixed.prefix,
+      readElement: findElement.parameter('a'),
+      writeElement: null,
+      type: 'A',
+    );
+
+    assertSimpleIdentifier(
+      prefixed.identifier,
+      readElement: findElement.getter('foo'),
+      writeElement: null,
+      type: 'int',
+    );
+  }
+
+  test_readWrite_assignment() async {
+    await assertNoErrorsInCode('''
+class A {
+  int foo = 0;
+}
+
+void f(A a) {
+  a.foo += 1;
+}
+''');
+
+    var assignment = findNode.assignment('foo += 1');
+    assertAssignment(
+      assignment,
+      readElement: findElement.getter('foo'),
+      readType: 'int',
+      writeElement: findElement.setter('foo'),
+      writeType: 'int',
+      operatorElement: elementMatcher(
+        numElement.getMethod('+'),
+        isLegacy: isNullSafetySdkAndLegacyLibrary,
+      ),
+      type: 'int',
+    );
+
+    var prefixed = assignment.leftHandSide as PrefixedIdentifier;
+    assertPrefixedIdentifier(
+      prefixed,
+      element: findElement.setter('foo'),
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      prefixed.prefix,
+      readElement: findElement.parameter('a'),
+      writeElement: null,
+      type: 'A',
+    );
+
+    assertSimpleIdentifier(
+      prefixed.identifier,
+      readElement: null,
+      writeElement: findElement.setter('foo'),
+      type: 'int',
+    );
+  }
+
+  test_write() async {
+    await assertNoErrorsInCode('''
+class A {
+  int foo = 0;
+}
+
+void f(A a) {
+  a.foo = 1;
+}
+''');
+
+    var assignment = findNode.assignment('foo = 1');
+    assertAssignment(
+      assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.setter('foo'),
+      writeType: 'int',
+      operatorElement: null,
+      type: 'int',
+    );
+
+    var prefixed = assignment.leftHandSide as PrefixedIdentifier;
+    assertPrefixedIdentifier(
+      prefixed,
+      element: findElement.setter('foo'),
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      prefixed.prefix,
+      readElement: findElement.parameter('a'),
+      writeElement: null,
+      type: 'A',
+    );
+
+    assertSimpleIdentifier(
+      prefixed.identifier,
+      readElement: null,
+      writeElement: findElement.setter('foo'),
+      type: 'int',
+    );
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
index 163de13..ed5052e 100644
--- a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
@@ -2,6 +2,7 @@
 // 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:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -16,6 +17,429 @@
 
 @reflectiveTest
 class PropertyAccessResolutionTest extends PubPackageResolutionTest {
+  test_extensionOverride_read() async {
+    await assertNoErrorsInCode('''
+class A {}
+
+extension E on A {
+  int get foo => 0;
+}
+
+void f(A a) {
+  E(a).foo;
+}
+''');
+
+    var propertyAccess = findNode.propertyAccess('foo;');
+    assertPropertyAccess2(
+      propertyAccess,
+      element: findElement.getter('foo'),
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      propertyAccess.propertyName,
+      readElement: findElement.getter('foo'),
+      writeElement: null,
+      type: 'int',
+    );
+  }
+
+  test_extensionOverride_readWrite_assignment() async {
+    await assertNoErrorsInCode('''
+class A {}
+
+extension E on A {
+  int get foo => 0;
+  set foo(num _) {}
+}
+
+void f(A a) {
+  E(a).foo += 1;
+}
+''');
+
+    var assignment = findNode.assignment('foo += 1');
+    assertAssignment(
+      assignment,
+      readElement: findElement.getter('foo'),
+      readType: 'int',
+      writeElement: findElement.setter('foo'),
+      writeType: 'num',
+      operatorElement: elementMatcher(
+        numElement.getMethod('+'),
+        isLegacy: isNullSafetySdkAndLegacyLibrary,
+      ),
+      type: 'int',
+    );
+
+    var propertyAccess = assignment.leftHandSide as PropertyAccess;
+    assertPropertyAccess2(
+      propertyAccess,
+      element: findElement.setter('foo'),
+      type: 'num',
+    );
+  }
+
+  test_extensionOverride_write() async {
+    await assertNoErrorsInCode('''
+class A {}
+
+extension E on A {
+  set foo(int _) {}
+}
+
+void f(A a) {
+  E(a).foo = 1;
+}
+''');
+
+    var assignment = findNode.assignment('foo = 1');
+    assertAssignment(
+      assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.setter('foo'),
+      writeType: 'int',
+      operatorElement: null,
+      type: 'int',
+    );
+
+    var propertyAccess = assignment.leftHandSide as PropertyAccess;
+    assertPropertyAccess2(
+      propertyAccess,
+      element: findElement.setter('foo'),
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      propertyAccess.propertyName,
+      readElement: null,
+      writeElement: findElement.setter('foo'),
+      type: 'int',
+    );
+  }
+
+  test_instanceCreation_read() async {
+    await assertNoErrorsInCode('''
+class A {
+  int foo = 0;
+}
+
+void f() {
+  A().foo;
+}
+''');
+
+    var propertyAccess = findNode.propertyAccess('foo;');
+    assertPropertyAccess2(
+      propertyAccess,
+      element: findElement.getter('foo'),
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      propertyAccess.propertyName,
+      readElement: findElement.getter('foo'),
+      writeElement: null,
+      type: 'int',
+    );
+  }
+
+  test_instanceCreation_readWrite_assignment() async {
+    await assertNoErrorsInCode('''
+class A {
+  int foo = 0;
+}
+
+void f() {
+  A().foo += 1;
+}
+''');
+
+    var assignment = findNode.assignment('foo += 1');
+    assertAssignment(
+      assignment,
+      readElement: findElement.getter('foo'),
+      readType: 'int',
+      writeElement: findElement.setter('foo'),
+      writeType: 'int',
+      operatorElement: elementMatcher(
+        numElement.getMethod('+'),
+        isLegacy: isNullSafetySdkAndLegacyLibrary,
+      ),
+      type: 'int',
+    );
+
+    var propertyAccess = assignment.leftHandSide as PropertyAccess;
+    assertPropertyAccess2(
+      propertyAccess,
+      element: findElement.setter('foo'),
+      type: 'int',
+    );
+  }
+
+  test_instanceCreation_write() async {
+    await assertNoErrorsInCode('''
+class A {
+  int foo = 0;
+}
+
+void f() {
+  A().foo = 1;
+}
+''');
+
+    var assignment = findNode.assignment('foo = 1');
+    assertAssignment(
+      assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.setter('foo'),
+      writeType: 'int',
+      operatorElement: null,
+      type: 'int',
+    );
+
+    var propertyAccess = assignment.leftHandSide as PropertyAccess;
+    assertPropertyAccess2(
+      propertyAccess,
+      element: findElement.setter('foo'),
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      propertyAccess.propertyName,
+      readElement: null,
+      writeElement: findElement.setter('foo'),
+      type: 'int',
+    );
+  }
+
+  test_ofExtension_read() async {
+    await assertNoErrorsInCode('''
+class A {}
+
+extension E on A {
+  int get foo => 0;
+}
+
+void f(A a) {
+  A().foo;
+}
+''');
+
+    var propertyAccess = findNode.propertyAccess('foo;');
+    assertPropertyAccess2(
+      propertyAccess,
+      element: findElement.getter('foo'),
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      propertyAccess.propertyName,
+      readElement: findElement.getter('foo'),
+      writeElement: null,
+      type: 'int',
+    );
+  }
+
+  test_ofExtension_readWrite_assignment() async {
+    await assertNoErrorsInCode('''
+class A {}
+
+extension E on A {
+  int get foo => 0;
+  set foo(num _) {}
+}
+
+void f() {
+  A().foo += 1;
+}
+''');
+
+    var assignment = findNode.assignment('foo += 1');
+    assertAssignment(
+      assignment,
+      readElement: findElement.getter('foo'),
+      readType: 'int',
+      writeElement: findElement.setter('foo'),
+      writeType: 'num',
+      operatorElement: elementMatcher(
+        numElement.getMethod('+'),
+        isLegacy: isNullSafetySdkAndLegacyLibrary,
+      ),
+      type: 'int',
+    );
+
+    var propertyAccess = assignment.leftHandSide as PropertyAccess;
+    assertPropertyAccess2(
+      propertyAccess,
+      element: findElement.setter('foo'),
+      type: 'num',
+    );
+  }
+
+  test_ofExtension_write() async {
+    await assertNoErrorsInCode('''
+class A {}
+
+extension E on A {
+  set foo(int _) {}
+}
+
+void f() {
+  A().foo = 1;
+}
+''');
+
+    var assignment = findNode.assignment('foo = 1');
+    assertAssignment(
+      assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.setter('foo'),
+      writeType: 'int',
+      operatorElement: null,
+      type: 'int',
+    );
+
+    var propertyAccess = assignment.leftHandSide as PropertyAccess;
+    assertPropertyAccess2(
+      propertyAccess,
+      element: findElement.setter('foo'),
+      type: 'int',
+    );
+
+    assertSimpleIdentifier(
+      propertyAccess.propertyName,
+      readElement: null,
+      writeElement: findElement.setter('foo'),
+      type: 'int',
+    );
+  }
+
+  test_super_read() async {
+    await assertNoErrorsInCode('''
+class A {
+  int foo = 0;
+}
+
+class B extends A {
+  void f() {
+    super.foo;
+  }
+}
+''');
+
+    var propertyAccess = findNode.propertyAccess('super.foo');
+    assertPropertyAccess2(
+      propertyAccess,
+      element: findElement.getter('foo'),
+      type: 'int',
+    );
+
+    assertSuperExpression(
+      propertyAccess.target,
+    );
+
+    assertSimpleIdentifier(
+      propertyAccess.propertyName,
+      readElement: findElement.getter('foo'),
+      writeElement: null,
+      type: 'int',
+    );
+  }
+
+  test_super_readWrite_assignment() async {
+    await assertNoErrorsInCode('''
+class A {
+  int foo = 0;
+}
+
+class B extends A {
+  void f() {
+    super.foo += 1;
+  }
+}
+''');
+
+    var assignment = findNode.assignment('foo += 1');
+    assertAssignment(
+      assignment,
+      readElement: findElement.getter('foo'),
+      readType: 'int',
+      writeElement: findElement.setter('foo'),
+      writeType: 'int',
+      operatorElement: elementMatcher(
+        numElement.getMethod('+'),
+        isLegacy: isNullSafetySdkAndLegacyLibrary,
+      ),
+      type: 'int',
+    );
+
+    var propertyAccess = assignment.leftHandSide as PropertyAccess;
+    assertPropertyAccess2(
+      propertyAccess,
+      element: findElement.setter('foo'),
+      type: 'int',
+    );
+
+    assertSuperExpression(
+      propertyAccess.target,
+    );
+
+    assertSimpleIdentifier(
+      propertyAccess.propertyName,
+      readElement: findElement.getter('foo'),
+      writeElement: findElement.setter('foo'),
+      type: 'int',
+    );
+  }
+
+  test_super_write() async {
+    await assertNoErrorsInCode('''
+class A {
+  int foo = 0;
+}
+
+class B extends A {
+  void f() {
+    super.foo = 1;
+  }
+}
+''');
+
+    var assignment = findNode.assignment('foo = 1');
+    assertAssignment(
+      assignment,
+      readElement: null,
+      readType: null,
+      writeElement: findElement.setter('foo'),
+      writeType: 'int',
+      operatorElement: null,
+      type: 'int',
+    );
+
+    var propertyAccess = assignment.leftHandSide as PropertyAccess;
+    assertPropertyAccess2(
+      propertyAccess,
+      element: findElement.setter('foo'),
+      type: 'int',
+    );
+
+    assertSuperExpression(
+      propertyAccess.target,
+    );
+
+    assertSimpleIdentifier(
+      propertyAccess.propertyName,
+      readElement: null,
+      writeElement: findElement.setter('foo'),
+      type: 'int',
+    );
+  }
+
   test_tearOff_method() async {
     await assertNoErrorsInCode('''
 class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 77da937..ff64040 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -96,9 +96,27 @@
 
   void assertAssignment(
     AssignmentExpression node, {
+    @required Object readElement,
+    @required String readType,
+    @required Object writeElement,
+    @required String writeType,
     @required Object operatorElement,
     @required String type,
   }) {
+    assertElement(node.readElement, readElement);
+    if (readType == null) {
+      expect(node.readType, isNull);
+    } else {
+      assertType(node.readType, readType);
+    }
+
+    assertElement(node.writeElement, writeElement);
+    if (writeType == null) {
+      expect(node.writeType, isNull);
+    } else {
+      assertType(node.writeType, writeType);
+    }
+
     assertElement(node.staticElement, operatorElement);
     assertType(node, type);
   }
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_method_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_method_test.dart
index db44bcf..3d229b4 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_method_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_method_test.dart
@@ -30,7 +30,6 @@
 }
 ''', [
       error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 87, 5),
-      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 95, 1),
     ]);
   }
 
@@ -61,7 +60,6 @@
 }
 ''', [
       error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 86, 8),
-      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 97, 1),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart
index 2526101..47bac74 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart
@@ -26,6 +26,16 @@
     ]);
   }
 
+  test_dynamic() async {
+    await assertErrorsInCode(r'''
+main() {
+  dynamic = 1;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 11, 7),
+    ]);
+  }
+
   test_enum() async {
     await assertErrorsInCode('''
 enum E { e }
diff --git a/pkg/analyzer/test/src/diagnostics/extension_override_with_cascade_test.dart b/pkg/analyzer/test/src/diagnostics/extension_override_with_cascade_test.dart
index 31888e1..b1d34fe 100644
--- a/pkg/analyzer/test/src/diagnostics/extension_override_with_cascade_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/extension_override_with_cascade_test.dart
@@ -21,10 +21,10 @@
   int get g => 0;
 }
 f() {
-  E(3)..g;
+  E(3)..g..g;
 }
 ''', [
-      error(CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, 53, 2),
+      error(CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, 49, 1),
     ]);
   }
 
@@ -34,10 +34,10 @@
   void m() {}
 }
 f() {
-  E(3)..m();
+  E(3)..m()..m();
 }
 ''', [
-      error(CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, 49, 2),
+      error(CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, 45, 1),
     ]);
   }
 
@@ -47,10 +47,10 @@
   set s(int i) {}
 }
 f() {
-  E(3)..s = 4;
+  E(3)..s = 1..s = 2;
 }
 ''', [
-      error(CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, 53, 2),
+      error(CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, 49, 1),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
index da01c89..591d171 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
@@ -164,16 +164,6 @@
 ''');
   }
 
-  test_dynamic() async {
-    await assertErrorsInCode(r'''
-main() {
-  dynamic = 1;
-}
-''', [
-      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 21, 1),
-    ]);
-  }
-
   test_functionExpressionInvocation() async {
     await assertErrorsInCode('''
 class C {
diff --git a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
index 440c7a7..0ffba47 100644
--- a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
@@ -425,6 +425,10 @@
 
     assertAssignment(
       findNode.assignment('foo += 0'),
+      readElement: null,
+      readType: 'dynamic',
+      writeElement: null,
+      writeType: 'dynamic',
       operatorElement: null,
       type: 'int',
     );
@@ -463,6 +467,10 @@
 
     assertAssignment(
       findNode.assignment('foo = 0'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: 'dynamic',
       operatorElement: null,
       type: 'int',
     );
diff --git a/pkg/dartdev/analysis_options.yaml b/pkg/dartdev/analysis_options.yaml
index b1e4858..4416a89 100644
--- a/pkg/dartdev/analysis_options.yaml
+++ b/pkg/dartdev/analysis_options.yaml
@@ -37,7 +37,6 @@
     - prefer_asserts_in_initializer_lists
     - prefer_const_constructors
     - prefer_const_declarations
-    - prefer_expression_function_bodies
     - prefer_function_declarations_over_variables
     - prefer_initializing_formals
     - prefer_inlined_adds
diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart
index 0b17ed9..275c8c2 100644
--- a/pkg/dartdev/lib/dartdev.dart
+++ b/pkg/dartdev/lib/dartdev.dart
@@ -179,6 +179,10 @@
 }
 
 class DartdevRunner<int> extends CommandRunner {
+  @override
+  final ArgParser argParser =
+      ArgParser(usageLineLength: dartdevUsageLineLength);
+
   static const String dartdevDescription =
       'A command-line utility for Dart development';
 
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index fdab918..4b94bcf 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 import 'dart:io';
 
-import 'package:args/command_runner.dart';
 import 'package:dart2native/generate.dart';
 import 'package:path/path.dart' as path;
 
@@ -228,14 +227,8 @@
   }
 }
 
-class CompileCommand extends Command {
-  @override
-  String get description => 'Compile Dart to various formats.';
-
-  @override
-  String get name => 'compile';
-
-  CompileCommand() {
+class CompileCommand extends DartdevCommand {
+  CompileCommand() : super('compile', 'Compile Dart to various formats.') {
     addSubcommand(CompileJSCommand());
     addSubcommand(CompileSnapshotCommand(
       commandName: 'jit-snapshot',
diff --git a/pkg/dartdev/lib/src/commands/fix.dart b/pkg/dartdev/lib/src/commands/fix.dart
index b0c09b0..36a8579 100644
--- a/pkg/dartdev/lib/src/commands/fix.dart
+++ b/pkg/dartdev/lib/src/commands/fix.dart
@@ -14,12 +14,8 @@
 import 'analyze_impl.dart';
 
 class FixCommand extends DartdevCommand {
-  FixCommand()
-      : super(
-          'fix', 'Fix Dart source code.',
-          // Experimental.
-          hidden: true,
-        );
+  // This command is hidden as its currently experimental.
+  FixCommand() : super('fix', 'Fix Dart source code.', hidden: true);
 
   @override
   FutureOr<int> run() async {
diff --git a/pkg/dartdev/lib/src/commands/pub.dart b/pkg/dartdev/lib/src/commands/pub.dart
index 7d91085..6b40ebc 100644
--- a/pkg/dartdev/lib/src/commands/pub.dart
+++ b/pkg/dartdev/lib/src/commands/pub.dart
@@ -15,7 +15,7 @@
   PubCommand() : super('pub', 'Work with packages.');
 
   @override
-  final ArgParser argParser = ArgParser.allowAnything();
+  ArgParser createArgParser() => ArgParser.allowAnything();
 
   @override
   void printUsage() {
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index 31bd2ba..fe2f67a 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -26,11 +26,13 @@
   // provided before any command and to provide a more consistent help message
   // with the rest of the tool.
   @override
-  final ArgParser argParser = ArgParser(
-    // Don't parse flags after script name.
-    allowTrailingOptions: false,
-    usageLineLength: stdout.hasTerminal ? stdout.terminalColumns : null,
-  );
+  ArgParser createArgParser() {
+    return ArgParser(
+      // Don't parse flags after script name.
+      allowTrailingOptions: false,
+      usageLineLength: dartdevUsageLineLength,
+    );
+  }
 
   @override
   final bool verbose;
diff --git a/pkg/dartdev/lib/src/core.dart b/pkg/dartdev/lib/src/core.dart
index 4de6ecd..9a05bee 100644
--- a/pkg/dartdev/lib/src/core.dart
+++ b/pkg/dartdev/lib/src/core.dart
@@ -5,6 +5,7 @@
 import 'dart:convert';
 import 'dart:io';
 
+import 'package:args/args.dart';
 import 'package:args/command_runner.dart';
 import 'package:cli_util/cli_logging.dart';
 import 'package:path/path.dart' as path;
@@ -33,6 +34,17 @@
   @override
   String get description => _description;
 
+  ArgParser _argParser;
+
+  @override
+  ArgParser get argParser => _argParser ??= createArgParser();
+
+  /// Create the ArgParser instance for this command.
+  ///
+  /// Subclasses can override this in order to create a customized ArgParser.
+  ArgParser createArgParser() =>
+      ArgParser(usageLineLength: dartdevUsageLineLength);
+
   Project get project => _project ??= Project();
 
   /// Return whether commands should emit verbose output.
diff --git a/pkg/dartdev/lib/src/utils.dart b/pkg/dartdev/lib/src/utils.dart
index 3d3bd68..f77574c 100644
--- a/pkg/dartdev/lib/src/utils.dart
+++ b/pkg/dartdev/lib/src/utils.dart
@@ -6,6 +6,11 @@
 
 import 'package:path/path.dart' as p;
 
+/// For commands where we are able to initialize the [ArgParser], this value
+/// is used as the usageLineLength.
+int get dartdevUsageLineLength =>
+    stdout.hasTerminal ? stdout.terminalColumns : null;
+
 /// Given a data structure which is a Map of String to dynamic values, return
 /// the same structure (`Map<String, dynamic>`) with the correct runtime types.
 Map<String, dynamic> castStringKeyedMap(dynamic untyped) {
@@ -36,6 +41,14 @@
 /// Static util methods used in dartdev to potentially modify the order of the
 /// arguments passed into dartdev.
 class PubUtils {
+  /// If [doModifyArgs] returns true, then this method returns a modified copy
+  /// of the argument list, 'help' is removed from the interior of the list, and
+  /// '--help' is added to the end of the list of arguments. This method returns
+  /// a modified copy of the list, the list itself is not modified.
+  static List<String> modifyArgs(List<String> args) => List.from(args)
+    ..remove('help')
+    ..add('--help');
+
   /// If ... help pub ..., and no other verb (such as 'analyze') appears before
   /// the ... help pub ... in the argument list, then return true.
   static bool shouldModifyArgs(List<String> args, List<String> allCmds) =>
@@ -47,14 +60,6 @@
       args.contains('help') &&
       args.contains('pub') &&
       args.indexOf('help') + 1 == args.indexOf('pub');
-
-  /// If [doModifyArgs] returns true, then this method returns a modified copy
-  /// of the argument list, 'help' is removed from the interior of the list, and
-  /// '--help' is added to the end of the list of arguments. This method returns
-  /// a modified copy of the list, the list itself is not modified.
-  static List<String> modifyArgs(List<String> args) => List.from(args)
-    ..remove('help')
-    ..add('--help');
 }
 
 extension FileSystemEntityExtension on FileSystemEntity {
diff --git a/pkg/dartdev/test/commands/flag_test.dart b/pkg/dartdev/test/commands/flag_test.dart
index 17a4ca0..1e887b1 100644
--- a/pkg/dartdev/test/commands/flag_test.dart
+++ b/pkg/dartdev/test/commands/flag_test.dart
@@ -31,12 +31,15 @@
   });
 
   // Assert that all found usageLineLengths are the same and null
-  test('argParser usageLineLength isNull', () {
+  test('argParser usageLineLength', () {
     DartdevRunner(['--disable-dartdev-analytics'])
         .commands
         .forEach((String commandKey, Command command) {
       if (command.argParser != null) {
-        if (command.name == 'run') {
+        if (command.name != 'help' &&
+            command.name != 'format' &&
+            command.name != 'migrate' &&
+            command.name != 'pub') {
           expect(command.argParser.usageLineLength,
               stdout.hasTerminal ? stdout.terminalColumns : null);
         } else {
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 77ebc088..5dbfb12 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -36,6 +36,9 @@
   /// reported.
   Builder lookupLocalMemberByName(Name name,
       {bool setter: false, bool required: false});
+
+  /// Calls [f] for each member declared in this extension.
+  void forEach(void f(String name, Builder builder));
 }
 
 abstract class ExtensionBuilderImpl extends DeclarationBuilderImpl
@@ -87,6 +90,11 @@
   }
 
   @override
+  void forEach(void f(String name, Builder builder)) {
+    scope.forEach(f);
+  }
+
+  @override
   bool get isExtension => true;
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 304aed3..0c3c024 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -2863,6 +2863,20 @@
           reportIssues(issues);
           count += computeDefaultTypesForVariables(declaration.typeVariables,
               inErrorRecovery: issues.isNotEmpty);
+
+          declaration.constructors.forEach((String name, Builder member) {
+            if (member is ProcedureBuilder) {
+              assert(member.isFactory,
+                  "Unexpected constructor member (${member.runtimeType}).");
+              count += computeDefaultTypesForVariables(member.typeVariables,
+                  // Type variables are inherited from the class so if the class
+                  // has issues, so does the factory constructors.
+                  inErrorRecovery: issues.isNotEmpty);
+            } else {
+              assert(member is ConstructorBuilder,
+                  "Unexpected constructor member (${member.runtimeType}).");
+            }
+          });
         }
         declaration.forEach((String name, Builder member) {
           if (member is ProcedureBuilder) {
@@ -2871,6 +2885,9 @@
             reportIssues(issues);
             count += computeDefaultTypesForVariables(member.typeVariables,
                 inErrorRecovery: issues.isNotEmpty);
+          } else {
+            assert(member is FieldBuilder,
+                "Unexpected class member $member (${member.runtimeType}).");
           }
         });
       } else if (declaration is TypeAliasBuilder) {
@@ -2885,6 +2902,35 @@
         reportIssues(issues);
         count += computeDefaultTypesForVariables(declaration.typeVariables,
             inErrorRecovery: issues.isNotEmpty);
+      } else if (declaration is ExtensionBuilder) {
+        {
+          List<Object> issues = getNonSimplicityIssuesForDeclaration(
+              declaration,
+              performErrorRecovery: true);
+          reportIssues(issues);
+          count += computeDefaultTypesForVariables(declaration.typeParameters,
+              inErrorRecovery: issues.isNotEmpty);
+        }
+        declaration.forEach((String name, Builder member) {
+          if (member is ProcedureBuilder) {
+            List<Object> issues =
+                getNonSimplicityIssuesForTypeVariables(member.typeVariables);
+            reportIssues(issues);
+            count += computeDefaultTypesForVariables(member.typeVariables,
+                inErrorRecovery: issues.isNotEmpty);
+          } else {
+            assert(member is FieldBuilder,
+                "Unexpected extension member $member (${member.runtimeType}).");
+          }
+        });
+      } else {
+        assert(
+            declaration is FieldBuilder ||
+                declaration is PrefixBuilder ||
+                declaration is DynamicTypeBuilder ||
+                declaration is NeverTypeBuilder,
+            "Unexpected top level member $declaration "
+            "(${declaration.runtimeType}).");
       }
     }
 
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 448aa23..d39c684 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -135,6 +135,7 @@
 coo
 costly
 cov
+cp
 crashes
 cumulative
 cx
@@ -638,6 +639,7 @@
 verbatim
 versioned
 versioning
+vp
 waited
 waiting
 waits
diff --git a/pkg/front_end/testcases/extensions/bounds.dart b/pkg/front_end/testcases/extensions/bounds.dart
new file mode 100644
index 0000000..ee4308a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/bounds.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2020, 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.
+
+extension Extension1<T extends Object> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension2<T extends String> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension3<T extends dynamic> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension4<T> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/bounds.dart.outline.expect b/pkg/front_end/testcases/extensions/bounds.dart.outline.expect
new file mode 100644
index 0000000..6c07498
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/bounds.dart.outline.expect
@@ -0,0 +1,110 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+extension Extension1<T extends core::Object* = core::Object*> on T* {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+  method method3 = self::Extension1|method3;
+  tearoff method3 = self::Extension1|get#method3;
+  method method4 = self::Extension1|method4;
+  tearoff method4 = self::Extension1|get#method4;
+}
+extension Extension2<T extends core::String* = core::String*> on T* {
+  method method1 = self::Extension2|method1;
+  tearoff method1 = self::Extension2|get#method1;
+  method method2 = self::Extension2|method2;
+  tearoff method2 = self::Extension2|get#method2;
+  method method3 = self::Extension2|method3;
+  tearoff method3 = self::Extension2|get#method3;
+  method method4 = self::Extension2|method4;
+  tearoff method4 = self::Extension2|get#method4;
+}
+extension Extension3<T extends dynamic = dynamic> on T* {
+  method method1 = self::Extension3|method1;
+  tearoff method1 = self::Extension3|get#method1;
+  method method2 = self::Extension3|method2;
+  tearoff method2 = self::Extension3|get#method2;
+  method method3 = self::Extension3|method3;
+  tearoff method3 = self::Extension3|get#method3;
+  method method4 = self::Extension3|method4;
+  tearoff method4 = self::Extension3|get#method4;
+}
+extension Extension4<T extends core::Object* = dynamic> on T* {
+  method method1 = self::Extension4|method1;
+  tearoff method1 = self::Extension4|get#method1;
+  method method2 = self::Extension4|method2;
+  tearoff method2 = self::Extension4|get#method2;
+  method method3 = self::Extension4|method3;
+  tearoff method3 = self::Extension4|get#method3;
+  method method4 = self::Extension4|method4;
+  tearoff method4 = self::Extension4|get#method4;
+}
+static method Extension1|method1<T extends core::Object* = core::Object*, S extends core::Object* = core::Object*>(final self::Extension1|method1::T* #this) → dynamic
+  ;
+static method Extension1|get#method1<T extends core::Object* = core::Object*>(final self::Extension1|get#method1::T* #this) → <S extends core::Object* = core::Object*>() →* dynamic
+  return <S extends core::Object* = core::Object*>() → dynamic => self::Extension1|method1<self::Extension1|get#method1::T*, S*>(#this);
+static method Extension1|method2<T extends core::Object* = core::Object*, S extends core::String* = core::String*>(final self::Extension1|method2::T* #this) → dynamic
+  ;
+static method Extension1|get#method2<T extends core::Object* = core::Object*>(final self::Extension1|get#method2::T* #this) → <S extends core::String* = core::String*>() →* dynamic
+  return <S extends core::String* = core::String*>() → dynamic => self::Extension1|method2<self::Extension1|get#method2::T*, S*>(#this);
+static method Extension1|method3<T extends core::Object* = core::Object*, S extends dynamic = dynamic>(final self::Extension1|method3::T* #this) → dynamic
+  ;
+static method Extension1|get#method3<T extends core::Object* = core::Object*>(final self::Extension1|get#method3::T* #this) → <S extends dynamic = dynamic>() →* dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension1|method3<self::Extension1|get#method3::T*, S%>(#this);
+static method Extension1|method4<T extends core::Object* = core::Object*, S extends core::Object* = dynamic>(final self::Extension1|method4::T* #this) → dynamic
+  ;
+static method Extension1|get#method4<T extends core::Object* = core::Object*>(final self::Extension1|get#method4::T* #this) → <S extends core::Object* = dynamic>() →* dynamic
+  return <S extends core::Object* = dynamic>() → dynamic => self::Extension1|method4<self::Extension1|get#method4::T*, S*>(#this);
+static method Extension2|method1<T extends core::String* = core::String*, S extends core::Object* = core::Object*>(final self::Extension2|method1::T* #this) → dynamic
+  ;
+static method Extension2|get#method1<T extends core::String* = core::String*>(final self::Extension2|get#method1::T* #this) → <S extends core::Object* = core::Object*>() →* dynamic
+  return <S extends core::Object* = core::Object*>() → dynamic => self::Extension2|method1<self::Extension2|get#method1::T*, S*>(#this);
+static method Extension2|method2<T extends core::String* = core::String*, S extends core::String* = core::String*>(final self::Extension2|method2::T* #this) → dynamic
+  ;
+static method Extension2|get#method2<T extends core::String* = core::String*>(final self::Extension2|get#method2::T* #this) → <S extends core::String* = core::String*>() →* dynamic
+  return <S extends core::String* = core::String*>() → dynamic => self::Extension2|method2<self::Extension2|get#method2::T*, S*>(#this);
+static method Extension2|method3<T extends core::String* = core::String*, S extends dynamic = dynamic>(final self::Extension2|method3::T* #this) → dynamic
+  ;
+static method Extension2|get#method3<T extends core::String* = core::String*>(final self::Extension2|get#method3::T* #this) → <S extends dynamic = dynamic>() →* dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension2|method3<self::Extension2|get#method3::T*, S%>(#this);
+static method Extension2|method4<T extends core::String* = core::String*, S extends core::Object* = dynamic>(final self::Extension2|method4::T* #this) → dynamic
+  ;
+static method Extension2|get#method4<T extends core::String* = core::String*>(final self::Extension2|get#method4::T* #this) → <S extends core::Object* = dynamic>() →* dynamic
+  return <S extends core::Object* = dynamic>() → dynamic => self::Extension2|method4<self::Extension2|get#method4::T*, S*>(#this);
+static method Extension3|method1<T extends dynamic = dynamic, S extends core::Object* = core::Object*>(final self::Extension3|method1::T* #this) → dynamic
+  ;
+static method Extension3|get#method1<T extends dynamic = dynamic>(final self::Extension3|get#method1::T* #this) → <S extends core::Object* = core::Object*>() →* dynamic
+  return <S extends core::Object* = core::Object*>() → dynamic => self::Extension3|method1<self::Extension3|get#method1::T%, S*>(#this);
+static method Extension3|method2<T extends dynamic = dynamic, S extends core::String* = core::String*>(final self::Extension3|method2::T* #this) → dynamic
+  ;
+static method Extension3|get#method2<T extends dynamic = dynamic>(final self::Extension3|get#method2::T* #this) → <S extends core::String* = core::String*>() →* dynamic
+  return <S extends core::String* = core::String*>() → dynamic => self::Extension3|method2<self::Extension3|get#method2::T%, S*>(#this);
+static method Extension3|method3<T extends dynamic = dynamic, S extends dynamic = dynamic>(final self::Extension3|method3::T* #this) → dynamic
+  ;
+static method Extension3|get#method3<T extends dynamic = dynamic>(final self::Extension3|get#method3::T* #this) → <S extends dynamic = dynamic>() →* dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension3|method3<self::Extension3|get#method3::T%, S%>(#this);
+static method Extension3|method4<T extends dynamic = dynamic, S extends core::Object* = dynamic>(final self::Extension3|method4::T* #this) → dynamic
+  ;
+static method Extension3|get#method4<T extends dynamic = dynamic>(final self::Extension3|get#method4::T* #this) → <S extends core::Object* = dynamic>() →* dynamic
+  return <S extends core::Object* = dynamic>() → dynamic => self::Extension3|method4<self::Extension3|get#method4::T%, S*>(#this);
+static method Extension4|method1<T extends core::Object* = dynamic, S extends core::Object* = core::Object*>(final self::Extension4|method1::T* #this) → dynamic
+  ;
+static method Extension4|get#method1<T extends core::Object* = dynamic>(final self::Extension4|get#method1::T* #this) → <S extends core::Object* = core::Object*>() →* dynamic
+  return <S extends core::Object* = core::Object*>() → dynamic => self::Extension4|method1<self::Extension4|get#method1::T*, S*>(#this);
+static method Extension4|method2<T extends core::Object* = dynamic, S extends core::String* = core::String*>(final self::Extension4|method2::T* #this) → dynamic
+  ;
+static method Extension4|get#method2<T extends core::Object* = dynamic>(final self::Extension4|get#method2::T* #this) → <S extends core::String* = core::String*>() →* dynamic
+  return <S extends core::String* = core::String*>() → dynamic => self::Extension4|method2<self::Extension4|get#method2::T*, S*>(#this);
+static method Extension4|method3<T extends core::Object* = dynamic, S extends dynamic = dynamic>(final self::Extension4|method3::T* #this) → dynamic
+  ;
+static method Extension4|get#method3<T extends core::Object* = dynamic>(final self::Extension4|get#method3::T* #this) → <S extends dynamic = dynamic>() →* dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension4|method3<self::Extension4|get#method3::T*, S%>(#this);
+static method Extension4|method4<T extends core::Object* = dynamic, S extends core::Object* = dynamic>(final self::Extension4|method4::T* #this) → dynamic
+  ;
+static method Extension4|get#method4<T extends core::Object* = dynamic>(final self::Extension4|get#method4::T* #this) → <S extends core::Object* = dynamic>() →* dynamic
+  return <S extends core::Object* = dynamic>() → dynamic => self::Extension4|method4<self::Extension4|get#method4::T*, S*>(#this);
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/bounds.dart.strong.expect b/pkg/front_end/testcases/extensions/bounds.dart.strong.expect
new file mode 100644
index 0000000..46c68c7
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/bounds.dart.strong.expect
@@ -0,0 +1,93 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+extension Extension1<T extends core::Object* = core::Object*> on T* {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+  method method3 = self::Extension1|method3;
+  tearoff method3 = self::Extension1|get#method3;
+  method method4 = self::Extension1|method4;
+  tearoff method4 = self::Extension1|get#method4;
+}
+extension Extension2<T extends core::String* = core::String*> on T* {
+  method method1 = self::Extension2|method1;
+  tearoff method1 = self::Extension2|get#method1;
+  method method2 = self::Extension2|method2;
+  tearoff method2 = self::Extension2|get#method2;
+  method method3 = self::Extension2|method3;
+  tearoff method3 = self::Extension2|get#method3;
+  method method4 = self::Extension2|method4;
+  tearoff method4 = self::Extension2|get#method4;
+}
+extension Extension3<T extends dynamic = dynamic> on T* {
+  method method1 = self::Extension3|method1;
+  tearoff method1 = self::Extension3|get#method1;
+  method method2 = self::Extension3|method2;
+  tearoff method2 = self::Extension3|get#method2;
+  method method3 = self::Extension3|method3;
+  tearoff method3 = self::Extension3|get#method3;
+  method method4 = self::Extension3|method4;
+  tearoff method4 = self::Extension3|get#method4;
+}
+extension Extension4<T extends core::Object* = dynamic> on T* {
+  method method1 = self::Extension4|method1;
+  tearoff method1 = self::Extension4|get#method1;
+  method method2 = self::Extension4|method2;
+  tearoff method2 = self::Extension4|get#method2;
+  method method3 = self::Extension4|method3;
+  tearoff method3 = self::Extension4|get#method3;
+  method method4 = self::Extension4|method4;
+  tearoff method4 = self::Extension4|get#method4;
+}
+static method Extension1|method1<T extends core::Object* = core::Object*, S extends core::Object* = core::Object*>(final self::Extension1|method1::T* #this) → dynamic {}
+static method Extension1|get#method1<T extends core::Object* = core::Object*>(final self::Extension1|get#method1::T* #this) → <S extends core::Object* = core::Object*>() →* dynamic
+  return <S extends core::Object* = core::Object*>() → dynamic => self::Extension1|method1<self::Extension1|get#method1::T*, S*>(#this);
+static method Extension1|method2<T extends core::Object* = core::Object*, S extends core::String* = core::String*>(final self::Extension1|method2::T* #this) → dynamic {}
+static method Extension1|get#method2<T extends core::Object* = core::Object*>(final self::Extension1|get#method2::T* #this) → <S extends core::String* = core::String*>() →* dynamic
+  return <S extends core::String* = core::String*>() → dynamic => self::Extension1|method2<self::Extension1|get#method2::T*, S*>(#this);
+static method Extension1|method3<T extends core::Object* = core::Object*, S extends dynamic = dynamic>(final self::Extension1|method3::T* #this) → dynamic {}
+static method Extension1|get#method3<T extends core::Object* = core::Object*>(final self::Extension1|get#method3::T* #this) → <S extends dynamic = dynamic>() →* dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension1|method3<self::Extension1|get#method3::T*, S%>(#this);
+static method Extension1|method4<T extends core::Object* = core::Object*, S extends core::Object* = dynamic>(final self::Extension1|method4::T* #this) → dynamic {}
+static method Extension1|get#method4<T extends core::Object* = core::Object*>(final self::Extension1|get#method4::T* #this) → <S extends core::Object* = dynamic>() →* dynamic
+  return <S extends core::Object* = dynamic>() → dynamic => self::Extension1|method4<self::Extension1|get#method4::T*, S*>(#this);
+static method Extension2|method1<T extends core::String* = core::String*, S extends core::Object* = core::Object*>(final self::Extension2|method1::T* #this) → dynamic {}
+static method Extension2|get#method1<T extends core::String* = core::String*>(final self::Extension2|get#method1::T* #this) → <S extends core::Object* = core::Object*>() →* dynamic
+  return <S extends core::Object* = core::Object*>() → dynamic => self::Extension2|method1<self::Extension2|get#method1::T*, S*>(#this);
+static method Extension2|method2<T extends core::String* = core::String*, S extends core::String* = core::String*>(final self::Extension2|method2::T* #this) → dynamic {}
+static method Extension2|get#method2<T extends core::String* = core::String*>(final self::Extension2|get#method2::T* #this) → <S extends core::String* = core::String*>() →* dynamic
+  return <S extends core::String* = core::String*>() → dynamic => self::Extension2|method2<self::Extension2|get#method2::T*, S*>(#this);
+static method Extension2|method3<T extends core::String* = core::String*, S extends dynamic = dynamic>(final self::Extension2|method3::T* #this) → dynamic {}
+static method Extension2|get#method3<T extends core::String* = core::String*>(final self::Extension2|get#method3::T* #this) → <S extends dynamic = dynamic>() →* dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension2|method3<self::Extension2|get#method3::T*, S%>(#this);
+static method Extension2|method4<T extends core::String* = core::String*, S extends core::Object* = dynamic>(final self::Extension2|method4::T* #this) → dynamic {}
+static method Extension2|get#method4<T extends core::String* = core::String*>(final self::Extension2|get#method4::T* #this) → <S extends core::Object* = dynamic>() →* dynamic
+  return <S extends core::Object* = dynamic>() → dynamic => self::Extension2|method4<self::Extension2|get#method4::T*, S*>(#this);
+static method Extension3|method1<T extends dynamic = dynamic, S extends core::Object* = core::Object*>(final self::Extension3|method1::T* #this) → dynamic {}
+static method Extension3|get#method1<T extends dynamic = dynamic>(final self::Extension3|get#method1::T* #this) → <S extends core::Object* = core::Object*>() →* dynamic
+  return <S extends core::Object* = core::Object*>() → dynamic => self::Extension3|method1<self::Extension3|get#method1::T%, S*>(#this);
+static method Extension3|method2<T extends dynamic = dynamic, S extends core::String* = core::String*>(final self::Extension3|method2::T* #this) → dynamic {}
+static method Extension3|get#method2<T extends dynamic = dynamic>(final self::Extension3|get#method2::T* #this) → <S extends core::String* = core::String*>() →* dynamic
+  return <S extends core::String* = core::String*>() → dynamic => self::Extension3|method2<self::Extension3|get#method2::T%, S*>(#this);
+static method Extension3|method3<T extends dynamic = dynamic, S extends dynamic = dynamic>(final self::Extension3|method3::T* #this) → dynamic {}
+static method Extension3|get#method3<T extends dynamic = dynamic>(final self::Extension3|get#method3::T* #this) → <S extends dynamic = dynamic>() →* dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension3|method3<self::Extension3|get#method3::T%, S%>(#this);
+static method Extension3|method4<T extends dynamic = dynamic, S extends core::Object* = dynamic>(final self::Extension3|method4::T* #this) → dynamic {}
+static method Extension3|get#method4<T extends dynamic = dynamic>(final self::Extension3|get#method4::T* #this) → <S extends core::Object* = dynamic>() →* dynamic
+  return <S extends core::Object* = dynamic>() → dynamic => self::Extension3|method4<self::Extension3|get#method4::T%, S*>(#this);
+static method Extension4|method1<T extends core::Object* = dynamic, S extends core::Object* = core::Object*>(final self::Extension4|method1::T* #this) → dynamic {}
+static method Extension4|get#method1<T extends core::Object* = dynamic>(final self::Extension4|get#method1::T* #this) → <S extends core::Object* = core::Object*>() →* dynamic
+  return <S extends core::Object* = core::Object*>() → dynamic => self::Extension4|method1<self::Extension4|get#method1::T*, S*>(#this);
+static method Extension4|method2<T extends core::Object* = dynamic, S extends core::String* = core::String*>(final self::Extension4|method2::T* #this) → dynamic {}
+static method Extension4|get#method2<T extends core::Object* = dynamic>(final self::Extension4|get#method2::T* #this) → <S extends core::String* = core::String*>() →* dynamic
+  return <S extends core::String* = core::String*>() → dynamic => self::Extension4|method2<self::Extension4|get#method2::T*, S*>(#this);
+static method Extension4|method3<T extends core::Object* = dynamic, S extends dynamic = dynamic>(final self::Extension4|method3::T* #this) → dynamic {}
+static method Extension4|get#method3<T extends core::Object* = dynamic>(final self::Extension4|get#method3::T* #this) → <S extends dynamic = dynamic>() →* dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension4|method3<self::Extension4|get#method3::T*, S%>(#this);
+static method Extension4|method4<T extends core::Object* = dynamic, S extends core::Object* = dynamic>(final self::Extension4|method4::T* #this) → dynamic {}
+static method Extension4|get#method4<T extends core::Object* = dynamic>(final self::Extension4|get#method4::T* #this) → <S extends core::Object* = dynamic>() →* dynamic
+  return <S extends core::Object* = dynamic>() → dynamic => self::Extension4|method4<self::Extension4|get#method4::T*, S*>(#this);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/bounds.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/bounds.dart.strong.transformed.expect
new file mode 100644
index 0000000..46c68c7
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/bounds.dart.strong.transformed.expect
@@ -0,0 +1,93 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+extension Extension1<T extends core::Object* = core::Object*> on T* {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+  method method3 = self::Extension1|method3;
+  tearoff method3 = self::Extension1|get#method3;
+  method method4 = self::Extension1|method4;
+  tearoff method4 = self::Extension1|get#method4;
+}
+extension Extension2<T extends core::String* = core::String*> on T* {
+  method method1 = self::Extension2|method1;
+  tearoff method1 = self::Extension2|get#method1;
+  method method2 = self::Extension2|method2;
+  tearoff method2 = self::Extension2|get#method2;
+  method method3 = self::Extension2|method3;
+  tearoff method3 = self::Extension2|get#method3;
+  method method4 = self::Extension2|method4;
+  tearoff method4 = self::Extension2|get#method4;
+}
+extension Extension3<T extends dynamic = dynamic> on T* {
+  method method1 = self::Extension3|method1;
+  tearoff method1 = self::Extension3|get#method1;
+  method method2 = self::Extension3|method2;
+  tearoff method2 = self::Extension3|get#method2;
+  method method3 = self::Extension3|method3;
+  tearoff method3 = self::Extension3|get#method3;
+  method method4 = self::Extension3|method4;
+  tearoff method4 = self::Extension3|get#method4;
+}
+extension Extension4<T extends core::Object* = dynamic> on T* {
+  method method1 = self::Extension4|method1;
+  tearoff method1 = self::Extension4|get#method1;
+  method method2 = self::Extension4|method2;
+  tearoff method2 = self::Extension4|get#method2;
+  method method3 = self::Extension4|method3;
+  tearoff method3 = self::Extension4|get#method3;
+  method method4 = self::Extension4|method4;
+  tearoff method4 = self::Extension4|get#method4;
+}
+static method Extension1|method1<T extends core::Object* = core::Object*, S extends core::Object* = core::Object*>(final self::Extension1|method1::T* #this) → dynamic {}
+static method Extension1|get#method1<T extends core::Object* = core::Object*>(final self::Extension1|get#method1::T* #this) → <S extends core::Object* = core::Object*>() →* dynamic
+  return <S extends core::Object* = core::Object*>() → dynamic => self::Extension1|method1<self::Extension1|get#method1::T*, S*>(#this);
+static method Extension1|method2<T extends core::Object* = core::Object*, S extends core::String* = core::String*>(final self::Extension1|method2::T* #this) → dynamic {}
+static method Extension1|get#method2<T extends core::Object* = core::Object*>(final self::Extension1|get#method2::T* #this) → <S extends core::String* = core::String*>() →* dynamic
+  return <S extends core::String* = core::String*>() → dynamic => self::Extension1|method2<self::Extension1|get#method2::T*, S*>(#this);
+static method Extension1|method3<T extends core::Object* = core::Object*, S extends dynamic = dynamic>(final self::Extension1|method3::T* #this) → dynamic {}
+static method Extension1|get#method3<T extends core::Object* = core::Object*>(final self::Extension1|get#method3::T* #this) → <S extends dynamic = dynamic>() →* dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension1|method3<self::Extension1|get#method3::T*, S%>(#this);
+static method Extension1|method4<T extends core::Object* = core::Object*, S extends core::Object* = dynamic>(final self::Extension1|method4::T* #this) → dynamic {}
+static method Extension1|get#method4<T extends core::Object* = core::Object*>(final self::Extension1|get#method4::T* #this) → <S extends core::Object* = dynamic>() →* dynamic
+  return <S extends core::Object* = dynamic>() → dynamic => self::Extension1|method4<self::Extension1|get#method4::T*, S*>(#this);
+static method Extension2|method1<T extends core::String* = core::String*, S extends core::Object* = core::Object*>(final self::Extension2|method1::T* #this) → dynamic {}
+static method Extension2|get#method1<T extends core::String* = core::String*>(final self::Extension2|get#method1::T* #this) → <S extends core::Object* = core::Object*>() →* dynamic
+  return <S extends core::Object* = core::Object*>() → dynamic => self::Extension2|method1<self::Extension2|get#method1::T*, S*>(#this);
+static method Extension2|method2<T extends core::String* = core::String*, S extends core::String* = core::String*>(final self::Extension2|method2::T* #this) → dynamic {}
+static method Extension2|get#method2<T extends core::String* = core::String*>(final self::Extension2|get#method2::T* #this) → <S extends core::String* = core::String*>() →* dynamic
+  return <S extends core::String* = core::String*>() → dynamic => self::Extension2|method2<self::Extension2|get#method2::T*, S*>(#this);
+static method Extension2|method3<T extends core::String* = core::String*, S extends dynamic = dynamic>(final self::Extension2|method3::T* #this) → dynamic {}
+static method Extension2|get#method3<T extends core::String* = core::String*>(final self::Extension2|get#method3::T* #this) → <S extends dynamic = dynamic>() →* dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension2|method3<self::Extension2|get#method3::T*, S%>(#this);
+static method Extension2|method4<T extends core::String* = core::String*, S extends core::Object* = dynamic>(final self::Extension2|method4::T* #this) → dynamic {}
+static method Extension2|get#method4<T extends core::String* = core::String*>(final self::Extension2|get#method4::T* #this) → <S extends core::Object* = dynamic>() →* dynamic
+  return <S extends core::Object* = dynamic>() → dynamic => self::Extension2|method4<self::Extension2|get#method4::T*, S*>(#this);
+static method Extension3|method1<T extends dynamic = dynamic, S extends core::Object* = core::Object*>(final self::Extension3|method1::T* #this) → dynamic {}
+static method Extension3|get#method1<T extends dynamic = dynamic>(final self::Extension3|get#method1::T* #this) → <S extends core::Object* = core::Object*>() →* dynamic
+  return <S extends core::Object* = core::Object*>() → dynamic => self::Extension3|method1<self::Extension3|get#method1::T%, S*>(#this);
+static method Extension3|method2<T extends dynamic = dynamic, S extends core::String* = core::String*>(final self::Extension3|method2::T* #this) → dynamic {}
+static method Extension3|get#method2<T extends dynamic = dynamic>(final self::Extension3|get#method2::T* #this) → <S extends core::String* = core::String*>() →* dynamic
+  return <S extends core::String* = core::String*>() → dynamic => self::Extension3|method2<self::Extension3|get#method2::T%, S*>(#this);
+static method Extension3|method3<T extends dynamic = dynamic, S extends dynamic = dynamic>(final self::Extension3|method3::T* #this) → dynamic {}
+static method Extension3|get#method3<T extends dynamic = dynamic>(final self::Extension3|get#method3::T* #this) → <S extends dynamic = dynamic>() →* dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension3|method3<self::Extension3|get#method3::T%, S%>(#this);
+static method Extension3|method4<T extends dynamic = dynamic, S extends core::Object* = dynamic>(final self::Extension3|method4::T* #this) → dynamic {}
+static method Extension3|get#method4<T extends dynamic = dynamic>(final self::Extension3|get#method4::T* #this) → <S extends core::Object* = dynamic>() →* dynamic
+  return <S extends core::Object* = dynamic>() → dynamic => self::Extension3|method4<self::Extension3|get#method4::T%, S*>(#this);
+static method Extension4|method1<T extends core::Object* = dynamic, S extends core::Object* = core::Object*>(final self::Extension4|method1::T* #this) → dynamic {}
+static method Extension4|get#method1<T extends core::Object* = dynamic>(final self::Extension4|get#method1::T* #this) → <S extends core::Object* = core::Object*>() →* dynamic
+  return <S extends core::Object* = core::Object*>() → dynamic => self::Extension4|method1<self::Extension4|get#method1::T*, S*>(#this);
+static method Extension4|method2<T extends core::Object* = dynamic, S extends core::String* = core::String*>(final self::Extension4|method2::T* #this) → dynamic {}
+static method Extension4|get#method2<T extends core::Object* = dynamic>(final self::Extension4|get#method2::T* #this) → <S extends core::String* = core::String*>() →* dynamic
+  return <S extends core::String* = core::String*>() → dynamic => self::Extension4|method2<self::Extension4|get#method2::T*, S*>(#this);
+static method Extension4|method3<T extends core::Object* = dynamic, S extends dynamic = dynamic>(final self::Extension4|method3::T* #this) → dynamic {}
+static method Extension4|get#method3<T extends core::Object* = dynamic>(final self::Extension4|get#method3::T* #this) → <S extends dynamic = dynamic>() →* dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension4|method3<self::Extension4|get#method3::T*, S%>(#this);
+static method Extension4|method4<T extends core::Object* = dynamic, S extends core::Object* = dynamic>(final self::Extension4|method4::T* #this) → dynamic {}
+static method Extension4|get#method4<T extends core::Object* = dynamic>(final self::Extension4|get#method4::T* #this) → <S extends core::Object* = dynamic>() →* dynamic
+  return <S extends core::Object* = dynamic>() → dynamic => self::Extension4|method4<self::Extension4|get#method4::T*, S*>(#this);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/bounds.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/bounds.dart.textual_outline.expect
new file mode 100644
index 0000000..fe2d23d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/bounds.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+extension Extension1<T extends Object> (){}
+on T (){}
+extension Extension2<T extends String> (){}
+on T (){}
+extension Extension3<T extends dynamic> (){}
+on T (){}
+extension Extension4<T> (){}
+on T (){}
+main() {}
diff --git a/pkg/front_end/testcases/extensions/check_bounds.dart.outline.expect b/pkg/front_end/testcases/extensions/check_bounds.dart.outline.expect
index 918d9dd..1a72e8b 100644
--- a/pkg/front_end/testcases/extensions/check_bounds.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/check_bounds.dart.outline.expect
@@ -35,7 +35,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-extension Extension<T extends self::B* = dynamic> on self::Class<T*>* {
+extension Extension<T extends self::B* = self::B*> on self::Class<T*>* {
   method method = self::Extension|method;
   tearoff method = self::Extension|get#method;
   method genericMethod = self::Extension|genericMethod;
@@ -73,14 +73,14 @@
 static final field dynamic field27;
 static final field dynamic field28;
 static final field dynamic field29;
-static method Extension|method<T extends self::B* = dynamic>(final self::Class<self::Extension|method::T*>* #this) → dynamic
+static method Extension|method<T extends self::B* = self::B*>(final self::Class<self::Extension|method::T*>* #this) → dynamic
   ;
-static method Extension|get#method<T extends self::B* = dynamic>(final self::Class<self::Extension|get#method::T*>* #this) → () →* dynamic
+static method Extension|get#method<T extends self::B* = self::B*>(final self::Class<self::Extension|get#method::T*>* #this) → () →* dynamic
   return () → dynamic => self::Extension|method<self::Extension|get#method::T*>(#this);
-static method Extension|genericMethod<T extends self::B* = dynamic, S extends self::B* = dynamic>(final self::Class<self::Extension|genericMethod::T*>* #this, self::Extension|genericMethod::S* s) → dynamic
+static method Extension|genericMethod<T extends self::B* = self::B*, S extends self::B* = self::B*>(final self::Class<self::Extension|genericMethod::T*>* #this, self::Extension|genericMethod::S* s) → dynamic
   ;
-static method Extension|get#genericMethod<T extends self::B* = dynamic>(final self::Class<self::Extension|get#genericMethod::T*>* #this) → <S extends self::B* = dynamic>(S*) →* dynamic
-  return <S extends self::B* = dynamic>(S* s) → dynamic => self::Extension|genericMethod<self::Extension|get#genericMethod::T*, S*>(#this, s);
+static method Extension|get#genericMethod<T extends self::B* = self::B*>(final self::Class<self::Extension|get#genericMethod::T*>* #this) → <S extends self::B* = self::B*>(S*) →* dynamic
+  return <S extends self::B* = self::B*>(S* s) → dynamic => self::Extension|genericMethod<self::Extension|get#genericMethod::T*, S*>(#this, s);
 static method main() → dynamic
   ;
 static method test() → dynamic
diff --git a/pkg/front_end/testcases/extensions/check_bounds.dart.strong.expect b/pkg/front_end/testcases/extensions/check_bounds.dart.strong.expect
index 8591b1d..1d88a8a 100644
--- a/pkg/front_end/testcases/extensions/check_bounds.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/check_bounds.dart.strong.expect
@@ -842,7 +842,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-extension Extension<T extends self::B* = dynamic> on self::Class<T*>* {
+extension Extension<T extends self::B* = self::B*> on self::Class<T*>* {
   method method = self::Extension|method;
   tearoff method = self::Extension|get#method;
   method genericMethod = self::Extension|genericMethod;
@@ -885,12 +885,12 @@
 static final field dynamic field27 = self::Extension|genericMethod<self::B*, self::A*>(self::classB, self::a);
 static final field dynamic field28 = self::Extension|genericMethod<self::B*, self::A*>(self::classB, self::a);
 static final field dynamic field29 = self::Extension|genericMethod<self::B*, self::B*>(self::classB, self::a as{TypeError} self::B*);
-static method Extension|method<T extends self::B* = dynamic>(final self::Class<self::Extension|method::T*>* #this) → dynamic {}
-static method Extension|get#method<T extends self::B* = dynamic>(final self::Class<self::Extension|get#method::T*>* #this) → () →* dynamic
+static method Extension|method<T extends self::B* = self::B*>(final self::Class<self::Extension|method::T*>* #this) → dynamic {}
+static method Extension|get#method<T extends self::B* = self::B*>(final self::Class<self::Extension|get#method::T*>* #this) → () →* dynamic
   return () → dynamic => self::Extension|method<self::Extension|get#method::T*>(#this);
-static method Extension|genericMethod<T extends self::B* = dynamic, S extends self::B* = dynamic>(final self::Class<self::Extension|genericMethod::T*>* #this, self::Extension|genericMethod::S* s) → dynamic {}
-static method Extension|get#genericMethod<T extends self::B* = dynamic>(final self::Class<self::Extension|get#genericMethod::T*>* #this) → <S extends self::B* = dynamic>(S*) →* dynamic
-  return <S extends self::B* = dynamic>(S* s) → dynamic => self::Extension|genericMethod<self::Extension|get#genericMethod::T*, S*>(#this, s);
+static method Extension|genericMethod<T extends self::B* = self::B*, S extends self::B* = self::B*>(final self::Class<self::Extension|genericMethod::T*>* #this, self::Extension|genericMethod::S* s) → dynamic {}
+static method Extension|get#genericMethod<T extends self::B* = self::B*>(final self::Class<self::Extension|get#genericMethod::T*>* #this) → <S extends self::B* = self::B*>(S*) →* dynamic
+  return <S extends self::B* = self::B*>(S* s) → dynamic => self::Extension|genericMethod<self::Extension|get#genericMethod::T*, S*>(#this, s);
 static method main() → dynamic {}
 static method test() → dynamic {
   self::A* a;
diff --git a/pkg/front_end/testcases/extensions/check_bounds.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/check_bounds.dart.strong.transformed.expect
index 8591b1d..1d88a8a 100644
--- a/pkg/front_end/testcases/extensions/check_bounds.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/check_bounds.dart.strong.transformed.expect
@@ -842,7 +842,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-extension Extension<T extends self::B* = dynamic> on self::Class<T*>* {
+extension Extension<T extends self::B* = self::B*> on self::Class<T*>* {
   method method = self::Extension|method;
   tearoff method = self::Extension|get#method;
   method genericMethod = self::Extension|genericMethod;
@@ -885,12 +885,12 @@
 static final field dynamic field27 = self::Extension|genericMethod<self::B*, self::A*>(self::classB, self::a);
 static final field dynamic field28 = self::Extension|genericMethod<self::B*, self::A*>(self::classB, self::a);
 static final field dynamic field29 = self::Extension|genericMethod<self::B*, self::B*>(self::classB, self::a as{TypeError} self::B*);
-static method Extension|method<T extends self::B* = dynamic>(final self::Class<self::Extension|method::T*>* #this) → dynamic {}
-static method Extension|get#method<T extends self::B* = dynamic>(final self::Class<self::Extension|get#method::T*>* #this) → () →* dynamic
+static method Extension|method<T extends self::B* = self::B*>(final self::Class<self::Extension|method::T*>* #this) → dynamic {}
+static method Extension|get#method<T extends self::B* = self::B*>(final self::Class<self::Extension|get#method::T*>* #this) → () →* dynamic
   return () → dynamic => self::Extension|method<self::Extension|get#method::T*>(#this);
-static method Extension|genericMethod<T extends self::B* = dynamic, S extends self::B* = dynamic>(final self::Class<self::Extension|genericMethod::T*>* #this, self::Extension|genericMethod::S* s) → dynamic {}
-static method Extension|get#genericMethod<T extends self::B* = dynamic>(final self::Class<self::Extension|get#genericMethod::T*>* #this) → <S extends self::B* = dynamic>(S*) →* dynamic
-  return <S extends self::B* = dynamic>(S* s) → dynamic => self::Extension|genericMethod<self::Extension|get#genericMethod::T*, S*>(#this, s);
+static method Extension|genericMethod<T extends self::B* = self::B*, S extends self::B* = self::B*>(final self::Class<self::Extension|genericMethod::T*>* #this, self::Extension|genericMethod::S* s) → dynamic {}
+static method Extension|get#genericMethod<T extends self::B* = self::B*>(final self::Class<self::Extension|get#genericMethod::T*>* #this) → <S extends self::B* = self::B*>(S*) →* dynamic
+  return <S extends self::B* = self::B*>(S* s) → dynamic => self::Extension|genericMethod<self::Extension|get#genericMethod::T*, S*>(#this, s);
 static method main() → dynamic {}
 static method test() → dynamic {
   self::A* a;
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.outline.expect b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.outline.expect
index d9ab5bc..293f3df 100644
--- a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.outline.expect
@@ -42,10 +42,10 @@
   ;
 static method Extension1|get#method(final self::Class* #this) → () →* core::int*
   return () → core::int* => self::Extension1|method(#this);
-static method Extension1|genericMethod<T extends core::num* = dynamic>(final self::Class* #this, self::Extension1|genericMethod::T* t) → core::int*
+static method Extension1|genericMethod<T extends core::num* = core::num*>(final self::Class* #this, self::Extension1|genericMethod::T* t) → core::int*
   ;
-static method Extension1|get#genericMethod(final self::Class* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
+static method Extension1|get#genericMethod(final self::Class* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
 static method Extension2|get#field(final self::Class* #this) → core::int*
   ;
 static method Extension2|set#field(final self::Class* #this, core::int* value) → void
@@ -54,10 +54,10 @@
   ;
 static method Extension2|get#method(final self::Class* #this) → () →* core::int*
   return () → core::int* => self::Extension2|method(#this);
-static method Extension2|genericMethod<T extends core::num* = dynamic>(final self::Class* #this, self::Extension2|genericMethod::T* t) → core::int*
+static method Extension2|genericMethod<T extends core::num* = core::num*>(final self::Class* #this, self::Extension2|genericMethod::T* t) → core::int*
   ;
-static method Extension2|get#genericMethod(final self::Class* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
+static method Extension2|get#genericMethod(final self::Class* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
 static method main() → dynamic
   ;
 static method expect(dynamic expected, dynamic actual) → dynamic
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.expect b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.expect
index 832f745..1de117d 100644
--- a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.expect
@@ -44,10 +44,10 @@
   return #this.{self::Class::field1};
 static method Extension1|get#method(final self::Class* #this) → () →* core::int*
   return () → core::int* => self::Extension1|method(#this);
-static method Extension1|genericMethod<T extends core::num* = dynamic>(final self::Class* #this, self::Extension1|genericMethod::T* t) → core::int*
+static method Extension1|genericMethod<T extends core::num* = core::num*>(final self::Class* #this, self::Extension1|genericMethod::T* t) → core::int*
   return #this.{self::Class::field1}.{core::num::+}(t) as{TypeError} core::int*;
-static method Extension1|get#genericMethod(final self::Class* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
+static method Extension1|get#genericMethod(final self::Class* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
 static method Extension2|get#field(final self::Class* #this) → core::int*
   return #this.{self::Class::field2};
 static method Extension2|set#field(final self::Class* #this, core::int* value) → void {
@@ -57,10 +57,10 @@
   return #this.{self::Class::field2};
 static method Extension2|get#method(final self::Class* #this) → () →* core::int*
   return () → core::int* => self::Extension2|method(#this);
-static method Extension2|genericMethod<T extends core::num* = dynamic>(final self::Class* #this, self::Extension2|genericMethod::T* t) → core::int*
+static method Extension2|genericMethod<T extends core::num* = core::num*>(final self::Class* #this, self::Extension2|genericMethod::T* t) → core::int*
   return #this.{self::Class::field2}.{core::num::+}(t) as{TypeError} core::int*;
-static method Extension2|get#genericMethod(final self::Class* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
+static method Extension2|get#genericMethod(final self::Class* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
 static method main() → dynamic {
   self::Class* c = new self::Class::•();
   self::expect(42, self::Extension1|get#field(c));
@@ -75,8 +75,8 @@
   self::expect(97, self::Extension2|genericMethod<core::int*>(c, 10));
   self::expect(52, self::Extension1|genericMethod<core::num*>(c, 10));
   self::expect(97, self::Extension2|genericMethod<core::num*>(c, 10));
-  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff1 = self::Extension1|get#genericMethod(c);
-  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff2 = self::Extension2|get#genericMethod(c);
+  <T extends core::num* = core::num*>(T*) →* core::int* genericTearOff1 = self::Extension1|get#genericMethod(c);
+  <T extends core::num* = core::num*>(T*) →* core::int* genericTearOff2 = self::Extension2|get#genericMethod(c);
   self::expect(52, genericTearOff1.call<core::int*>(10));
   self::expect(97, genericTearOff2.call<core::int*>(10));
   self::expect(52, genericTearOff1.call<core::num*>(10));
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.transformed.expect
index 832f745..1de117d 100644
--- a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.transformed.expect
@@ -44,10 +44,10 @@
   return #this.{self::Class::field1};
 static method Extension1|get#method(final self::Class* #this) → () →* core::int*
   return () → core::int* => self::Extension1|method(#this);
-static method Extension1|genericMethod<T extends core::num* = dynamic>(final self::Class* #this, self::Extension1|genericMethod::T* t) → core::int*
+static method Extension1|genericMethod<T extends core::num* = core::num*>(final self::Class* #this, self::Extension1|genericMethod::T* t) → core::int*
   return #this.{self::Class::field1}.{core::num::+}(t) as{TypeError} core::int*;
-static method Extension1|get#genericMethod(final self::Class* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
+static method Extension1|get#genericMethod(final self::Class* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
 static method Extension2|get#field(final self::Class* #this) → core::int*
   return #this.{self::Class::field2};
 static method Extension2|set#field(final self::Class* #this, core::int* value) → void {
@@ -57,10 +57,10 @@
   return #this.{self::Class::field2};
 static method Extension2|get#method(final self::Class* #this) → () →* core::int*
   return () → core::int* => self::Extension2|method(#this);
-static method Extension2|genericMethod<T extends core::num* = dynamic>(final self::Class* #this, self::Extension2|genericMethod::T* t) → core::int*
+static method Extension2|genericMethod<T extends core::num* = core::num*>(final self::Class* #this, self::Extension2|genericMethod::T* t) → core::int*
   return #this.{self::Class::field2}.{core::num::+}(t) as{TypeError} core::int*;
-static method Extension2|get#genericMethod(final self::Class* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
+static method Extension2|get#genericMethod(final self::Class* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
 static method main() → dynamic {
   self::Class* c = new self::Class::•();
   self::expect(42, self::Extension1|get#field(c));
@@ -75,8 +75,8 @@
   self::expect(97, self::Extension2|genericMethod<core::int*>(c, 10));
   self::expect(52, self::Extension1|genericMethod<core::num*>(c, 10));
   self::expect(97, self::Extension2|genericMethod<core::num*>(c, 10));
-  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff1 = self::Extension1|get#genericMethod(c);
-  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff2 = self::Extension2|get#genericMethod(c);
+  <T extends core::num* = core::num*>(T*) →* core::int* genericTearOff1 = self::Extension1|get#genericMethod(c);
+  <T extends core::num* = core::num*>(T*) →* core::int* genericTearOff2 = self::Extension2|get#genericMethod(c);
   self::expect(52, genericTearOff1.call<core::int*>(10));
   self::expect(97, genericTearOff2.call<core::int*>(10));
   self::expect(52, genericTearOff1.call<core::num*>(10));
diff --git a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.outline.expect b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.outline.expect
index dc566af..c63ea7d 100644
--- a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.outline.expect
@@ -18,7 +18,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-extension Extension1<T extends core::num* = dynamic> on self::Class<T*>* {
+extension Extension1<T extends core::num* = core::num*> on self::Class<T*>* {
   static field latestType = self::Extension1|latestType;
   get field = self::Extension1|get#field;
   method method = self::Extension1|method;
@@ -27,7 +27,7 @@
   tearoff genericMethod = self::Extension1|get#genericMethod;
   set field = self::Extension1|set#field;
 }
-extension Extension2<T extends core::num* = dynamic> on self::Class<T*>* {
+extension Extension2<T extends core::num* = core::num*> on self::Class<T*>* {
   get field = self::Extension2|get#field;
   method method = self::Extension2|method;
   tearoff method = self::Extension2|get#method;
@@ -36,30 +36,30 @@
   set field = self::Extension2|set#field;
 }
 static field core::String* Extension1|latestType;
-static method Extension1|get#field<T extends core::num* = dynamic>(final self::Class<self::Extension1|get#field::T*>* #this) → self::Extension1|get#field::T*
+static method Extension1|get#field<T extends core::num* = core::num*>(final self::Class<self::Extension1|get#field::T*>* #this) → self::Extension1|get#field::T*
   ;
-static method Extension1|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension1|set#field::T*>* #this, self::Extension1|set#field::T* value) → void
+static method Extension1|set#field<T extends core::num* = core::num*>(final self::Class<self::Extension1|set#field::T*>* #this, self::Extension1|set#field::T* value) → void
   ;
-static method Extension1|method<T extends core::num* = dynamic>(final self::Class<self::Extension1|method::T*>* #this) → self::Extension1|method::T*
+static method Extension1|method<T extends core::num* = core::num*>(final self::Class<self::Extension1|method::T*>* #this) → self::Extension1|method::T*
   ;
-static method Extension1|get#method<T extends core::num* = dynamic>(final self::Class<self::Extension1|get#method::T*>* #this) → () →* self::Extension1|get#method::T*
+static method Extension1|get#method<T extends core::num* = core::num*>(final self::Class<self::Extension1|get#method::T*>* #this) → () →* self::Extension1|get#method::T*
   return () → self::Extension1|get#method::T* => self::Extension1|method<self::Extension1|get#method::T*>(#this);
-static method Extension1|genericMethod<T extends core::num* = dynamic, S extends core::num* = dynamic>(final self::Class<self::Extension1|genericMethod::T*>* #this, self::Extension1|genericMethod::S* t) → self::Extension1|genericMethod::T*
+static method Extension1|genericMethod<T extends core::num* = core::num*, S extends core::num* = core::num*>(final self::Class<self::Extension1|genericMethod::T*>* #this, self::Extension1|genericMethod::S* t) → self::Extension1|genericMethod::T*
   ;
-static method Extension1|get#genericMethod<T extends core::num* = dynamic>(final self::Class<self::Extension1|get#genericMethod::T*>* #this) → <S extends core::num* = dynamic>(S*) →* self::Extension1|get#genericMethod::T*
-  return <S extends core::num* = dynamic>(S* t) → self::Extension1|get#genericMethod::T* => self::Extension1|genericMethod<self::Extension1|get#genericMethod::T*, S*>(#this, t);
-static method Extension2|get#field<T extends core::num* = dynamic>(final self::Class<self::Extension2|get#field::T*>* #this) → self::Extension2|get#field::T*
+static method Extension1|get#genericMethod<T extends core::num* = core::num*>(final self::Class<self::Extension1|get#genericMethod::T*>* #this) → <S extends core::num* = core::num*>(S*) →* self::Extension1|get#genericMethod::T*
+  return <S extends core::num* = core::num*>(S* t) → self::Extension1|get#genericMethod::T* => self::Extension1|genericMethod<self::Extension1|get#genericMethod::T*, S*>(#this, t);
+static method Extension2|get#field<T extends core::num* = core::num*>(final self::Class<self::Extension2|get#field::T*>* #this) → self::Extension2|get#field::T*
   ;
-static method Extension2|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension2|set#field::T*>* #this, self::Extension2|set#field::T* value) → void
+static method Extension2|set#field<T extends core::num* = core::num*>(final self::Class<self::Extension2|set#field::T*>* #this, self::Extension2|set#field::T* value) → void
   ;
-static method Extension2|method<T extends core::num* = dynamic>(final self::Class<self::Extension2|method::T*>* #this) → self::Extension2|method::T*
+static method Extension2|method<T extends core::num* = core::num*>(final self::Class<self::Extension2|method::T*>* #this) → self::Extension2|method::T*
   ;
-static method Extension2|get#method<T extends core::num* = dynamic>(final self::Class<self::Extension2|get#method::T*>* #this) → () →* self::Extension2|get#method::T*
+static method Extension2|get#method<T extends core::num* = core::num*>(final self::Class<self::Extension2|get#method::T*>* #this) → () →* self::Extension2|get#method::T*
   return () → self::Extension2|get#method::T* => self::Extension2|method<self::Extension2|get#method::T*>(#this);
-static method Extension2|genericMethod<T extends core::num* = dynamic, S extends core::num* = dynamic>(final self::Class<self::Extension2|genericMethod::T*>* #this, self::Extension2|genericMethod::S* t) → self::Extension2|genericMethod::T*
+static method Extension2|genericMethod<T extends core::num* = core::num*, S extends core::num* = core::num*>(final self::Class<self::Extension2|genericMethod::T*>* #this, self::Extension2|genericMethod::S* t) → self::Extension2|genericMethod::T*
   ;
-static method Extension2|get#genericMethod<T extends core::num* = dynamic>(final self::Class<self::Extension2|get#genericMethod::T*>* #this) → <S extends core::num* = dynamic>(S*) →* self::Extension2|get#genericMethod::T*
-  return <S extends core::num* = dynamic>(S* t) → self::Extension2|get#genericMethod::T* => self::Extension2|genericMethod<self::Extension2|get#genericMethod::T*, S*>(#this, t);
+static method Extension2|get#genericMethod<T extends core::num* = core::num*>(final self::Class<self::Extension2|get#genericMethod::T*>* #this) → <S extends core::num* = core::num*>(S*) →* self::Extension2|get#genericMethod::T*
+  return <S extends core::num* = core::num*>(S* t) → self::Extension2|get#genericMethod::T* => self::Extension2|genericMethod<self::Extension2|get#genericMethod::T*, S*>(#this, t);
 static method main() → dynamic
   ;
 static method expect(dynamic expected, dynamic actual) → dynamic
diff --git a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.expect b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.expect
index a876381..adc49e4 100644
--- a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.expect
@@ -19,7 +19,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-extension Extension1<T extends core::num* = dynamic> on self::Class<T*>* {
+extension Extension1<T extends core::num* = core::num*> on self::Class<T*>* {
   static field latestType = self::Extension1|latestType;
   get field = self::Extension1|get#field;
   method method = self::Extension1|method;
@@ -28,7 +28,7 @@
   tearoff genericMethod = self::Extension1|get#genericMethod;
   set field = self::Extension1|set#field;
 }
-extension Extension2<T extends core::num* = dynamic> on self::Class<T*>* {
+extension Extension2<T extends core::num* = core::num*> on self::Class<T*>* {
   get field = self::Extension2|get#field;
   method method = self::Extension2|method;
   tearoff method = self::Extension2|get#method;
@@ -37,39 +37,39 @@
   set field = self::Extension2|set#field;
 }
 static field core::String* Extension1|latestType;
-static method Extension1|get#field<T extends core::num* = dynamic>(final self::Class<self::Extension1|get#field::T*>* #this) → self::Extension1|get#field::T* {
+static method Extension1|get#field<T extends core::num* = core::num*>(final self::Class<self::Extension1|get#field::T*>* #this) → self::Extension1|get#field::T* {
   self::Extension1|latestType = "${self::Extension1|get#field::T*}";
   return #this.{self::Class::field1};
 }
-static method Extension1|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension1|set#field::T*>* #this, self::Extension1|set#field::T* value) → void {
+static method Extension1|set#field<T extends core::num* = core::num*>(final self::Class<self::Extension1|set#field::T*>* #this, self::Extension1|set#field::T* value) → void {
   self::Extension1|latestType = "${self::Extension1|set#field::T*}";
   #this.{self::Class::field1} = value;
 }
-static method Extension1|method<T extends core::num* = dynamic>(final self::Class<self::Extension1|method::T*>* #this) → self::Extension1|method::T* {
+static method Extension1|method<T extends core::num* = core::num*>(final self::Class<self::Extension1|method::T*>* #this) → self::Extension1|method::T* {
   self::Extension1|latestType = "${self::Extension1|method::T*}";
   return #this.{self::Class::field1};
 }
-static method Extension1|get#method<T extends core::num* = dynamic>(final self::Class<self::Extension1|get#method::T*>* #this) → () →* self::Extension1|get#method::T*
+static method Extension1|get#method<T extends core::num* = core::num*>(final self::Class<self::Extension1|get#method::T*>* #this) → () →* self::Extension1|get#method::T*
   return () → self::Extension1|get#method::T* => self::Extension1|method<self::Extension1|get#method::T*>(#this);
-static method Extension1|genericMethod<T extends core::num* = dynamic, S extends core::num* = dynamic>(final self::Class<self::Extension1|genericMethod::T*>* #this, self::Extension1|genericMethod::S* t) → self::Extension1|genericMethod::T* {
+static method Extension1|genericMethod<T extends core::num* = core::num*, S extends core::num* = core::num*>(final self::Class<self::Extension1|genericMethod::T*>* #this, self::Extension1|genericMethod::S* t) → self::Extension1|genericMethod::T* {
   self::Extension1|latestType = "${self::Extension1|genericMethod::T*}:${self::Extension1|genericMethod::S*}";
   return #this.{self::Class::field1}.{core::num::+}(t) as{TypeError} self::Extension1|genericMethod::T*;
 }
-static method Extension1|get#genericMethod<T extends core::num* = dynamic>(final self::Class<self::Extension1|get#genericMethod::T*>* #this) → <S extends core::num* = dynamic>(S*) →* self::Extension1|get#genericMethod::T*
-  return <S extends core::num* = dynamic>(S* t) → self::Extension1|get#genericMethod::T* => self::Extension1|genericMethod<self::Extension1|get#genericMethod::T*, S*>(#this, t);
-static method Extension2|get#field<T extends core::num* = dynamic>(final self::Class<self::Extension2|get#field::T*>* #this) → self::Extension2|get#field::T*
+static method Extension1|get#genericMethod<T extends core::num* = core::num*>(final self::Class<self::Extension1|get#genericMethod::T*>* #this) → <S extends core::num* = core::num*>(S*) →* self::Extension1|get#genericMethod::T*
+  return <S extends core::num* = core::num*>(S* t) → self::Extension1|get#genericMethod::T* => self::Extension1|genericMethod<self::Extension1|get#genericMethod::T*, S*>(#this, t);
+static method Extension2|get#field<T extends core::num* = core::num*>(final self::Class<self::Extension2|get#field::T*>* #this) → self::Extension2|get#field::T*
   return #this.{self::Class::field2};
-static method Extension2|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension2|set#field::T*>* #this, self::Extension2|set#field::T* value) → void {
+static method Extension2|set#field<T extends core::num* = core::num*>(final self::Class<self::Extension2|set#field::T*>* #this, self::Extension2|set#field::T* value) → void {
   #this.{self::Class::field2} = value;
 }
-static method Extension2|method<T extends core::num* = dynamic>(final self::Class<self::Extension2|method::T*>* #this) → self::Extension2|method::T*
+static method Extension2|method<T extends core::num* = core::num*>(final self::Class<self::Extension2|method::T*>* #this) → self::Extension2|method::T*
   return #this.{self::Class::field2};
-static method Extension2|get#method<T extends core::num* = dynamic>(final self::Class<self::Extension2|get#method::T*>* #this) → () →* self::Extension2|get#method::T*
+static method Extension2|get#method<T extends core::num* = core::num*>(final self::Class<self::Extension2|get#method::T*>* #this) → () →* self::Extension2|get#method::T*
   return () → self::Extension2|get#method::T* => self::Extension2|method<self::Extension2|get#method::T*>(#this);
-static method Extension2|genericMethod<T extends core::num* = dynamic, S extends core::num* = dynamic>(final self::Class<self::Extension2|genericMethod::T*>* #this, self::Extension2|genericMethod::S* t) → self::Extension2|genericMethod::T*
+static method Extension2|genericMethod<T extends core::num* = core::num*, S extends core::num* = core::num*>(final self::Class<self::Extension2|genericMethod::T*>* #this, self::Extension2|genericMethod::S* t) → self::Extension2|genericMethod::T*
   return #this.{self::Class::field2}.{core::num::+}(t) as{TypeError} self::Extension2|genericMethod::T*;
-static method Extension2|get#genericMethod<T extends core::num* = dynamic>(final self::Class<self::Extension2|get#genericMethod::T*>* #this) → <S extends core::num* = dynamic>(S*) →* self::Extension2|get#genericMethod::T*
-  return <S extends core::num* = dynamic>(S* t) → self::Extension2|get#genericMethod::T* => self::Extension2|genericMethod<self::Extension2|get#genericMethod::T*, S*>(#this, t);
+static method Extension2|get#genericMethod<T extends core::num* = core::num*>(final self::Class<self::Extension2|get#genericMethod::T*>* #this) → <S extends core::num* = core::num*>(S*) →* self::Extension2|get#genericMethod::T*
+  return <S extends core::num* = core::num*>(S* t) → self::Extension2|get#genericMethod::T* => self::Extension2|genericMethod<self::Extension2|get#genericMethod::T*, S*>(#this, t);
 static method main() → dynamic {
   self::Class<core::int*>* c = new self::Class::•<core::int*>(42, 87);
   self::expect(42, self::Extension1|get#field<core::num*>(c));
@@ -106,9 +106,9 @@
   self::expect("int:num", self::Extension1|latestType);
   self::expect(52, self::Extension1|genericMethod<core::int*, core::int*>(c, 10));
   self::expect("int:int", self::Extension1|latestType);
-  <S extends core::num* = dynamic>(S*) →* core::num* genericTearOffNumber1 = self::Extension1|get#genericMethod<core::num*>(c);
-  <S extends core::num* = dynamic>(S*) →* core::int* genericTearOffInteger1 = self::Extension1|get#genericMethod<core::int*>(c);
-  <S extends core::num* = dynamic>(S*) →* core::num* genericTearOff2 = self::Extension2|get#genericMethod<core::num*>(c);
+  <S extends core::num* = core::num*>(S*) →* core::num* genericTearOffNumber1 = self::Extension1|get#genericMethod<core::num*>(c);
+  <S extends core::num* = core::num*>(S*) →* core::int* genericTearOffInteger1 = self::Extension1|get#genericMethod<core::int*>(c);
+  <S extends core::num* = core::num*>(S*) →* core::num* genericTearOff2 = self::Extension2|get#genericMethod<core::num*>(c);
   self::expect(52, genericTearOffNumber1.call<core::int*>(10));
   self::expect("num:int", self::Extension1|latestType);
   self::expect(52, genericTearOffInteger1.call<core::int*>(10));
diff --git a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.transformed.expect
index a876381..adc49e4 100644
--- a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.transformed.expect
@@ -19,7 +19,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-extension Extension1<T extends core::num* = dynamic> on self::Class<T*>* {
+extension Extension1<T extends core::num* = core::num*> on self::Class<T*>* {
   static field latestType = self::Extension1|latestType;
   get field = self::Extension1|get#field;
   method method = self::Extension1|method;
@@ -28,7 +28,7 @@
   tearoff genericMethod = self::Extension1|get#genericMethod;
   set field = self::Extension1|set#field;
 }
-extension Extension2<T extends core::num* = dynamic> on self::Class<T*>* {
+extension Extension2<T extends core::num* = core::num*> on self::Class<T*>* {
   get field = self::Extension2|get#field;
   method method = self::Extension2|method;
   tearoff method = self::Extension2|get#method;
@@ -37,39 +37,39 @@
   set field = self::Extension2|set#field;
 }
 static field core::String* Extension1|latestType;
-static method Extension1|get#field<T extends core::num* = dynamic>(final self::Class<self::Extension1|get#field::T*>* #this) → self::Extension1|get#field::T* {
+static method Extension1|get#field<T extends core::num* = core::num*>(final self::Class<self::Extension1|get#field::T*>* #this) → self::Extension1|get#field::T* {
   self::Extension1|latestType = "${self::Extension1|get#field::T*}";
   return #this.{self::Class::field1};
 }
-static method Extension1|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension1|set#field::T*>* #this, self::Extension1|set#field::T* value) → void {
+static method Extension1|set#field<T extends core::num* = core::num*>(final self::Class<self::Extension1|set#field::T*>* #this, self::Extension1|set#field::T* value) → void {
   self::Extension1|latestType = "${self::Extension1|set#field::T*}";
   #this.{self::Class::field1} = value;
 }
-static method Extension1|method<T extends core::num* = dynamic>(final self::Class<self::Extension1|method::T*>* #this) → self::Extension1|method::T* {
+static method Extension1|method<T extends core::num* = core::num*>(final self::Class<self::Extension1|method::T*>* #this) → self::Extension1|method::T* {
   self::Extension1|latestType = "${self::Extension1|method::T*}";
   return #this.{self::Class::field1};
 }
-static method Extension1|get#method<T extends core::num* = dynamic>(final self::Class<self::Extension1|get#method::T*>* #this) → () →* self::Extension1|get#method::T*
+static method Extension1|get#method<T extends core::num* = core::num*>(final self::Class<self::Extension1|get#method::T*>* #this) → () →* self::Extension1|get#method::T*
   return () → self::Extension1|get#method::T* => self::Extension1|method<self::Extension1|get#method::T*>(#this);
-static method Extension1|genericMethod<T extends core::num* = dynamic, S extends core::num* = dynamic>(final self::Class<self::Extension1|genericMethod::T*>* #this, self::Extension1|genericMethod::S* t) → self::Extension1|genericMethod::T* {
+static method Extension1|genericMethod<T extends core::num* = core::num*, S extends core::num* = core::num*>(final self::Class<self::Extension1|genericMethod::T*>* #this, self::Extension1|genericMethod::S* t) → self::Extension1|genericMethod::T* {
   self::Extension1|latestType = "${self::Extension1|genericMethod::T*}:${self::Extension1|genericMethod::S*}";
   return #this.{self::Class::field1}.{core::num::+}(t) as{TypeError} self::Extension1|genericMethod::T*;
 }
-static method Extension1|get#genericMethod<T extends core::num* = dynamic>(final self::Class<self::Extension1|get#genericMethod::T*>* #this) → <S extends core::num* = dynamic>(S*) →* self::Extension1|get#genericMethod::T*
-  return <S extends core::num* = dynamic>(S* t) → self::Extension1|get#genericMethod::T* => self::Extension1|genericMethod<self::Extension1|get#genericMethod::T*, S*>(#this, t);
-static method Extension2|get#field<T extends core::num* = dynamic>(final self::Class<self::Extension2|get#field::T*>* #this) → self::Extension2|get#field::T*
+static method Extension1|get#genericMethod<T extends core::num* = core::num*>(final self::Class<self::Extension1|get#genericMethod::T*>* #this) → <S extends core::num* = core::num*>(S*) →* self::Extension1|get#genericMethod::T*
+  return <S extends core::num* = core::num*>(S* t) → self::Extension1|get#genericMethod::T* => self::Extension1|genericMethod<self::Extension1|get#genericMethod::T*, S*>(#this, t);
+static method Extension2|get#field<T extends core::num* = core::num*>(final self::Class<self::Extension2|get#field::T*>* #this) → self::Extension2|get#field::T*
   return #this.{self::Class::field2};
-static method Extension2|set#field<T extends core::num* = dynamic>(final self::Class<self::Extension2|set#field::T*>* #this, self::Extension2|set#field::T* value) → void {
+static method Extension2|set#field<T extends core::num* = core::num*>(final self::Class<self::Extension2|set#field::T*>* #this, self::Extension2|set#field::T* value) → void {
   #this.{self::Class::field2} = value;
 }
-static method Extension2|method<T extends core::num* = dynamic>(final self::Class<self::Extension2|method::T*>* #this) → self::Extension2|method::T*
+static method Extension2|method<T extends core::num* = core::num*>(final self::Class<self::Extension2|method::T*>* #this) → self::Extension2|method::T*
   return #this.{self::Class::field2};
-static method Extension2|get#method<T extends core::num* = dynamic>(final self::Class<self::Extension2|get#method::T*>* #this) → () →* self::Extension2|get#method::T*
+static method Extension2|get#method<T extends core::num* = core::num*>(final self::Class<self::Extension2|get#method::T*>* #this) → () →* self::Extension2|get#method::T*
   return () → self::Extension2|get#method::T* => self::Extension2|method<self::Extension2|get#method::T*>(#this);
-static method Extension2|genericMethod<T extends core::num* = dynamic, S extends core::num* = dynamic>(final self::Class<self::Extension2|genericMethod::T*>* #this, self::Extension2|genericMethod::S* t) → self::Extension2|genericMethod::T*
+static method Extension2|genericMethod<T extends core::num* = core::num*, S extends core::num* = core::num*>(final self::Class<self::Extension2|genericMethod::T*>* #this, self::Extension2|genericMethod::S* t) → self::Extension2|genericMethod::T*
   return #this.{self::Class::field2}.{core::num::+}(t) as{TypeError} self::Extension2|genericMethod::T*;
-static method Extension2|get#genericMethod<T extends core::num* = dynamic>(final self::Class<self::Extension2|get#genericMethod::T*>* #this) → <S extends core::num* = dynamic>(S*) →* self::Extension2|get#genericMethod::T*
-  return <S extends core::num* = dynamic>(S* t) → self::Extension2|get#genericMethod::T* => self::Extension2|genericMethod<self::Extension2|get#genericMethod::T*, S*>(#this, t);
+static method Extension2|get#genericMethod<T extends core::num* = core::num*>(final self::Class<self::Extension2|get#genericMethod::T*>* #this) → <S extends core::num* = core::num*>(S*) →* self::Extension2|get#genericMethod::T*
+  return <S extends core::num* = core::num*>(S* t) → self::Extension2|get#genericMethod::T* => self::Extension2|genericMethod<self::Extension2|get#genericMethod::T*, S*>(#this, t);
 static method main() → dynamic {
   self::Class<core::int*>* c = new self::Class::•<core::int*>(42, 87);
   self::expect(42, self::Extension1|get#field<core::num*>(c));
@@ -106,9 +106,9 @@
   self::expect("int:num", self::Extension1|latestType);
   self::expect(52, self::Extension1|genericMethod<core::int*, core::int*>(c, 10));
   self::expect("int:int", self::Extension1|latestType);
-  <S extends core::num* = dynamic>(S*) →* core::num* genericTearOffNumber1 = self::Extension1|get#genericMethod<core::num*>(c);
-  <S extends core::num* = dynamic>(S*) →* core::int* genericTearOffInteger1 = self::Extension1|get#genericMethod<core::int*>(c);
-  <S extends core::num* = dynamic>(S*) →* core::num* genericTearOff2 = self::Extension2|get#genericMethod<core::num*>(c);
+  <S extends core::num* = core::num*>(S*) →* core::num* genericTearOffNumber1 = self::Extension1|get#genericMethod<core::num*>(c);
+  <S extends core::num* = core::num*>(S*) →* core::int* genericTearOffInteger1 = self::Extension1|get#genericMethod<core::int*>(c);
+  <S extends core::num* = core::num*>(S*) →* core::num* genericTearOff2 = self::Extension2|get#genericMethod<core::num*>(c);
   self::expect(52, genericTearOffNumber1.call<core::int*>(10));
   self::expect("num:int", self::Extension1|latestType);
   self::expect(52, genericTearOffInteger1.call<core::int*>(10));
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart.outline.expect b/pkg/front_end/testcases/extensions/instance_access.dart.outline.expect
index 1be509f..7bdfef2 100644
--- a/pkg/front_end/testcases/extensions/instance_access.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/instance_access.dart.outline.expect
@@ -54,10 +54,10 @@
   ;
 static method Extension1|get#method(final self::Class1* #this) → () →* core::int*
   return () → core::int* => self::Extension1|method(#this);
-static method Extension1|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int*
+static method Extension1|genericMethod<T extends core::num* = core::num*>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int*
   ;
-static method Extension1|get#genericMethod(final self::Class1* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
+static method Extension1|get#genericMethod(final self::Class1* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
 static method Extension1|get#property(final self::Class1* #this) → core::int*
   ;
 static method Extension1|set#property(final self::Class1* #this, core::int* value) → void
@@ -66,10 +66,10 @@
   ;
 static method Extension2|get#method(final self::Class2* #this) → () →* core::int*
   return () → core::int* => self::Extension2|method(#this);
-static method Extension2|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int*
+static method Extension2|genericMethod<T extends core::num* = core::num*>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int*
   ;
-static method Extension2|get#genericMethod(final self::Class2* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
+static method Extension2|get#genericMethod(final self::Class2* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
 static method Extension2|get#property(final self::Class2* #this) → core::int*
   ;
 static method Extension2|set#property(final self::Class2* #this, core::int* value) → void
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart.strong.expect b/pkg/front_end/testcases/extensions/instance_access.dart.strong.expect
index c5b4aa7..ca462d0 100644
--- a/pkg/front_end/testcases/extensions/instance_access.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/instance_access.dart.strong.expect
@@ -58,12 +58,12 @@
 }
 static method Extension1|get#method(final self::Class1* #this) → () →* core::int*
   return () → core::int* => self::Extension1|method(#this);
-static method Extension1|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int* {
+static method Extension1|genericMethod<T extends core::num* = core::num*>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int* {
   core::print("Extension1.genericMethod<${self::Extension1|genericMethod::T*}>(${t}) on ${#this}");
   return #this.{self::Class1::field}.{core::num::+}(t) as{TypeError} core::int*;
 }
-static method Extension1|get#genericMethod(final self::Class1* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
+static method Extension1|get#genericMethod(final self::Class1* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
 static method Extension1|get#property(final self::Class1* #this) → core::int* {
   core::print("Extension1.property get on ${#this}");
   return #this.{self::Class1::field};
@@ -79,12 +79,12 @@
 }
 static method Extension2|get#method(final self::Class2* #this) → () →* core::int*
   return () → core::int* => self::Extension2|method(#this);
-static method Extension2|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int* {
+static method Extension2|genericMethod<T extends core::num* = core::num*>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int* {
   core::print("Extension2.genericMethod<${self::Extension2|genericMethod::T*}>(${t}) on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(t).{core::num::+}(4) as{TypeError} core::int*;
 }
-static method Extension2|get#genericMethod(final self::Class2* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
+static method Extension2|get#genericMethod(final self::Class2* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
 static method Extension2|get#property(final self::Class2* #this) → core::int* {
   core::print("Extension2.property get on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(5);
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect
index c5b4aa7..ca462d0 100644
--- a/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect
@@ -58,12 +58,12 @@
 }
 static method Extension1|get#method(final self::Class1* #this) → () →* core::int*
   return () → core::int* => self::Extension1|method(#this);
-static method Extension1|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int* {
+static method Extension1|genericMethod<T extends core::num* = core::num*>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int* {
   core::print("Extension1.genericMethod<${self::Extension1|genericMethod::T*}>(${t}) on ${#this}");
   return #this.{self::Class1::field}.{core::num::+}(t) as{TypeError} core::int*;
 }
-static method Extension1|get#genericMethod(final self::Class1* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
+static method Extension1|get#genericMethod(final self::Class1* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
 static method Extension1|get#property(final self::Class1* #this) → core::int* {
   core::print("Extension1.property get on ${#this}");
   return #this.{self::Class1::field};
@@ -79,12 +79,12 @@
 }
 static method Extension2|get#method(final self::Class2* #this) → () →* core::int*
   return () → core::int* => self::Extension2|method(#this);
-static method Extension2|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int* {
+static method Extension2|genericMethod<T extends core::num* = core::num*>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int* {
   core::print("Extension2.genericMethod<${self::Extension2|genericMethod::T*}>(${t}) on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(t).{core::num::+}(4) as{TypeError} core::int*;
 }
-static method Extension2|get#genericMethod(final self::Class2* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
+static method Extension2|get#genericMethod(final self::Class2* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
 static method Extension2|get#property(final self::Class2* #this) → core::int* {
   core::print("Extension2.property get on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(5);
diff --git a/pkg/front_end/testcases/extensions/instance_tearoff.dart.outline.expect b/pkg/front_end/testcases/extensions/instance_tearoff.dart.outline.expect
index 9e91236..08380b2 100644
--- a/pkg/front_end/testcases/extensions/instance_tearoff.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/instance_tearoff.dart.outline.expect
@@ -50,18 +50,18 @@
   ;
 static method Extension1|get#method(final self::Class1* #this) → () →* core::int*
   return () → core::int* => self::Extension1|method(#this);
-static method Extension1|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int*
+static method Extension1|genericMethod<T extends core::num* = core::num*>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int*
   ;
-static method Extension1|get#genericMethod(final self::Class1* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
+static method Extension1|get#genericMethod(final self::Class1* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
 static method Extension2|method(final self::Class2* #this) → core::int*
   ;
 static method Extension2|get#method(final self::Class2* #this) → () →* core::int*
   return () → core::int* => self::Extension2|method(#this);
-static method Extension2|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int*
+static method Extension2|genericMethod<T extends core::num* = core::num*>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int*
   ;
-static method Extension2|get#genericMethod(final self::Class2* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
+static method Extension2|get#genericMethod(final self::Class2* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
 static method main() → dynamic
   ;
 static method testExtension1() → dynamic
diff --git a/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.expect b/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.expect
index cea7116..9508bad 100644
--- a/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.expect
@@ -54,24 +54,24 @@
 }
 static method Extension1|get#method(final self::Class1* #this) → () →* core::int*
   return () → core::int* => self::Extension1|method(#this);
-static method Extension1|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int* {
+static method Extension1|genericMethod<T extends core::num* = core::num*>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int* {
   core::print("Extension1.genericMethod<${self::Extension1|genericMethod::T*}>(${t}) on ${#this}");
   return #this.{self::Class1::field}.{core::num::+}(t) as{TypeError} core::int*;
 }
-static method Extension1|get#genericMethod(final self::Class1* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
+static method Extension1|get#genericMethod(final self::Class1* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
 static method Extension2|method(final self::Class2* #this) → core::int* {
   core::print("Extension2.method on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(2);
 }
 static method Extension2|get#method(final self::Class2* #this) → () →* core::int*
   return () → core::int* => self::Extension2|method(#this);
-static method Extension2|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int* {
+static method Extension2|genericMethod<T extends core::num* = core::num*>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int* {
   core::print("Extension2.genericMethod<${self::Extension2|genericMethod::T*}>(${t}) on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(t).{core::num::+}(3) as{TypeError} core::int*;
 }
-static method Extension2|get#genericMethod(final self::Class2* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
+static method Extension2|get#genericMethod(final self::Class2* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
 static method main() → dynamic {
   self::testExtension1();
   self::testExtension2();
@@ -87,10 +87,10 @@
   self::expect(1, tearOff1.call());
   c1 = new self::Class1::•(7.{core::int::unary-}());
   self::expect(1, tearOff1.call());
-  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff0 = self::Extension1|get#genericMethod(c0);
+  <T extends core::num* = core::num*>(T*) →* core::int* genericTearOff0 = self::Extension1|get#genericMethod(c0);
   self::expect(38, genericTearOff0.call<core::int*>(42));
   self::expect(38, genericTearOff0.call<core::num*>(42));
-  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff1 = self::Extension1|get#genericMethod(c1);
+  <T extends core::num* = core::num*>(T*) →* core::int* genericTearOff1 = self::Extension1|get#genericMethod(c1);
   self::expect(35, genericTearOff1.call<core::int*>(42));
   self::expect(35, genericTearOff1.call<core::num*>(42));
 }
@@ -105,10 +105,10 @@
   self::expect(3, tearOff1.call());
   c1 = new self::Class2::•(7.{core::int::unary-}());
   self::expect(3, tearOff1.call());
-  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff0 = self::Extension2|get#genericMethod(c0);
+  <T extends core::num* = core::num*>(T*) →* core::int* genericTearOff0 = self::Extension2|get#genericMethod(c0);
   self::expect(41, genericTearOff0.call<core::int*>(42));
   self::expect(41, genericTearOff0.call<core::num*>(42));
-  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff1 = self::Extension2|get#genericMethod(c1);
+  <T extends core::num* = core::num*>(T*) →* core::int* genericTearOff1 = self::Extension2|get#genericMethod(c1);
   self::expect(38, genericTearOff1.call<core::int*>(42));
   self::expect(38, genericTearOff1.call<core::num*>(42));
 }
diff --git a/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.transformed.expect
index cea7116..9508bad 100644
--- a/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.transformed.expect
@@ -54,24 +54,24 @@
 }
 static method Extension1|get#method(final self::Class1* #this) → () →* core::int*
   return () → core::int* => self::Extension1|method(#this);
-static method Extension1|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int* {
+static method Extension1|genericMethod<T extends core::num* = core::num*>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int* {
   core::print("Extension1.genericMethod<${self::Extension1|genericMethod::T*}>(${t}) on ${#this}");
   return #this.{self::Class1::field}.{core::num::+}(t) as{TypeError} core::int*;
 }
-static method Extension1|get#genericMethod(final self::Class1* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
+static method Extension1|get#genericMethod(final self::Class1* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension1|genericMethod<T*>(#this, t);
 static method Extension2|method(final self::Class2* #this) → core::int* {
   core::print("Extension2.method on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(2);
 }
 static method Extension2|get#method(final self::Class2* #this) → () →* core::int*
   return () → core::int* => self::Extension2|method(#this);
-static method Extension2|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int* {
+static method Extension2|genericMethod<T extends core::num* = core::num*>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int* {
   core::print("Extension2.genericMethod<${self::Extension2|genericMethod::T*}>(${t}) on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(t).{core::num::+}(3) as{TypeError} core::int*;
 }
-static method Extension2|get#genericMethod(final self::Class2* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
+static method Extension2|get#genericMethod(final self::Class2* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::Extension2|genericMethod<T*>(#this, t);
 static method main() → dynamic {
   self::testExtension1();
   self::testExtension2();
@@ -87,10 +87,10 @@
   self::expect(1, tearOff1.call());
   c1 = new self::Class1::•(7.{core::int::unary-}());
   self::expect(1, tearOff1.call());
-  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff0 = self::Extension1|get#genericMethod(c0);
+  <T extends core::num* = core::num*>(T*) →* core::int* genericTearOff0 = self::Extension1|get#genericMethod(c0);
   self::expect(38, genericTearOff0.call<core::int*>(42));
   self::expect(38, genericTearOff0.call<core::num*>(42));
-  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff1 = self::Extension1|get#genericMethod(c1);
+  <T extends core::num* = core::num*>(T*) →* core::int* genericTearOff1 = self::Extension1|get#genericMethod(c1);
   self::expect(35, genericTearOff1.call<core::int*>(42));
   self::expect(35, genericTearOff1.call<core::num*>(42));
 }
@@ -105,10 +105,10 @@
   self::expect(3, tearOff1.call());
   c1 = new self::Class2::•(7.{core::int::unary-}());
   self::expect(3, tearOff1.call());
-  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff0 = self::Extension2|get#genericMethod(c0);
+  <T extends core::num* = core::num*>(T*) →* core::int* genericTearOff0 = self::Extension2|get#genericMethod(c0);
   self::expect(41, genericTearOff0.call<core::int*>(42));
   self::expect(41, genericTearOff0.call<core::num*>(42));
-  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff1 = self::Extension2|get#genericMethod(c1);
+  <T extends core::num* = core::num*>(T*) →* core::int* genericTearOff1 = self::Extension2|get#genericMethod(c1);
   self::expect(38, genericTearOff1.call<core::int*>(42));
   self::expect(38, genericTearOff1.call<core::num*>(42));
 }
diff --git a/pkg/front_end/testcases/extensions/on_function_type.dart.outline.expect b/pkg/front_end/testcases/extensions/on_function_type.dart.outline.expect
index 548304c..6e6c978 100644
--- a/pkg/front_end/testcases/extensions/on_function_type.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/on_function_type.dart.outline.expect
@@ -24,14 +24,14 @@
   get returnType = self::_extension#0|get#returnType;
   get parameterType = self::_extension#0|get#parameterType;
 }
-extension _extension#1<T extends self::Class<T*>* = dynamic> on <S extends T* = dynamic>(T*, S*) →* dynamic {
+extension _extension#1<T extends self::Class<T*>* = self::Class<dynamic>*> on <S extends T* = dynamic>(T*, S*) →* dynamic {
   get parameterType = self::_extension#1|get#parameterType;
 }
 static method _extension#0|get#returnType<R extends core::Object* = dynamic, T extends core::Object* = dynamic>(final (self::_extension#0|get#returnType::T*) →* self::_extension#0|get#returnType::R* #this) → core::Type*
   ;
 static method _extension#0|get#parameterType<R extends core::Object* = dynamic, T extends core::Object* = dynamic>(final (self::_extension#0|get#parameterType::T*) →* self::_extension#0|get#parameterType::R* #this) → core::Type*
   ;
-static method _extension#1|get#parameterType<T extends self::Class<self::_extension#1|get#parameterType::T*>* = dynamic>(final <S extends self::_extension#1|get#parameterType::T* = dynamic>(self::_extension#1|get#parameterType::T*, S*) →* dynamic #this) → core::Type*
+static method _extension#1|get#parameterType<T extends self::Class<self::_extension#1|get#parameterType::T*>* = self::Class<dynamic>*>(final <S extends self::_extension#1|get#parameterType::T* = dynamic>(self::_extension#1|get#parameterType::T*, S*) →* dynamic #this) → core::Type*
   ;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/extensions/on_function_type.dart.strong.expect b/pkg/front_end/testcases/extensions/on_function_type.dart.strong.expect
index 79633f7..59a3ec8 100644
--- a/pkg/front_end/testcases/extensions/on_function_type.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/on_function_type.dart.strong.expect
@@ -26,14 +26,14 @@
   get returnType = self::_extension#0|get#returnType;
   get parameterType = self::_extension#0|get#parameterType;
 }
-extension _extension#1<T extends self::Class<T*>* = dynamic> on <S extends T* = dynamic>(T*, S*) →* dynamic {
+extension _extension#1<T extends self::Class<T*>* = self::Class<dynamic>*> on <S extends T* = dynamic>(T*, S*) →* dynamic {
   get parameterType = self::_extension#1|get#parameterType;
 }
 static method _extension#0|get#returnType<R extends core::Object* = dynamic, T extends core::Object* = dynamic>(final (self::_extension#0|get#returnType::T*) →* self::_extension#0|get#returnType::R* #this) → core::Type*
   return self::_extension#0|get#returnType::R*;
 static method _extension#0|get#parameterType<R extends core::Object* = dynamic, T extends core::Object* = dynamic>(final (self::_extension#0|get#parameterType::T*) →* self::_extension#0|get#parameterType::R* #this) → core::Type*
   return self::_extension#0|get#parameterType::T*;
-static method _extension#1|get#parameterType<T extends self::Class<self::_extension#1|get#parameterType::T*>* = dynamic>(final <S extends self::_extension#1|get#parameterType::T* = dynamic>(self::_extension#1|get#parameterType::T*, S*) →* dynamic #this) → core::Type*
+static method _extension#1|get#parameterType<T extends self::Class<self::_extension#1|get#parameterType::T*>* = self::Class<dynamic>*>(final <S extends self::_extension#1|get#parameterType::T* = dynamic>(self::_extension#1|get#parameterType::T*, S*) →* dynamic #this) → core::Type*
   return self::_extension#1|get#parameterType::T*;
 static method main() → dynamic {
   function local1(core::int* i) → core::int*
diff --git a/pkg/front_end/testcases/extensions/on_function_type.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/on_function_type.dart.strong.transformed.expect
index 79633f7..59a3ec8 100644
--- a/pkg/front_end/testcases/extensions/on_function_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/on_function_type.dart.strong.transformed.expect
@@ -26,14 +26,14 @@
   get returnType = self::_extension#0|get#returnType;
   get parameterType = self::_extension#0|get#parameterType;
 }
-extension _extension#1<T extends self::Class<T*>* = dynamic> on <S extends T* = dynamic>(T*, S*) →* dynamic {
+extension _extension#1<T extends self::Class<T*>* = self::Class<dynamic>*> on <S extends T* = dynamic>(T*, S*) →* dynamic {
   get parameterType = self::_extension#1|get#parameterType;
 }
 static method _extension#0|get#returnType<R extends core::Object* = dynamic, T extends core::Object* = dynamic>(final (self::_extension#0|get#returnType::T*) →* self::_extension#0|get#returnType::R* #this) → core::Type*
   return self::_extension#0|get#returnType::R*;
 static method _extension#0|get#parameterType<R extends core::Object* = dynamic, T extends core::Object* = dynamic>(final (self::_extension#0|get#parameterType::T*) →* self::_extension#0|get#parameterType::R* #this) → core::Type*
   return self::_extension#0|get#parameterType::T*;
-static method _extension#1|get#parameterType<T extends self::Class<self::_extension#1|get#parameterType::T*>* = dynamic>(final <S extends self::_extension#1|get#parameterType::T* = dynamic>(self::_extension#1|get#parameterType::T*, S*) →* dynamic #this) → core::Type*
+static method _extension#1|get#parameterType<T extends self::Class<self::_extension#1|get#parameterType::T*>* = self::Class<dynamic>*>(final <S extends self::_extension#1|get#parameterType::T* = dynamic>(self::_extension#1|get#parameterType::T*, S*) →* dynamic #this) → core::Type*
   return self::_extension#1|get#parameterType::T*;
 static method main() → dynamic {
   function local1(core::int* i) → core::int*
diff --git a/pkg/front_end/testcases/extensions/on_type_inference.dart.outline.expect b/pkg/front_end/testcases/extensions/on_type_inference.dart.outline.expect
index a4e1d3c..2753b81 100644
--- a/pkg/front_end/testcases/extensions/on_type_inference.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/on_type_inference.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-extension BestCom<T extends core::num* = dynamic> on core::Iterable<T*>* {
+extension BestCom<T extends core::num* = core::num*> on core::Iterable<T*>* {
   method best = self::BestCom|best;
   tearoff best = self::BestCom|get#best;
 }
@@ -14,9 +14,9 @@
   method best = self::BestSpec|best;
   tearoff best = self::BestSpec|get#best;
 }
-static method BestCom|best<T extends core::num* = dynamic>(final core::Iterable<self::BestCom|best::T*>* #this) → self::BestCom|best::T*
+static method BestCom|best<T extends core::num* = core::num*>(final core::Iterable<self::BestCom|best::T*>* #this) → self::BestCom|best::T*
   ;
-static method BestCom|get#best<T extends core::num* = dynamic>(final core::Iterable<self::BestCom|get#best::T*>* #this) → () →* self::BestCom|get#best::T*
+static method BestCom|get#best<T extends core::num* = core::num*>(final core::Iterable<self::BestCom|get#best::T*>* #this) → () →* self::BestCom|get#best::T*
   return () → self::BestCom|get#best::T* => self::BestCom|best<self::BestCom|get#best::T*>(#this);
 static method BestList|best<T extends core::Object* = dynamic>(final core::List<self::BestList|best::T*>* #this) → self::BestList|best::T*
   ;
diff --git a/pkg/front_end/testcases/extensions/on_type_inference.dart.strong.expect b/pkg/front_end/testcases/extensions/on_type_inference.dart.strong.expect
index 25a3e4a..b0990ec 100644
--- a/pkg/front_end/testcases/extensions/on_type_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/on_type_inference.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-extension BestCom<T extends core::num* = dynamic> on core::Iterable<T*>* {
+extension BestCom<T extends core::num* = core::num*> on core::Iterable<T*>* {
   method best = self::BestCom|best;
   tearoff best = self::BestCom|get#best;
 }
@@ -14,9 +14,9 @@
   method best = self::BestSpec|best;
   tearoff best = self::BestSpec|get#best;
 }
-static method BestCom|best<T extends core::num* = dynamic>(final core::Iterable<self::BestCom|best::T*>* #this) → self::BestCom|best::T*
+static method BestCom|best<T extends core::num* = core::num*>(final core::Iterable<self::BestCom|best::T*>* #this) → self::BestCom|best::T*
   return null;
-static method BestCom|get#best<T extends core::num* = dynamic>(final core::Iterable<self::BestCom|get#best::T*>* #this) → () →* self::BestCom|get#best::T*
+static method BestCom|get#best<T extends core::num* = core::num*>(final core::Iterable<self::BestCom|get#best::T*>* #this) → () →* self::BestCom|get#best::T*
   return () → self::BestCom|get#best::T* => self::BestCom|best<self::BestCom|get#best::T*>(#this);
 static method BestList|best<T extends core::Object* = dynamic>(final core::List<self::BestList|best::T*>* #this) → self::BestList|best::T*
   return null;
diff --git a/pkg/front_end/testcases/extensions/on_type_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/on_type_inference.dart.strong.transformed.expect
index 25a3e4a..b0990ec 100644
--- a/pkg/front_end/testcases/extensions/on_type_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/on_type_inference.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-extension BestCom<T extends core::num* = dynamic> on core::Iterable<T*>* {
+extension BestCom<T extends core::num* = core::num*> on core::Iterable<T*>* {
   method best = self::BestCom|best;
   tearoff best = self::BestCom|get#best;
 }
@@ -14,9 +14,9 @@
   method best = self::BestSpec|best;
   tearoff best = self::BestSpec|get#best;
 }
-static method BestCom|best<T extends core::num* = dynamic>(final core::Iterable<self::BestCom|best::T*>* #this) → self::BestCom|best::T*
+static method BestCom|best<T extends core::num* = core::num*>(final core::Iterable<self::BestCom|best::T*>* #this) → self::BestCom|best::T*
   return null;
-static method BestCom|get#best<T extends core::num* = dynamic>(final core::Iterable<self::BestCom|get#best::T*>* #this) → () →* self::BestCom|get#best::T*
+static method BestCom|get#best<T extends core::num* = core::num*>(final core::Iterable<self::BestCom|get#best::T*>* #this) → () →* self::BestCom|get#best::T*
   return () → self::BestCom|get#best::T* => self::BestCom|best<self::BestCom|get#best::T*>(#this);
 static method BestList|best<T extends core::Object* = dynamic>(final core::List<self::BestList|best::T*>* #this) → self::BestList|best::T*
   return null;
diff --git a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.outline.expect b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.outline.expect
index 9ecbc38..2681a86 100644
--- a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.outline.expect
@@ -38,19 +38,19 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-extension Extension<T extends self::Struct* = dynamic> on T* {
+extension Extension<T extends self::Struct* = self::Struct*> on T* {
   method method = self::Extension|method;
   tearoff method = self::Extension|get#method;
   get property = self::Extension|get#property;
   set property = self::Extension|set#property;
 }
-static method Extension|method<T extends self::Struct* = dynamic>(final self::Extension|method::T* #this) → self::Extension|method::T*
+static method Extension|method<T extends self::Struct* = self::Struct*>(final self::Extension|method::T* #this) → self::Extension|method::T*
   ;
-static method Extension|get#method<T extends self::Struct* = dynamic>(final self::Extension|get#method::T* #this) → () →* self::Extension|get#method::T*
+static method Extension|get#method<T extends self::Struct* = self::Struct*>(final self::Extension|get#method::T* #this) → () →* self::Extension|get#method::T*
   return () → self::Extension|get#method::T* => self::Extension|method<self::Extension|get#method::T*>(#this);
-static method Extension|get#property<T extends self::Struct* = dynamic>(final self::Extension|get#property::T* #this) → self::Extension|get#property::T*
+static method Extension|get#property<T extends self::Struct* = self::Struct*>(final self::Extension|get#property::T* #this) → self::Extension|get#property::T*
   ;
-static method Extension|set#property<T extends self::Struct* = dynamic>(final self::Extension|set#property::T* #this, self::Extension|set#property::T* value) → void
+static method Extension|set#property<T extends self::Struct* = self::Struct*>(final self::Extension|set#property::T* #this, self::Extension|set#property::T* value) → void
   ;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.expect b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.expect
index 9a73f83..0558246 100644
--- a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.expect
@@ -81,19 +81,19 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-extension Extension<T extends self::Struct* = dynamic> on T* {
+extension Extension<T extends self::Struct* = self::Struct*> on T* {
   method method = self::Extension|method;
   tearoff method = self::Extension|get#method;
   get property = self::Extension|get#property;
   set property = self::Extension|set#property;
 }
-static method Extension|method<T extends self::Struct* = dynamic>(final self::Extension|method::T* #this) → self::Extension|method::T*
+static method Extension|method<T extends self::Struct* = self::Struct*>(final self::Extension|method::T* #this) → self::Extension|method::T*
   return #this;
-static method Extension|get#method<T extends self::Struct* = dynamic>(final self::Extension|get#method::T* #this) → () →* self::Extension|get#method::T*
+static method Extension|get#method<T extends self::Struct* = self::Struct*>(final self::Extension|get#method::T* #this) → () →* self::Extension|get#method::T*
   return () → self::Extension|get#method::T* => self::Extension|method<self::Extension|get#method::T*>(#this);
-static method Extension|get#property<T extends self::Struct* = dynamic>(final self::Extension|get#property::T* #this) → self::Extension|get#property::T*
+static method Extension|get#property<T extends self::Struct* = self::Struct*>(final self::Extension|get#property::T* #this) → self::Extension|get#property::T*
   return #this;
-static method Extension|set#property<T extends self::Struct* = dynamic>(final self::Extension|set#property::T* #this, self::Extension|set#property::T* value) → void {}
+static method Extension|set#property<T extends self::Struct* = self::Struct*>(final self::Extension|set#property::T* #this, self::Extension|set#property::T* value) → void {}
 static method main() → dynamic {
   self::Struct* struct;
   self::StructA* structA;
diff --git a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.transformed.expect
index 9a73f83..0558246 100644
--- a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.transformed.expect
@@ -81,19 +81,19 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-extension Extension<T extends self::Struct* = dynamic> on T* {
+extension Extension<T extends self::Struct* = self::Struct*> on T* {
   method method = self::Extension|method;
   tearoff method = self::Extension|get#method;
   get property = self::Extension|get#property;
   set property = self::Extension|set#property;
 }
-static method Extension|method<T extends self::Struct* = dynamic>(final self::Extension|method::T* #this) → self::Extension|method::T*
+static method Extension|method<T extends self::Struct* = self::Struct*>(final self::Extension|method::T* #this) → self::Extension|method::T*
   return #this;
-static method Extension|get#method<T extends self::Struct* = dynamic>(final self::Extension|get#method::T* #this) → () →* self::Extension|get#method::T*
+static method Extension|get#method<T extends self::Struct* = self::Struct*>(final self::Extension|get#method::T* #this) → () →* self::Extension|get#method::T*
   return () → self::Extension|get#method::T* => self::Extension|method<self::Extension|get#method::T*>(#this);
-static method Extension|get#property<T extends self::Struct* = dynamic>(final self::Extension|get#property::T* #this) → self::Extension|get#property::T*
+static method Extension|get#property<T extends self::Struct* = self::Struct*>(final self::Extension|get#property::T* #this) → self::Extension|get#property::T*
   return #this;
-static method Extension|set#property<T extends self::Struct* = dynamic>(final self::Extension|set#property::T* #this, self::Extension|set#property::T* value) → void {}
+static method Extension|set#property<T extends self::Struct* = self::Struct*>(final self::Extension|set#property::T* #this, self::Extension|set#property::T* value) → void {}
 static method main() → dynamic {
   self::Struct* struct;
   self::StructA* structA;
diff --git a/pkg/front_end/testcases/extensions/type_variables.dart.outline.expect b/pkg/front_end/testcases/extensions/type_variables.dart.outline.expect
index bba96b0..f786bf3 100644
--- a/pkg/front_end/testcases/extensions/type_variables.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/type_variables.dart.outline.expect
@@ -22,7 +22,7 @@
   method method2 = self::A2|method2;
   tearoff method2 = self::A2|get#method2;
 }
-extension A3<T extends self::A1<T*>* = dynamic> on self::A1<T*>* {
+extension A3<T extends self::A1<T*>* = self::A1<dynamic>*> on self::A1<T*>* {
 }
 extension A4<T extends core::Object* = dynamic> on self::A1<T*>* {
   method method = self::A4|method;
@@ -32,10 +32,10 @@
   ;
 static method A2|get#method1<T extends core::Object* = dynamic>(final self::A1<self::A2|get#method1::T*>* #this) → <S extends self::A2|get#method1::T* = dynamic>() →* self::A1<self::A2|get#method1::T*>*
   return <S extends self::A2|get#method1::T* = dynamic>() → self::A1<self::A2|get#method1::T*>* => self::A2|method1<self::A2|get#method1::T*, S*>(#this);
-static method A2|method2<T extends core::Object* = dynamic, S extends self::A1<self::A2|method2::T*>* = dynamic>(final self::A1<self::A2|method2::T*>* #this, self::A2|method2::S* o) → self::A1<self::A2|method2::T*>*
+static method A2|method2<T extends core::Object* = dynamic, S extends self::A1<self::A2|method2::T*>* = self::A1<dynamic>*>(final self::A1<self::A2|method2::T*>* #this, self::A2|method2::S* o) → self::A1<self::A2|method2::T*>*
   ;
-static method A2|get#method2<T extends core::Object* = dynamic>(final self::A1<self::A2|get#method2::T*>* #this) → <S extends self::A1<self::A2|get#method2::T*>* = dynamic>(S*) →* self::A1<self::A2|get#method2::T*>*
-  return <S extends self::A1<self::A2|get#method2::T*>* = dynamic>(S* o) → self::A1<self::A2|get#method2::T*>* => self::A2|method2<self::A2|get#method2::T*, S*>(#this, o);
+static method A2|get#method2<T extends core::Object* = dynamic>(final self::A1<self::A2|get#method2::T*>* #this) → <S extends self::A1<self::A2|get#method2::T*>* = self::A1<dynamic>*>(S*) →* self::A1<self::A2|get#method2::T*>*
+  return <S extends self::A1<self::A2|get#method2::T*>* = self::A1<dynamic>*>(S* o) → self::A1<self::A2|get#method2::T*>* => self::A2|method2<self::A2|get#method2::T*, S*>(#this, o);
 static method A4|method<#T extends core::Object* = dynamic, T extends core::Object* = dynamic>(final self::A1<self::A4|method::#T*>* #this) → dynamic
   ;
 static method A4|get#method<#T extends core::Object* = dynamic>(final self::A1<self::A4|get#method::#T*>* #this) → <T extends core::Object* = dynamic>() →* dynamic
diff --git a/pkg/front_end/testcases/extensions/type_variables.dart.strong.expect b/pkg/front_end/testcases/extensions/type_variables.dart.strong.expect
index 52157a0..e2c6597 100644
--- a/pkg/front_end/testcases/extensions/type_variables.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/type_variables.dart.strong.expect
@@ -23,7 +23,7 @@
   method method2 = self::A2|method2;
   tearoff method2 = self::A2|get#method2;
 }
-extension A3<T extends self::A1<T*>* = dynamic> on self::A1<T*>* {
+extension A3<T extends self::A1<T*>* = self::A1<dynamic>*> on self::A1<T*>* {
 }
 extension A4<T extends core::Object* = dynamic> on self::A1<T*>* {
   method method = self::A4|method;
@@ -34,14 +34,14 @@
 }
 static method A2|get#method1<T extends core::Object* = dynamic>(final self::A1<self::A2|get#method1::T*>* #this) → <S extends self::A2|get#method1::T* = dynamic>() →* self::A1<self::A2|get#method1::T*>*
   return <S extends self::A2|get#method1::T* = dynamic>() → self::A1<self::A2|get#method1::T*>* => self::A2|method1<self::A2|get#method1::T*, S*>(#this);
-static method A2|method2<T extends core::Object* = dynamic, S extends self::A1<self::A2|method2::T*>* = dynamic>(final self::A1<self::A2|method2::T*>* #this, self::A2|method2::S* o) → self::A1<self::A2|method2::T*>* {
+static method A2|method2<T extends core::Object* = dynamic, S extends self::A1<self::A2|method2::T*>* = self::A1<dynamic>*>(final self::A1<self::A2|method2::T*>* #this, self::A2|method2::S* o) → self::A1<self::A2|method2::T*>* {
   core::print(o);
   core::print(self::A2|method2::T*);
   core::print(self::A2|method2::S*);
   return #this;
 }
-static method A2|get#method2<T extends core::Object* = dynamic>(final self::A1<self::A2|get#method2::T*>* #this) → <S extends self::A1<self::A2|get#method2::T*>* = dynamic>(S*) →* self::A1<self::A2|get#method2::T*>*
-  return <S extends self::A1<self::A2|get#method2::T*>* = dynamic>(S* o) → self::A1<self::A2|get#method2::T*>* => self::A2|method2<self::A2|get#method2::T*, S*>(#this, o);
+static method A2|get#method2<T extends core::Object* = dynamic>(final self::A1<self::A2|get#method2::T*>* #this) → <S extends self::A1<self::A2|get#method2::T*>* = self::A1<dynamic>*>(S*) →* self::A1<self::A2|get#method2::T*>*
+  return <S extends self::A1<self::A2|get#method2::T*>* = self::A1<dynamic>*>(S* o) → self::A1<self::A2|get#method2::T*>* => self::A2|method2<self::A2|get#method2::T*, S*>(#this, o);
 static method A4|method<#T extends core::Object* = dynamic, T extends core::Object* = dynamic>(final self::A1<self::A4|method::#T*>* #this) → dynamic {}
 static method A4|get#method<#T extends core::Object* = dynamic>(final self::A1<self::A4|get#method::#T*>* #this) → <T extends core::Object* = dynamic>() →* dynamic
   return <T extends core::Object* = dynamic>() → dynamic => self::A4|method<self::A4|get#method::#T*, T*>(#this);
diff --git a/pkg/front_end/testcases/extensions/type_variables.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/type_variables.dart.strong.transformed.expect
index 52157a0..e2c6597 100644
--- a/pkg/front_end/testcases/extensions/type_variables.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/type_variables.dart.strong.transformed.expect
@@ -23,7 +23,7 @@
   method method2 = self::A2|method2;
   tearoff method2 = self::A2|get#method2;
 }
-extension A3<T extends self::A1<T*>* = dynamic> on self::A1<T*>* {
+extension A3<T extends self::A1<T*>* = self::A1<dynamic>*> on self::A1<T*>* {
 }
 extension A4<T extends core::Object* = dynamic> on self::A1<T*>* {
   method method = self::A4|method;
@@ -34,14 +34,14 @@
 }
 static method A2|get#method1<T extends core::Object* = dynamic>(final self::A1<self::A2|get#method1::T*>* #this) → <S extends self::A2|get#method1::T* = dynamic>() →* self::A1<self::A2|get#method1::T*>*
   return <S extends self::A2|get#method1::T* = dynamic>() → self::A1<self::A2|get#method1::T*>* => self::A2|method1<self::A2|get#method1::T*, S*>(#this);
-static method A2|method2<T extends core::Object* = dynamic, S extends self::A1<self::A2|method2::T*>* = dynamic>(final self::A1<self::A2|method2::T*>* #this, self::A2|method2::S* o) → self::A1<self::A2|method2::T*>* {
+static method A2|method2<T extends core::Object* = dynamic, S extends self::A1<self::A2|method2::T*>* = self::A1<dynamic>*>(final self::A1<self::A2|method2::T*>* #this, self::A2|method2::S* o) → self::A1<self::A2|method2::T*>* {
   core::print(o);
   core::print(self::A2|method2::T*);
   core::print(self::A2|method2::S*);
   return #this;
 }
-static method A2|get#method2<T extends core::Object* = dynamic>(final self::A1<self::A2|get#method2::T*>* #this) → <S extends self::A1<self::A2|get#method2::T*>* = dynamic>(S*) →* self::A1<self::A2|get#method2::T*>*
-  return <S extends self::A1<self::A2|get#method2::T*>* = dynamic>(S* o) → self::A1<self::A2|get#method2::T*>* => self::A2|method2<self::A2|get#method2::T*, S*>(#this, o);
+static method A2|get#method2<T extends core::Object* = dynamic>(final self::A1<self::A2|get#method2::T*>* #this) → <S extends self::A1<self::A2|get#method2::T*>* = self::A1<dynamic>*>(S*) →* self::A1<self::A2|get#method2::T*>*
+  return <S extends self::A1<self::A2|get#method2::T*>* = self::A1<dynamic>*>(S* o) → self::A1<self::A2|get#method2::T*>* => self::A2|method2<self::A2|get#method2::T*, S*>(#this, o);
 static method A4|method<#T extends core::Object* = dynamic, T extends core::Object* = dynamic>(final self::A1<self::A4|method::#T*>* #this) → dynamic {}
 static method A4|get#method<#T extends core::Object* = dynamic>(final self::A1<self::A4|get#method::#T*>* #this) → <T extends core::Object* = dynamic>() →* dynamic
   return <T extends core::Object* = dynamic>() → dynamic => self::A4|method<self::A4|get#method::#T*, T*>(#this);
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.outline.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.outline.expect
index 010caf6..c671d48 100644
--- a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.outline.expect
@@ -54,10 +54,10 @@
   ;
 static method _extension#0|get#method(final self::Class1* #this) → () →* core::int*
   return () → core::int* => self::_extension#0|method(#this);
-static method _extension#0|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::_extension#0|genericMethod::T* t) → core::int*
+static method _extension#0|genericMethod<T extends core::num* = core::num*>(final self::Class1* #this, self::_extension#0|genericMethod::T* t) → core::int*
   ;
-static method _extension#0|get#genericMethod(final self::Class1* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::_extension#0|genericMethod<T*>(#this, t);
+static method _extension#0|get#genericMethod(final self::Class1* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::_extension#0|genericMethod<T*>(#this, t);
 static method _extension#0|get#property(final self::Class1* #this) → core::int*
   ;
 static method _extension#0|set#property(final self::Class1* #this, core::int* value) → void
@@ -66,10 +66,10 @@
   ;
 static method _extension#1|get#method(final self::Class2* #this) → () →* core::int*
   return () → core::int* => self::_extension#1|method(#this);
-static method _extension#1|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::_extension#1|genericMethod::T* t) → core::int*
+static method _extension#1|genericMethod<T extends core::num* = core::num*>(final self::Class2* #this, self::_extension#1|genericMethod::T* t) → core::int*
   ;
-static method _extension#1|get#genericMethod(final self::Class2* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::_extension#1|genericMethod<T*>(#this, t);
+static method _extension#1|get#genericMethod(final self::Class2* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::_extension#1|genericMethod<T*>(#this, t);
 static method _extension#1|get#property(final self::Class2* #this) → core::int*
   ;
 static method _extension#1|set#property(final self::Class2* #this, core::int* value) → void
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect
index 62bb7de..aa753cc 100644
--- a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect
@@ -58,12 +58,12 @@
 }
 static method _extension#0|get#method(final self::Class1* #this) → () →* core::int*
   return () → core::int* => self::_extension#0|method(#this);
-static method _extension#0|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::_extension#0|genericMethod::T* t) → core::int* {
+static method _extension#0|genericMethod<T extends core::num* = core::num*>(final self::Class1* #this, self::_extension#0|genericMethod::T* t) → core::int* {
   core::print("Extension1.genericMethod<${self::_extension#0|genericMethod::T*}>(${t}) on ${#this}");
   return #this.{self::Class1::field}.{core::num::+}(t) as{TypeError} core::int*;
 }
-static method _extension#0|get#genericMethod(final self::Class1* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::_extension#0|genericMethod<T*>(#this, t);
+static method _extension#0|get#genericMethod(final self::Class1* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::_extension#0|genericMethod<T*>(#this, t);
 static method _extension#0|get#property(final self::Class1* #this) → core::int* {
   core::print("Extension1.property get on ${#this}");
   return #this.{self::Class1::field};
@@ -79,12 +79,12 @@
 }
 static method _extension#1|get#method(final self::Class2* #this) → () →* core::int*
   return () → core::int* => self::_extension#1|method(#this);
-static method _extension#1|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::_extension#1|genericMethod::T* t) → core::int* {
+static method _extension#1|genericMethod<T extends core::num* = core::num*>(final self::Class2* #this, self::_extension#1|genericMethod::T* t) → core::int* {
   core::print("Extension2.genericMethod<${self::_extension#1|genericMethod::T*}>(${t}) on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(t).{core::num::+}(4) as{TypeError} core::int*;
 }
-static method _extension#1|get#genericMethod(final self::Class2* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::_extension#1|genericMethod<T*>(#this, t);
+static method _extension#1|get#genericMethod(final self::Class2* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::_extension#1|genericMethod<T*>(#this, t);
 static method _extension#1|get#property(final self::Class2* #this) → core::int* {
   core::print("Extension2.property get on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(5);
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
index 62bb7de..aa753cc 100644
--- a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
@@ -58,12 +58,12 @@
 }
 static method _extension#0|get#method(final self::Class1* #this) → () →* core::int*
   return () → core::int* => self::_extension#0|method(#this);
-static method _extension#0|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::_extension#0|genericMethod::T* t) → core::int* {
+static method _extension#0|genericMethod<T extends core::num* = core::num*>(final self::Class1* #this, self::_extension#0|genericMethod::T* t) → core::int* {
   core::print("Extension1.genericMethod<${self::_extension#0|genericMethod::T*}>(${t}) on ${#this}");
   return #this.{self::Class1::field}.{core::num::+}(t) as{TypeError} core::int*;
 }
-static method _extension#0|get#genericMethod(final self::Class1* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::_extension#0|genericMethod<T*>(#this, t);
+static method _extension#0|get#genericMethod(final self::Class1* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::_extension#0|genericMethod<T*>(#this, t);
 static method _extension#0|get#property(final self::Class1* #this) → core::int* {
   core::print("Extension1.property get on ${#this}");
   return #this.{self::Class1::field};
@@ -79,12 +79,12 @@
 }
 static method _extension#1|get#method(final self::Class2* #this) → () →* core::int*
   return () → core::int* => self::_extension#1|method(#this);
-static method _extension#1|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::_extension#1|genericMethod::T* t) → core::int* {
+static method _extension#1|genericMethod<T extends core::num* = core::num*>(final self::Class2* #this, self::_extension#1|genericMethod::T* t) → core::int* {
   core::print("Extension2.genericMethod<${self::_extension#1|genericMethod::T*}>(${t}) on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(t).{core::num::+}(4) as{TypeError} core::int*;
 }
-static method _extension#1|get#genericMethod(final self::Class2* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
-  return <T extends core::num* = dynamic>(T* t) → core::int* => self::_extension#1|genericMethod<T*>(#this, t);
+static method _extension#1|get#genericMethod(final self::Class2* #this) → <T extends core::num* = core::num*>(T*) →* core::int*
+  return <T extends core::num* = core::num*>(T* t) → core::int* => self::_extension#1|genericMethod<T*>(#this, t);
 static method _extension#1|get#property(final self::Class2* #this) → core::int* {
   core::print("Extension2.property get on ${#this}");
   return #this.{self::Class2::field}.{core::num::+}(5);
diff --git a/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect b/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect
index 8cc1729..9fd7126 100644
--- a/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect
+++ b/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect
@@ -1088,7 +1088,7 @@
     ;
 }
 class Af1<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Af1<self::Af1::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Af1<self::Af1::foo::X*>*
     ;
   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
@@ -1102,7 +1102,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Bf1<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Bf1<self::Bf1::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Bf1<self::Bf1::foo::X*>*
     ;
   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
@@ -1116,7 +1116,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Cf1<X extends () →* core::int* = () →* core::int*> extends core::Object {
-  static factory foo<X extends () →* core::int* = dynamic>() → self::Cf1<self::Cf1::foo::X*>*
+  static factory foo<X extends () →* core::int* = () →* core::int*>() → self::Cf1<self::Cf1::foo::X*>*
     ;
   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
@@ -1130,7 +1130,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Df1<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Df1<self::Df1::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Df1<self::Df1::foo::X*>*
     ;
   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
@@ -1144,7 +1144,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ef1<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ef1<self::Ef1::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ef1<self::Ef1::foo::X*>*
     ;
   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
@@ -1158,7 +1158,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ff1<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic> extends core::Object {
-  static factory foo<X extends ({x: core::int*}) →* dynamic = dynamic>() → self::Ff1<self::Ff1::foo::X*>*
+  static factory foo<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic>() → self::Ff1<self::Ff1::foo::X*>*
     ;
   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
@@ -1172,7 +1172,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Gf1<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Gf1<self::Gf1::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Gf1<self::Gf1::foo::X*>*
     ;
   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
@@ -1186,7 +1186,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Hf1<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Hf1<self::Hf1::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Hf1<self::Hf1::foo::X*>*
     ;
   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
@@ -1200,7 +1200,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class If1<X extends core::Function* = core::Function*> extends core::Object {
-  static factory foo<X extends core::Function* = dynamic>() → self::If1<self::If1::foo::X*>*
+  static factory foo<X extends core::Function* = core::Function*>() → self::If1<self::If1::foo::X*>*
     ;
   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
@@ -1214,7 +1214,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Jf1<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::Function*) →* dynamic = dynamic>() → self::Jf1<self::Jf1::foo::X*>*
+  static factory foo<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic>() → self::Jf1<self::Jf1::foo::X*>*
     ;
   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
@@ -1228,7 +1228,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Kf1<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = dynamic>() → self::Kf1<self::Kf1::foo::X*>*
+  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic>() → self::Kf1<self::Kf1::foo::X*>*
     ;
   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
@@ -1242,7 +1242,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Bf2<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Bf2<self::Bf2::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Bf2<self::Bf2::foo::X*>*
     ;
   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
@@ -1256,7 +1256,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Cf2<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Cf2<self::Cf2::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Cf2<self::Cf2::foo::X*>*
     ;
   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
@@ -1270,7 +1270,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Df2<X extends () →* core::int* = () →* core::int*> extends core::Object {
-  static factory foo<X extends () →* core::int* = dynamic>() → self::Df2<self::Df2::foo::X*>*
+  static factory foo<X extends () →* core::int* = () →* core::int*>() → self::Df2<self::Df2::foo::X*>*
     ;
   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
@@ -1284,7 +1284,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ef2<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ef2<self::Ef2::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ef2<self::Ef2::foo::X*>*
     ;
   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
@@ -1298,7 +1298,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ff2<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ff2<self::Ff2::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ff2<self::Ff2::foo::X*>*
     ;
   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
@@ -1312,7 +1312,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Gf2<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic> extends core::Object {
-  static factory foo<X extends ({x: core::int*}) →* dynamic = dynamic>() → self::Gf2<self::Gf2::foo::X*>*
+  static factory foo<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic>() → self::Gf2<self::Gf2::foo::X*>*
     ;
   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
@@ -1326,7 +1326,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Hf2<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Hf2<self::Hf2::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Hf2<self::Hf2::foo::X*>*
     ;
   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
@@ -1340,7 +1340,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class If2<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::If2<self::If2::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::If2<self::If2::foo::X*>*
     ;
   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
@@ -1354,7 +1354,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Jf2<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::Function*) →* dynamic = dynamic>() → self::Jf2<self::Jf2::foo::X*>*
+  static factory foo<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic>() → self::Jf2<self::Jf2::foo::X*>*
     ;
   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
@@ -1368,7 +1368,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Kf2<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = dynamic>() → self::Kf2<self::Kf2::foo::X*>*
+  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic>() → self::Kf2<self::Kf2::foo::X*>*
     ;
   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
diff --git a/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect b/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect
index 1f6c822..9b9542f 100644
--- a/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect
+++ b/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect
@@ -1123,7 +1123,7 @@
     ;
 }
 class Af1<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Af1<self::Af1::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Af1<self::Af1::foo::X*>*
     return null;
   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
@@ -1137,7 +1137,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Bf1<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Bf1<self::Bf1::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Bf1<self::Bf1::foo::X*>*
     return null;
   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
@@ -1151,7 +1151,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Cf1<X extends () →* core::int* = () →* core::int*> extends core::Object {
-  static factory foo<X extends () →* core::int* = dynamic>() → self::Cf1<self::Cf1::foo::X*>*
+  static factory foo<X extends () →* core::int* = () →* core::int*>() → self::Cf1<self::Cf1::foo::X*>*
     return null;
   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
@@ -1165,7 +1165,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Df1<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Df1<self::Df1::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Df1<self::Df1::foo::X*>*
     return null;
   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
@@ -1179,7 +1179,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ef1<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ef1<self::Ef1::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ef1<self::Ef1::foo::X*>*
     return null;
   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
@@ -1193,7 +1193,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ff1<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic> extends core::Object {
-  static factory foo<X extends ({x: core::int*}) →* dynamic = dynamic>() → self::Ff1<self::Ff1::foo::X*>*
+  static factory foo<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic>() → self::Ff1<self::Ff1::foo::X*>*
     return null;
   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
@@ -1207,7 +1207,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Gf1<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Gf1<self::Gf1::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Gf1<self::Gf1::foo::X*>*
     return null;
   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
@@ -1221,7 +1221,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Hf1<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Hf1<self::Hf1::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Hf1<self::Hf1::foo::X*>*
     return null;
   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
@@ -1235,7 +1235,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class If1<X extends core::Function* = core::Function*> extends core::Object {
-  static factory foo<X extends core::Function* = dynamic>() → self::If1<self::If1::foo::X*>*
+  static factory foo<X extends core::Function* = core::Function*>() → self::If1<self::If1::foo::X*>*
     return null;
   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
@@ -1249,7 +1249,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Jf1<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::Function*) →* dynamic = dynamic>() → self::Jf1<self::Jf1::foo::X*>*
+  static factory foo<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic>() → self::Jf1<self::Jf1::foo::X*>*
     return null;
   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
@@ -1263,7 +1263,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Kf1<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = dynamic>() → self::Kf1<self::Kf1::foo::X*>*
+  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic>() → self::Kf1<self::Kf1::foo::X*>*
     return null;
   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
@@ -1277,7 +1277,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Bf2<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Bf2<self::Bf2::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Bf2<self::Bf2::foo::X*>*
     return null;
   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
@@ -1291,7 +1291,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Cf2<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Cf2<self::Cf2::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Cf2<self::Cf2::foo::X*>*
     return null;
   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
@@ -1305,7 +1305,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Df2<X extends () →* core::int* = () →* core::int*> extends core::Object {
-  static factory foo<X extends () →* core::int* = dynamic>() → self::Df2<self::Df2::foo::X*>*
+  static factory foo<X extends () →* core::int* = () →* core::int*>() → self::Df2<self::Df2::foo::X*>*
     return null;
   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
@@ -1319,7 +1319,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ef2<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ef2<self::Ef2::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ef2<self::Ef2::foo::X*>*
     return null;
   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
@@ -1333,7 +1333,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ff2<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ff2<self::Ff2::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ff2<self::Ff2::foo::X*>*
     return null;
   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
@@ -1347,7 +1347,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Gf2<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic> extends core::Object {
-  static factory foo<X extends ({x: core::int*}) →* dynamic = dynamic>() → self::Gf2<self::Gf2::foo::X*>*
+  static factory foo<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic>() → self::Gf2<self::Gf2::foo::X*>*
     return null;
   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
@@ -1361,7 +1361,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Hf2<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Hf2<self::Hf2::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Hf2<self::Hf2::foo::X*>*
     return null;
   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
@@ -1375,7 +1375,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class If2<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::If2<self::If2::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::If2<self::If2::foo::X*>*
     return null;
   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
@@ -1389,7 +1389,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Jf2<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::Function*) →* dynamic = dynamic>() → self::Jf2<self::Jf2::foo::X*>*
+  static factory foo<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic>() → self::Jf2<self::Jf2::foo::X*>*
     return null;
   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
@@ -1403,7 +1403,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Kf2<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = dynamic>() → self::Kf2<self::Kf2::foo::X*>*
+  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic>() → self::Kf2<self::Kf2::foo::X*>*
     return null;
   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
diff --git a/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect
index 9ad3d47d..67d2466 100644
--- a/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect
@@ -1123,7 +1123,7 @@
     ;
 }
 class Af1<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Af1<self::Af1::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Af1<self::Af1::foo::X*>*
     return null;
   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
@@ -1137,7 +1137,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Bf1<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Bf1<self::Bf1::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Bf1<self::Bf1::foo::X*>*
     return null;
   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
@@ -1151,7 +1151,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Cf1<X extends () →* core::int* = () →* core::int*> extends core::Object {
-  static factory foo<X extends () →* core::int* = dynamic>() → self::Cf1<self::Cf1::foo::X*>*
+  static factory foo<X extends () →* core::int* = () →* core::int*>() → self::Cf1<self::Cf1::foo::X*>*
     return null;
   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
@@ -1165,7 +1165,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Df1<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Df1<self::Df1::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Df1<self::Df1::foo::X*>*
     return null;
   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
@@ -1179,7 +1179,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ef1<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ef1<self::Ef1::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ef1<self::Ef1::foo::X*>*
     return null;
   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
@@ -1193,7 +1193,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ff1<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic> extends core::Object {
-  static factory foo<X extends ({x: core::int*}) →* dynamic = dynamic>() → self::Ff1<self::Ff1::foo::X*>*
+  static factory foo<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic>() → self::Ff1<self::Ff1::foo::X*>*
     return null;
   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
@@ -1207,7 +1207,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Gf1<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Gf1<self::Gf1::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Gf1<self::Gf1::foo::X*>*
     return null;
   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
@@ -1221,7 +1221,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Hf1<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Hf1<self::Hf1::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Hf1<self::Hf1::foo::X*>*
     return null;
   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
@@ -1235,7 +1235,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class If1<X extends core::Function* = core::Function*> extends core::Object {
-  static factory foo<X extends core::Function* = dynamic>() → self::If1<self::If1::foo::X*>*
+  static factory foo<X extends core::Function* = core::Function*>() → self::If1<self::If1::foo::X*>*
     return null;
   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
@@ -1249,7 +1249,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Jf1<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::Function*) →* dynamic = dynamic>() → self::Jf1<self::Jf1::foo::X*>*
+  static factory foo<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic>() → self::Jf1<self::Jf1::foo::X*>*
     return null;
   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
@@ -1263,7 +1263,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Kf1<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = dynamic>() → self::Kf1<self::Kf1::foo::X*>*
+  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic>() → self::Kf1<self::Kf1::foo::X*>*
     return null;
   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
@@ -1277,7 +1277,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Bf2<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Bf2<self::Bf2::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Bf2<self::Bf2::foo::X*>*
     return null;
   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
@@ -1291,7 +1291,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Cf2<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Cf2<self::Cf2::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Cf2<self::Cf2::foo::X*>*
     return null;
   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
@@ -1305,7 +1305,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Df2<X extends () →* core::int* = () →* core::int*> extends core::Object {
-  static factory foo<X extends () →* core::int* = dynamic>() → self::Df2<self::Df2::foo::X*>*
+  static factory foo<X extends () →* core::int* = () →* core::int*>() → self::Df2<self::Df2::foo::X*>*
     return null;
   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
@@ -1319,7 +1319,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ef2<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ef2<self::Ef2::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ef2<self::Ef2::foo::X*>*
     return null;
   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
@@ -1333,7 +1333,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ff2<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ff2<self::Ff2::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ff2<self::Ff2::foo::X*>*
     return null;
   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
@@ -1347,7 +1347,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Gf2<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic> extends core::Object {
-  static factory foo<X extends ({x: core::int*}) →* dynamic = dynamic>() → self::Gf2<self::Gf2::foo::X*>*
+  static factory foo<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic>() → self::Gf2<self::Gf2::foo::X*>*
     return null;
   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
@@ -1361,7 +1361,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Hf2<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Hf2<self::Hf2::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Hf2<self::Hf2::foo::X*>*
     return null;
   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
@@ -1375,7 +1375,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class If2<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::If2<self::If2::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::If2<self::If2::foo::X*>*
     return null;
   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
@@ -1389,7 +1389,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Jf2<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::Function*) →* dynamic = dynamic>() → self::Jf2<self::Jf2::foo::X*>*
+  static factory foo<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic>() → self::Jf2<self::Jf2::foo::X*>*
     return null;
   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
@@ -1403,7 +1403,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Kf2<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = dynamic>() → self::Kf2<self::Kf2::foo::X*>*
+  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic>() → self::Kf2<self::Kf2::foo::X*>*
     return null;
   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
diff --git a/pkg/front_end/testcases/general/issue38943.dart.outline.expect b/pkg/front_end/testcases/general/issue38943.dart.outline.expect
index d4c0c37..0c892f9 100644
--- a/pkg/front_end/testcases/general/issue38943.dart.outline.expect
+++ b/pkg/front_end/testcases/general/issue38943.dart.outline.expect
@@ -5,7 +5,7 @@
 class D<X extends () →* void = () →* void> extends core::Object {
   constructor _() → self::D<self::D::X*>*
     ;
-  static factory foo<X extends () →* void = dynamic>() → self::D<self::D::foo::X*>*
+  static factory foo<X extends () →* void = () →* void>() → self::D<self::D::foo::X*>*
     ;
   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
diff --git a/pkg/front_end/testcases/general/issue38943.dart.strong.expect b/pkg/front_end/testcases/general/issue38943.dart.strong.expect
index 0c63fd5..c85022a 100644
--- a/pkg/front_end/testcases/general/issue38943.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue38943.dart.strong.expect
@@ -5,7 +5,7 @@
 class D<X extends () →* void = () →* void> extends core::Object {
   constructor _() → self::D<self::D::X*>*
     : super core::Object::•() {}
-  static factory foo<X extends () →* void = dynamic>() → self::D<self::D::foo::X*>*
+  static factory foo<X extends () →* void = () →* void>() → self::D<self::D::foo::X*>*
     return new self::D::_<self::D::foo::X*>();
   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
diff --git a/pkg/front_end/testcases/general/issue38943.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue38943.dart.strong.transformed.expect
index 0c63fd5..c85022a 100644
--- a/pkg/front_end/testcases/general/issue38943.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue38943.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 class D<X extends () →* void = () →* void> extends core::Object {
   constructor _() → self::D<self::D::X*>*
     : super core::Object::•() {}
-  static factory foo<X extends () →* void = dynamic>() → self::D<self::D::foo::X*>*
+  static factory foo<X extends () →* void = () →* void>() → self::D<self::D::foo::X*>*
     return new self::D::_<self::D::foo::X*>();
   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
diff --git a/pkg/front_end/testcases/general/vm_type_ops.dart.outline.expect b/pkg/front_end/testcases/general/vm_type_ops.dart.outline.expect
index c188005..c37c149 100644
--- a/pkg/front_end/testcases/general/vm_type_ops.dart.outline.expect
+++ b/pkg/front_end/testcases/general/vm_type_ops.dart.outline.expect
@@ -36,7 +36,7 @@
     ;
 }
 class E<P extends core::String* = core::String*> extends core::Object {
-  static factory •<P extends core::String* = dynamic>() → self::E<self::E::•::P*>*
+  static factory •<P extends core::String* = core::String*>() → self::E<self::E::•::P*>*
     ;
   method foo6<generic-covariant-impl T extends self::E::P* = self::E::P*, U extends core::List<self::E::foo6::T*>* = core::List<self::E::P*>*>(core::Map<self::E::foo6::T*, self::E::foo6::U*>* map) → void
     ;
diff --git a/pkg/front_end/testcases/general/vm_type_ops.dart.strong.expect b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.expect
index 7a316df..f5999a8 100644
--- a/pkg/front_end/testcases/general/vm_type_ops.dart.strong.expect
+++ b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.expect
@@ -56,7 +56,7 @@
   }
 }
 class E<P extends core::String* = core::String*> extends core::Object {
-  static factory •<P extends core::String* = dynamic>() → self::E<self::E::•::P*>*
+  static factory •<P extends core::String* = core::String*>() → self::E<self::E::•::P*>*
     return null;
   method foo6<generic-covariant-impl T extends self::E::P* = self::E::P*, U extends core::List<self::E::foo6::T*>* = core::List<self::E::P*>*>(core::Map<self::E::foo6::T*, self::E::foo6::U*>* map) → void {}
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect
index 7a316df..f5999a8 100644
--- a/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect
@@ -56,7 +56,7 @@
   }
 }
 class E<P extends core::String* = core::String*> extends core::Object {
-  static factory •<P extends core::String* = dynamic>() → self::E<self::E::•::P*>*
+  static factory •<P extends core::String* = core::String*>() → self::E<self::E::•::P*>*
     return null;
   method foo6<generic-covariant-impl T extends self::E::P* = self::E::P*, U extends core::List<self::E::foo6::T*>* = core::List<self::E::P*>*>(core::Map<self::E::foo6::T*, self::E::foo6::U*>* map) → void {}
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.outline.expect b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.outline.expect
index 98a5645..85c8784 100644
--- a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.outline.expect
+++ b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.outline.expect
@@ -51,7 +51,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-extension E<X extends self::A<core::num*>* = dynamic> on self::A<core::int*>* {
+extension E<X extends self::A<core::num*>* = self::A<core::num*>*> on self::A<core::int*>* {
   static field fieldOfE = self::E|fieldOfE;
   method fooOfE = self::E|fooOfE;
   tearoff fooOfE = self::E|get#fooOfE;
@@ -61,17 +61,17 @@
   tearoff bazOfE = self::E|get#bazOfE;
 }
 static field self::A<core::num*>* E|fieldOfE;
-static method E|fooOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → self::A<core::num*>*
+static method E|fooOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → self::A<core::num*>*
   ;
-static method E|get#fooOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → () →* self::A<core::num*>*
+static method E|get#fooOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → () →* self::A<core::num*>*
   return () → self::A<core::num*>* => self::E|fooOfE<self::E|get#fooOfE::X*>(#this);
-static method E|barOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this, self::A<core::num*>* a) → void
+static method E|barOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this, self::A<core::num*>* a) → void
   ;
-static method E|get#barOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → (self::A<core::num*>*) →* void
+static method E|get#barOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → (self::A<core::num*>*) →* void
   return (self::A<core::num*>* a) → void => self::E|barOfE<self::E|get#barOfE::X*>(#this, a);
-static method E|bazOfE<X extends self::A<core::num*>* = dynamic, Y extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → void
+static method E|bazOfE<X extends self::A<core::num*>* = self::A<core::num*>*, Y extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → void
   ;
-static method E|get#bazOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → <Y extends self::A<core::num*>* = dynamic>() →* void
-  return <Y extends self::A<core::num*>* = dynamic>() → void => self::E|bazOfE<self::E|get#bazOfE::X*, Y*>(#this);
+static method E|get#bazOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → <Y extends self::A<core::num*>* = self::A<core::num*>*>() →* void
+  return <Y extends self::A<core::num*>* = self::A<core::num*>*>() → void => self::E|bazOfE<self::E|get#bazOfE::X*, Y*>(#this);
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.expect b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.expect
index b123cc59..87bc7b9 100644
--- a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.expect
+++ b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.expect
@@ -53,7 +53,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-extension E<X extends self::A<core::num*>* = dynamic> on self::A<core::int*>* {
+extension E<X extends self::A<core::num*>* = self::A<core::num*>*> on self::A<core::int*>* {
   static field fieldOfE = self::E|fieldOfE;
   method fooOfE = self::E|fooOfE;
   tearoff fooOfE = self::E|get#fooOfE;
@@ -63,14 +63,14 @@
   tearoff bazOfE = self::E|get#bazOfE;
 }
 static field self::A<core::num*>* E|fieldOfE;
-static method E|fooOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → self::A<core::num*>*
+static method E|fooOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → self::A<core::num*>*
   return null;
-static method E|get#fooOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → () →* self::A<core::num*>*
+static method E|get#fooOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → () →* self::A<core::num*>*
   return () → self::A<core::num*>* => self::E|fooOfE<self::E|get#fooOfE::X*>(#this);
-static method E|barOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this, self::A<core::num*>* a) → void {}
-static method E|get#barOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → (self::A<core::num*>*) →* void
+static method E|barOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this, self::A<core::num*>* a) → void {}
+static method E|get#barOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → (self::A<core::num*>*) →* void
   return (self::A<core::num*>* a) → void => self::E|barOfE<self::E|get#barOfE::X*>(#this, a);
-static method E|bazOfE<X extends self::A<core::num*>* = dynamic, Y extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → void {}
-static method E|get#bazOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → <Y extends self::A<core::num*>* = dynamic>() →* void
-  return <Y extends self::A<core::num*>* = dynamic>() → void => self::E|bazOfE<self::E|get#bazOfE::X*, Y*>(#this);
+static method E|bazOfE<X extends self::A<core::num*>* = self::A<core::num*>*, Y extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → void {}
+static method E|get#bazOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → <Y extends self::A<core::num*>* = self::A<core::num*>*>() →* void
+  return <Y extends self::A<core::num*>* = self::A<core::num*>*>() → void => self::E|bazOfE<self::E|get#bazOfE::X*, Y*>(#this);
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.transformed.expect b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.transformed.expect
index b123cc59..87bc7b9 100644
--- a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.transformed.expect
@@ -53,7 +53,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-extension E<X extends self::A<core::num*>* = dynamic> on self::A<core::int*>* {
+extension E<X extends self::A<core::num*>* = self::A<core::num*>*> on self::A<core::int*>* {
   static field fieldOfE = self::E|fieldOfE;
   method fooOfE = self::E|fooOfE;
   tearoff fooOfE = self::E|get#fooOfE;
@@ -63,14 +63,14 @@
   tearoff bazOfE = self::E|get#bazOfE;
 }
 static field self::A<core::num*>* E|fieldOfE;
-static method E|fooOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → self::A<core::num*>*
+static method E|fooOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → self::A<core::num*>*
   return null;
-static method E|get#fooOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → () →* self::A<core::num*>*
+static method E|get#fooOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → () →* self::A<core::num*>*
   return () → self::A<core::num*>* => self::E|fooOfE<self::E|get#fooOfE::X*>(#this);
-static method E|barOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this, self::A<core::num*>* a) → void {}
-static method E|get#barOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → (self::A<core::num*>*) →* void
+static method E|barOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this, self::A<core::num*>* a) → void {}
+static method E|get#barOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → (self::A<core::num*>*) →* void
   return (self::A<core::num*>* a) → void => self::E|barOfE<self::E|get#barOfE::X*>(#this, a);
-static method E|bazOfE<X extends self::A<core::num*>* = dynamic, Y extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → void {}
-static method E|get#bazOfE<X extends self::A<core::num*>* = dynamic>(final self::A<core::int*>* #this) → <Y extends self::A<core::num*>* = dynamic>() →* void
-  return <Y extends self::A<core::num*>* = dynamic>() → void => self::E|bazOfE<self::E|get#bazOfE::X*, Y*>(#this);
+static method E|bazOfE<X extends self::A<core::num*>* = self::A<core::num*>*, Y extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → void {}
+static method E|get#bazOfE<X extends self::A<core::num*>* = self::A<core::num*>*>(final self::A<core::int*>* #this) → <Y extends self::A<core::num*>* = self::A<core::num*>*>() →* void
+  return <Y extends self::A<core::num*>* = self::A<core::num*>*>() → void => self::E|bazOfE<self::E|get#bazOfE::X*, Y*>(#this);
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect
index bee7ac6..8b4a395 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect
@@ -1123,7 +1123,7 @@
     ;
 }
 class Af1<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Af1<self::Af1::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Af1<self::Af1::foo::X*>*
     return null;
   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
@@ -1137,7 +1137,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Bf1<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Bf1<self::Bf1::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Bf1<self::Bf1::foo::X*>*
     return null;
   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
@@ -1151,7 +1151,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Cf1<X extends () →* core::int* = () →* core::int*> extends core::Object {
-  static factory foo<X extends () →* core::int* = dynamic>() → self::Cf1<self::Cf1::foo::X*>*
+  static factory foo<X extends () →* core::int* = () →* core::int*>() → self::Cf1<self::Cf1::foo::X*>*
     return null;
   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
@@ -1165,7 +1165,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Df1<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Df1<self::Df1::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Df1<self::Df1::foo::X*>*
     return null;
   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
@@ -1179,7 +1179,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ef1<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ef1<self::Ef1::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ef1<self::Ef1::foo::X*>*
     return null;
   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
@@ -1193,7 +1193,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ff1<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic> extends core::Object {
-  static factory foo<X extends ({x: core::int*}) →* dynamic = dynamic>() → self::Ff1<self::Ff1::foo::X*>*
+  static factory foo<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic>() → self::Ff1<self::Ff1::foo::X*>*
     return null;
   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
@@ -1207,7 +1207,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Gf1<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Gf1<self::Gf1::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Gf1<self::Gf1::foo::X*>*
     return null;
   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
@@ -1221,7 +1221,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Hf1<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Hf1<self::Hf1::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Hf1<self::Hf1::foo::X*>*
     return null;
   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
@@ -1235,7 +1235,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class If1<X extends core::Function* = core::Function*> extends core::Object {
-  static factory foo<X extends core::Function* = dynamic>() → self::If1<self::If1::foo::X*>*
+  static factory foo<X extends core::Function* = core::Function*>() → self::If1<self::If1::foo::X*>*
     return null;
   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
@@ -1249,7 +1249,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Jf1<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::Function*) →* dynamic = dynamic>() → self::Jf1<self::Jf1::foo::X*>*
+  static factory foo<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic>() → self::Jf1<self::Jf1::foo::X*>*
     return null;
   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
@@ -1263,7 +1263,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Kf1<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = dynamic>() → self::Kf1<self::Kf1::foo::X*>*
+  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic>() → self::Kf1<self::Kf1::foo::X*>*
     return null;
   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
@@ -1277,7 +1277,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Bf2<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Bf2<self::Bf2::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Bf2<self::Bf2::foo::X*>*
     return null;
   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
@@ -1291,7 +1291,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Cf2<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Cf2<self::Cf2::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Cf2<self::Cf2::foo::X*>*
     return null;
   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
@@ -1305,7 +1305,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Df2<X extends () →* core::int* = () →* core::int*> extends core::Object {
-  static factory foo<X extends () →* core::int* = dynamic>() → self::Df2<self::Df2::foo::X*>*
+  static factory foo<X extends () →* core::int* = () →* core::int*>() → self::Df2<self::Df2::foo::X*>*
     return null;
   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
@@ -1319,7 +1319,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ef2<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ef2<self::Ef2::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ef2<self::Ef2::foo::X*>*
     return null;
   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
@@ -1333,7 +1333,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ff2<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ff2<self::Ff2::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ff2<self::Ff2::foo::X*>*
     return null;
   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
@@ -1347,7 +1347,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Gf2<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic> extends core::Object {
-  static factory foo<X extends ({x: core::int*}) →* dynamic = dynamic>() → self::Gf2<self::Gf2::foo::X*>*
+  static factory foo<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic>() → self::Gf2<self::Gf2::foo::X*>*
     return null;
   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
@@ -1361,7 +1361,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Hf2<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Hf2<self::Hf2::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Hf2<self::Hf2::foo::X*>*
     return null;
   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
@@ -1375,7 +1375,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class If2<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::If2<self::If2::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::If2<self::If2::foo::X*>*
     return null;
   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
@@ -1389,7 +1389,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Jf2<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::Function*) →* dynamic = dynamic>() → self::Jf2<self::Jf2::foo::X*>*
+  static factory foo<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic>() → self::Jf2<self::Jf2::foo::X*>*
     return null;
   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
@@ -1403,7 +1403,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Kf2<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = dynamic>() → self::Kf2<self::Kf2::foo::X*>*
+  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic>() → self::Kf2<self::Kf2::foo::X*>*
     return null;
   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
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect
index 047138b..511e518 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect
@@ -1123,7 +1123,7 @@
     ;
 }
 class Af1<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Af1<self::Af1::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Af1<self::Af1::foo::X*>*
     return null;
   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
@@ -1137,7 +1137,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Bf1<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Bf1<self::Bf1::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Bf1<self::Bf1::foo::X*>*
     return null;
   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
@@ -1151,7 +1151,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Cf1<X extends () →* core::int* = () →* core::int*> extends core::Object {
-  static factory foo<X extends () →* core::int* = dynamic>() → self::Cf1<self::Cf1::foo::X*>*
+  static factory foo<X extends () →* core::int* = () →* core::int*>() → self::Cf1<self::Cf1::foo::X*>*
     return null;
   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
@@ -1165,7 +1165,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Df1<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Df1<self::Df1::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Df1<self::Df1::foo::X*>*
     return null;
   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
@@ -1179,7 +1179,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ef1<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ef1<self::Ef1::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ef1<self::Ef1::foo::X*>*
     return null;
   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
@@ -1193,7 +1193,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ff1<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic> extends core::Object {
-  static factory foo<X extends ({x: core::int*}) →* dynamic = dynamic>() → self::Ff1<self::Ff1::foo::X*>*
+  static factory foo<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic>() → self::Ff1<self::Ff1::foo::X*>*
     return null;
   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
@@ -1207,7 +1207,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Gf1<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Gf1<self::Gf1::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Gf1<self::Gf1::foo::X*>*
     return null;
   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
@@ -1221,7 +1221,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Hf1<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Hf1<self::Hf1::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Hf1<self::Hf1::foo::X*>*
     return null;
   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
@@ -1235,7 +1235,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class If1<X extends core::Function* = core::Function*> extends core::Object {
-  static factory foo<X extends core::Function* = dynamic>() → self::If1<self::If1::foo::X*>*
+  static factory foo<X extends core::Function* = core::Function*>() → self::If1<self::If1::foo::X*>*
     return null;
   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
@@ -1249,7 +1249,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Jf1<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::Function*) →* dynamic = dynamic>() → self::Jf1<self::Jf1::foo::X*>*
+  static factory foo<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic>() → self::Jf1<self::Jf1::foo::X*>*
     return null;
   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
@@ -1263,7 +1263,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Kf1<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = dynamic>() → self::Kf1<self::Kf1::foo::X*>*
+  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic>() → self::Kf1<self::Kf1::foo::X*>*
     return null;
   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
@@ -1277,7 +1277,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Bf2<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Bf2<self::Bf2::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Bf2<self::Bf2::foo::X*>*
     return null;
   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
@@ -1291,7 +1291,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Cf2<X extends (core::int*) →* dynamic = (core::int*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::int*) →* dynamic = dynamic>() → self::Cf2<self::Cf2::foo::X*>*
+  static factory foo<X extends (core::int*) →* dynamic = (core::int*) →* dynamic>() → self::Cf2<self::Cf2::foo::X*>*
     return null;
   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
@@ -1305,7 +1305,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Df2<X extends () →* core::int* = () →* core::int*> extends core::Object {
-  static factory foo<X extends () →* core::int* = dynamic>() → self::Df2<self::Df2::foo::X*>*
+  static factory foo<X extends () →* core::int* = () →* core::int*>() → self::Df2<self::Df2::foo::X*>*
     return null;
   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
@@ -1319,7 +1319,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ef2<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ef2<self::Ef2::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ef2<self::Ef2::foo::X*>*
     return null;
   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
@@ -1333,7 +1333,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Ff2<X extends () →* dynamic = () →* dynamic> extends core::Object {
-  static factory foo<X extends () →* dynamic = dynamic>() → self::Ff2<self::Ff2::foo::X*>*
+  static factory foo<X extends () →* dynamic = () →* dynamic>() → self::Ff2<self::Ff2::foo::X*>*
     return null;
   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
@@ -1347,7 +1347,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Gf2<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic> extends core::Object {
-  static factory foo<X extends ({x: core::int*}) →* dynamic = dynamic>() → self::Gf2<self::Gf2::foo::X*>*
+  static factory foo<X extends ({x: core::int*}) →* dynamic = ({x: core::int*}) →* dynamic>() → self::Gf2<self::Gf2::foo::X*>*
     return null;
   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
@@ -1361,7 +1361,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Hf2<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::Hf2<self::Hf2::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::Hf2<self::Hf2::foo::X*>*
     return null;
   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
@@ -1375,7 +1375,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class If2<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic> extends core::Object {
-  static factory foo<X extends ([core::int*]) →* dynamic = dynamic>() → self::If2<self::If2::foo::X*>*
+  static factory foo<X extends ([core::int*]) →* dynamic = ([core::int*]) →* dynamic>() → self::If2<self::If2::foo::X*>*
     return null;
   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
@@ -1389,7 +1389,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Jf2<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends (core::Function*) →* dynamic = dynamic>() → self::Jf2<self::Jf2::foo::X*>*
+  static factory foo<X extends (core::Function*) →* dynamic = (core::Function*) →* dynamic>() → self::Jf2<self::Jf2::foo::X*>*
     return null;
   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
@@ -1403,7 +1403,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Kf2<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic> extends core::Object {
-  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = dynamic>() → self::Kf2<self::Kf2::foo::X*>*
+  static factory foo<X extends () →* (() →* core::Function*) →* dynamic = () →* (() →* core::Function*) →* dynamic>() → self::Kf2<self::Kf2::foo::X*>*
     return null;
   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
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue38943.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue38943.dart.weak.expect
index 0c63fd5..c85022a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue38943.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue38943.dart.weak.expect
@@ -5,7 +5,7 @@
 class D<X extends () →* void = () →* void> extends core::Object {
   constructor _() → self::D<self::D::X*>*
     : super core::Object::•() {}
-  static factory foo<X extends () →* void = dynamic>() → self::D<self::D::foo::X*>*
+  static factory foo<X extends () →* void = () →* void>() → self::D<self::D::foo::X*>*
     return new self::D::_<self::D::foo::X*>();
   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
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue38943.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue38943.dart.weak.transformed.expect
index 0c63fd5..c85022a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue38943.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue38943.dart.weak.transformed.expect
@@ -5,7 +5,7 @@
 class D<X extends () →* void = () →* void> extends core::Object {
   constructor _() → self::D<self::D::X*>*
     : super core::Object::•() {}
-  static factory foo<X extends () →* void = dynamic>() → self::D<self::D::foo::X*>*
+  static factory foo<X extends () →* void = () →* void>() → self::D<self::D::foo::X*>*
     return new self::D::_<self::D::foo::X*>();
   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
diff --git a/pkg/front_end/testcases/nnbd/extension_bounds.dart b/pkg/front_end/testcases/nnbd/extension_bounds.dart
new file mode 100644
index 0000000..3cbeff4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_bounds.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2020, 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.
+
+extension Extension1<T extends Object> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension2<T extends String> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension3<T extends dynamic> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension4<T> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension5<T extends Object?> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/extension_bounds.dart.outline.expect b/pkg/front_end/testcases/nnbd/extension_bounds.dart.outline.expect
new file mode 100644
index 0000000..5a8fb0d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_bounds.dart.outline.expect
@@ -0,0 +1,166 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+extension Extension1<T extends core::Object = core::Object> on T {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+  method method3 = self::Extension1|method3;
+  tearoff method3 = self::Extension1|get#method3;
+  method method4 = self::Extension1|method4;
+  tearoff method4 = self::Extension1|get#method4;
+  method method5 = self::Extension1|method5;
+  tearoff method5 = self::Extension1|get#method5;
+}
+extension Extension2<T extends core::String = core::String> on T {
+  method method1 = self::Extension2|method1;
+  tearoff method1 = self::Extension2|get#method1;
+  method method2 = self::Extension2|method2;
+  tearoff method2 = self::Extension2|get#method2;
+  method method3 = self::Extension2|method3;
+  tearoff method3 = self::Extension2|get#method3;
+  method method4 = self::Extension2|method4;
+  tearoff method4 = self::Extension2|get#method4;
+  method method5 = self::Extension2|method5;
+  tearoff method5 = self::Extension2|get#method5;
+}
+extension Extension3<T extends dynamic = dynamic> on T% {
+  method method1 = self::Extension3|method1;
+  tearoff method1 = self::Extension3|get#method1;
+  method method2 = self::Extension3|method2;
+  tearoff method2 = self::Extension3|get#method2;
+  method method3 = self::Extension3|method3;
+  tearoff method3 = self::Extension3|get#method3;
+  method method4 = self::Extension3|method4;
+  tearoff method4 = self::Extension3|get#method4;
+  method method5 = self::Extension3|method5;
+  tearoff method5 = self::Extension3|get#method5;
+}
+extension Extension4<T extends core::Object? = dynamic> on T% {
+  method method1 = self::Extension4|method1;
+  tearoff method1 = self::Extension4|get#method1;
+  method method2 = self::Extension4|method2;
+  tearoff method2 = self::Extension4|get#method2;
+  method method3 = self::Extension4|method3;
+  tearoff method3 = self::Extension4|get#method3;
+  method method4 = self::Extension4|method4;
+  tearoff method4 = self::Extension4|get#method4;
+  method method5 = self::Extension4|method5;
+  tearoff method5 = self::Extension4|get#method5;
+}
+extension Extension5<T extends core::Object? = core::Object?> on T% {
+  method method1 = self::Extension5|method1;
+  tearoff method1 = self::Extension5|get#method1;
+  method method2 = self::Extension5|method2;
+  tearoff method2 = self::Extension5|get#method2;
+  method method3 = self::Extension5|method3;
+  tearoff method3 = self::Extension5|get#method3;
+  method method4 = self::Extension5|method4;
+  tearoff method4 = self::Extension5|get#method4;
+  method method5 = self::Extension5|method5;
+  tearoff method5 = self::Extension5|get#method5;
+}
+static method Extension1|method1<T extends core::Object = core::Object, S extends core::Object = core::Object>(final self::Extension1|method1::T #this) → dynamic
+  ;
+static method Extension1|get#method1<T extends core::Object = core::Object>(final self::Extension1|get#method1::T #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension1|method1<self::Extension1|get#method1::T, S>(#this);
+static method Extension1|method2<T extends core::Object = core::Object, S extends core::String = core::String>(final self::Extension1|method2::T #this) → dynamic
+  ;
+static method Extension1|get#method2<T extends core::Object = core::Object>(final self::Extension1|get#method2::T #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension1|method2<self::Extension1|get#method2::T, S>(#this);
+static method Extension1|method3<T extends core::Object = core::Object, S extends dynamic = dynamic>(final self::Extension1|method3::T #this) → dynamic
+  ;
+static method Extension1|get#method3<T extends core::Object = core::Object>(final self::Extension1|get#method3::T #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension1|method3<self::Extension1|get#method3::T, S%>(#this);
+static method Extension1|method4<T extends core::Object = core::Object, S extends core::Object? = dynamic>(final self::Extension1|method4::T #this) → dynamic
+  ;
+static method Extension1|get#method4<T extends core::Object = core::Object>(final self::Extension1|get#method4::T #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension1|method4<self::Extension1|get#method4::T, S%>(#this);
+static method Extension1|method5<T extends core::Object = core::Object, S extends core::Object? = core::Object?>(final self::Extension1|method5::T #this) → dynamic
+  ;
+static method Extension1|get#method5<T extends core::Object = core::Object>(final self::Extension1|get#method5::T #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension1|method5<self::Extension1|get#method5::T, S%>(#this);
+static method Extension2|method1<T extends core::String = core::String, S extends core::Object = core::Object>(final self::Extension2|method1::T #this) → dynamic
+  ;
+static method Extension2|get#method1<T extends core::String = core::String>(final self::Extension2|get#method1::T #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension2|method1<self::Extension2|get#method1::T, S>(#this);
+static method Extension2|method2<T extends core::String = core::String, S extends core::String = core::String>(final self::Extension2|method2::T #this) → dynamic
+  ;
+static method Extension2|get#method2<T extends core::String = core::String>(final self::Extension2|get#method2::T #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension2|method2<self::Extension2|get#method2::T, S>(#this);
+static method Extension2|method3<T extends core::String = core::String, S extends dynamic = dynamic>(final self::Extension2|method3::T #this) → dynamic
+  ;
+static method Extension2|get#method3<T extends core::String = core::String>(final self::Extension2|get#method3::T #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension2|method3<self::Extension2|get#method3::T, S%>(#this);
+static method Extension2|get#method4<T extends core::String = core::String>(final self::Extension2|get#method4::T #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension2|method4<self::Extension2|get#method4::T, S%>(#this);
+static method Extension2|method4<T extends core::String = core::String, S extends core::Object? = dynamic>(final self::Extension2|method4::T #this) → dynamic
+  ;
+static method Extension2|method5<T extends core::String = core::String, S extends core::Object? = core::Object?>(final self::Extension2|method5::T #this) → dynamic
+  ;
+static method Extension2|get#method5<T extends core::String = core::String>(final self::Extension2|get#method5::T #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension2|method5<self::Extension2|get#method5::T, S%>(#this);
+static method Extension3|method1<T extends dynamic = dynamic, S extends core::Object = core::Object>(final self::Extension3|method1::T% #this) → dynamic
+  ;
+static method Extension3|get#method1<T extends dynamic = dynamic>(final self::Extension3|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension3|method1<self::Extension3|get#method1::T%, S>(#this);
+static method Extension3|method2<T extends dynamic = dynamic, S extends core::String = core::String>(final self::Extension3|method2::T% #this) → dynamic
+  ;
+static method Extension3|get#method2<T extends dynamic = dynamic>(final self::Extension3|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension3|method2<self::Extension3|get#method2::T%, S>(#this);
+static method Extension3|method3<T extends dynamic = dynamic, S extends dynamic = dynamic>(final self::Extension3|method3::T% #this) → dynamic
+  ;
+static method Extension3|get#method3<T extends dynamic = dynamic>(final self::Extension3|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension3|method3<self::Extension3|get#method3::T%, S%>(#this);
+static method Extension3|method4<T extends dynamic = dynamic, S extends core::Object? = dynamic>(final self::Extension3|method4::T% #this) → dynamic
+  ;
+static method Extension3|get#method4<T extends dynamic = dynamic>(final self::Extension3|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension3|method4<self::Extension3|get#method4::T%, S%>(#this);
+static method Extension3|method5<T extends dynamic = dynamic, S extends core::Object? = core::Object?>(final self::Extension3|method5::T% #this) → dynamic
+  ;
+static method Extension3|get#method5<T extends dynamic = dynamic>(final self::Extension3|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension3|method5<self::Extension3|get#method5::T%, S%>(#this);
+static method Extension4|method1<T extends core::Object? = dynamic, S extends core::Object = core::Object>(final self::Extension4|method1::T% #this) → dynamic
+  ;
+static method Extension4|get#method1<T extends core::Object? = dynamic>(final self::Extension4|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension4|method1<self::Extension4|get#method1::T%, S>(#this);
+static method Extension4|method2<T extends core::Object? = dynamic, S extends core::String = core::String>(final self::Extension4|method2::T% #this) → dynamic
+  ;
+static method Extension4|get#method2<T extends core::Object? = dynamic>(final self::Extension4|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension4|method2<self::Extension4|get#method2::T%, S>(#this);
+static method Extension4|method3<T extends core::Object? = dynamic, S extends dynamic = dynamic>(final self::Extension4|method3::T% #this) → dynamic
+  ;
+static method Extension4|get#method3<T extends core::Object? = dynamic>(final self::Extension4|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension4|method3<self::Extension4|get#method3::T%, S%>(#this);
+static method Extension4|method4<T extends core::Object? = dynamic, S extends core::Object? = dynamic>(final self::Extension4|method4::T% #this) → dynamic
+  ;
+static method Extension4|get#method4<T extends core::Object? = dynamic>(final self::Extension4|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension4|method4<self::Extension4|get#method4::T%, S%>(#this);
+static method Extension4|method5<T extends core::Object? = dynamic, S extends core::Object? = core::Object?>(final self::Extension4|method5::T% #this) → dynamic
+  ;
+static method Extension4|get#method5<T extends core::Object? = dynamic>(final self::Extension4|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension4|method5<self::Extension4|get#method5::T%, S%>(#this);
+static method Extension5|method1<T extends core::Object? = core::Object?, S extends core::Object = core::Object>(final self::Extension5|method1::T% #this) → dynamic
+  ;
+static method Extension5|get#method1<T extends core::Object? = core::Object?>(final self::Extension5|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension5|method1<self::Extension5|get#method1::T%, S>(#this);
+static method Extension5|method2<T extends core::Object? = core::Object?, S extends core::String = core::String>(final self::Extension5|method2::T% #this) → dynamic
+  ;
+static method Extension5|get#method2<T extends core::Object? = core::Object?>(final self::Extension5|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension5|method2<self::Extension5|get#method2::T%, S>(#this);
+static method Extension5|method3<T extends core::Object? = core::Object?, S extends dynamic = dynamic>(final self::Extension5|method3::T% #this) → dynamic
+  ;
+static method Extension5|get#method3<T extends core::Object? = core::Object?>(final self::Extension5|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension5|method3<self::Extension5|get#method3::T%, S%>(#this);
+static method Extension5|method4<T extends core::Object? = core::Object?, S extends core::Object? = dynamic>(final self::Extension5|method4::T% #this) → dynamic
+  ;
+static method Extension5|get#method4<T extends core::Object? = core::Object?>(final self::Extension5|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension5|method4<self::Extension5|get#method4::T%, S%>(#this);
+static method Extension5|method5<T extends core::Object? = core::Object?, S extends core::Object? = core::Object?>(final self::Extension5|method5::T% #this) → dynamic
+  ;
+static method Extension5|get#method5<T extends core::Object? = core::Object?>(final self::Extension5|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension5|method5<self::Extension5|get#method5::T%, S%>(#this);
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/extension_bounds.dart.strong.expect b/pkg/front_end/testcases/nnbd/extension_bounds.dart.strong.expect
new file mode 100644
index 0000000..0cf68fa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_bounds.dart.strong.expect
@@ -0,0 +1,140 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+extension Extension1<T extends core::Object = core::Object> on T {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+  method method3 = self::Extension1|method3;
+  tearoff method3 = self::Extension1|get#method3;
+  method method4 = self::Extension1|method4;
+  tearoff method4 = self::Extension1|get#method4;
+  method method5 = self::Extension1|method5;
+  tearoff method5 = self::Extension1|get#method5;
+}
+extension Extension2<T extends core::String = core::String> on T {
+  method method1 = self::Extension2|method1;
+  tearoff method1 = self::Extension2|get#method1;
+  method method2 = self::Extension2|method2;
+  tearoff method2 = self::Extension2|get#method2;
+  method method3 = self::Extension2|method3;
+  tearoff method3 = self::Extension2|get#method3;
+  method method4 = self::Extension2|method4;
+  tearoff method4 = self::Extension2|get#method4;
+  method method5 = self::Extension2|method5;
+  tearoff method5 = self::Extension2|get#method5;
+}
+extension Extension3<T extends dynamic = dynamic> on T% {
+  method method1 = self::Extension3|method1;
+  tearoff method1 = self::Extension3|get#method1;
+  method method2 = self::Extension3|method2;
+  tearoff method2 = self::Extension3|get#method2;
+  method method3 = self::Extension3|method3;
+  tearoff method3 = self::Extension3|get#method3;
+  method method4 = self::Extension3|method4;
+  tearoff method4 = self::Extension3|get#method4;
+  method method5 = self::Extension3|method5;
+  tearoff method5 = self::Extension3|get#method5;
+}
+extension Extension4<T extends core::Object? = dynamic> on T% {
+  method method1 = self::Extension4|method1;
+  tearoff method1 = self::Extension4|get#method1;
+  method method2 = self::Extension4|method2;
+  tearoff method2 = self::Extension4|get#method2;
+  method method3 = self::Extension4|method3;
+  tearoff method3 = self::Extension4|get#method3;
+  method method4 = self::Extension4|method4;
+  tearoff method4 = self::Extension4|get#method4;
+  method method5 = self::Extension4|method5;
+  tearoff method5 = self::Extension4|get#method5;
+}
+extension Extension5<T extends core::Object? = core::Object?> on T% {
+  method method1 = self::Extension5|method1;
+  tearoff method1 = self::Extension5|get#method1;
+  method method2 = self::Extension5|method2;
+  tearoff method2 = self::Extension5|get#method2;
+  method method3 = self::Extension5|method3;
+  tearoff method3 = self::Extension5|get#method3;
+  method method4 = self::Extension5|method4;
+  tearoff method4 = self::Extension5|get#method4;
+  method method5 = self::Extension5|method5;
+  tearoff method5 = self::Extension5|get#method5;
+}
+static method Extension1|method1<T extends core::Object = core::Object, S extends core::Object = core::Object>(final self::Extension1|method1::T #this) → dynamic {}
+static method Extension1|get#method1<T extends core::Object = core::Object>(final self::Extension1|get#method1::T #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension1|method1<self::Extension1|get#method1::T, S>(#this);
+static method Extension1|method2<T extends core::Object = core::Object, S extends core::String = core::String>(final self::Extension1|method2::T #this) → dynamic {}
+static method Extension1|get#method2<T extends core::Object = core::Object>(final self::Extension1|get#method2::T #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension1|method2<self::Extension1|get#method2::T, S>(#this);
+static method Extension1|method3<T extends core::Object = core::Object, S extends dynamic = dynamic>(final self::Extension1|method3::T #this) → dynamic {}
+static method Extension1|get#method3<T extends core::Object = core::Object>(final self::Extension1|get#method3::T #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension1|method3<self::Extension1|get#method3::T, S%>(#this);
+static method Extension1|method4<T extends core::Object = core::Object, S extends core::Object? = dynamic>(final self::Extension1|method4::T #this) → dynamic {}
+static method Extension1|get#method4<T extends core::Object = core::Object>(final self::Extension1|get#method4::T #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension1|method4<self::Extension1|get#method4::T, S%>(#this);
+static method Extension1|method5<T extends core::Object = core::Object, S extends core::Object? = core::Object?>(final self::Extension1|method5::T #this) → dynamic {}
+static method Extension1|get#method5<T extends core::Object = core::Object>(final self::Extension1|get#method5::T #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension1|method5<self::Extension1|get#method5::T, S%>(#this);
+static method Extension2|method1<T extends core::String = core::String, S extends core::Object = core::Object>(final self::Extension2|method1::T #this) → dynamic {}
+static method Extension2|get#method1<T extends core::String = core::String>(final self::Extension2|get#method1::T #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension2|method1<self::Extension2|get#method1::T, S>(#this);
+static method Extension2|method2<T extends core::String = core::String, S extends core::String = core::String>(final self::Extension2|method2::T #this) → dynamic {}
+static method Extension2|get#method2<T extends core::String = core::String>(final self::Extension2|get#method2::T #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension2|method2<self::Extension2|get#method2::T, S>(#this);
+static method Extension2|method3<T extends core::String = core::String, S extends dynamic = dynamic>(final self::Extension2|method3::T #this) → dynamic {}
+static method Extension2|get#method3<T extends core::String = core::String>(final self::Extension2|get#method3::T #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension2|method3<self::Extension2|get#method3::T, S%>(#this);
+static method Extension2|get#method4<T extends core::String = core::String>(final self::Extension2|get#method4::T #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension2|method4<self::Extension2|get#method4::T, S%>(#this);
+static method Extension2|method4<T extends core::String = core::String, S extends core::Object? = dynamic>(final self::Extension2|method4::T #this) → dynamic {}
+static method Extension2|method5<T extends core::String = core::String, S extends core::Object? = core::Object?>(final self::Extension2|method5::T #this) → dynamic {}
+static method Extension2|get#method5<T extends core::String = core::String>(final self::Extension2|get#method5::T #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension2|method5<self::Extension2|get#method5::T, S%>(#this);
+static method Extension3|method1<T extends dynamic = dynamic, S extends core::Object = core::Object>(final self::Extension3|method1::T% #this) → dynamic {}
+static method Extension3|get#method1<T extends dynamic = dynamic>(final self::Extension3|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension3|method1<self::Extension3|get#method1::T%, S>(#this);
+static method Extension3|method2<T extends dynamic = dynamic, S extends core::String = core::String>(final self::Extension3|method2::T% #this) → dynamic {}
+static method Extension3|get#method2<T extends dynamic = dynamic>(final self::Extension3|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension3|method2<self::Extension3|get#method2::T%, S>(#this);
+static method Extension3|method3<T extends dynamic = dynamic, S extends dynamic = dynamic>(final self::Extension3|method3::T% #this) → dynamic {}
+static method Extension3|get#method3<T extends dynamic = dynamic>(final self::Extension3|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension3|method3<self::Extension3|get#method3::T%, S%>(#this);
+static method Extension3|method4<T extends dynamic = dynamic, S extends core::Object? = dynamic>(final self::Extension3|method4::T% #this) → dynamic {}
+static method Extension3|get#method4<T extends dynamic = dynamic>(final self::Extension3|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension3|method4<self::Extension3|get#method4::T%, S%>(#this);
+static method Extension3|method5<T extends dynamic = dynamic, S extends core::Object? = core::Object?>(final self::Extension3|method5::T% #this) → dynamic {}
+static method Extension3|get#method5<T extends dynamic = dynamic>(final self::Extension3|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension3|method5<self::Extension3|get#method5::T%, S%>(#this);
+static method Extension4|method1<T extends core::Object? = dynamic, S extends core::Object = core::Object>(final self::Extension4|method1::T% #this) → dynamic {}
+static method Extension4|get#method1<T extends core::Object? = dynamic>(final self::Extension4|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension4|method1<self::Extension4|get#method1::T%, S>(#this);
+static method Extension4|method2<T extends core::Object? = dynamic, S extends core::String = core::String>(final self::Extension4|method2::T% #this) → dynamic {}
+static method Extension4|get#method2<T extends core::Object? = dynamic>(final self::Extension4|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension4|method2<self::Extension4|get#method2::T%, S>(#this);
+static method Extension4|method3<T extends core::Object? = dynamic, S extends dynamic = dynamic>(final self::Extension4|method3::T% #this) → dynamic {}
+static method Extension4|get#method3<T extends core::Object? = dynamic>(final self::Extension4|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension4|method3<self::Extension4|get#method3::T%, S%>(#this);
+static method Extension4|method4<T extends core::Object? = dynamic, S extends core::Object? = dynamic>(final self::Extension4|method4::T% #this) → dynamic {}
+static method Extension4|get#method4<T extends core::Object? = dynamic>(final self::Extension4|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension4|method4<self::Extension4|get#method4::T%, S%>(#this);
+static method Extension4|method5<T extends core::Object? = dynamic, S extends core::Object? = core::Object?>(final self::Extension4|method5::T% #this) → dynamic {}
+static method Extension4|get#method5<T extends core::Object? = dynamic>(final self::Extension4|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension4|method5<self::Extension4|get#method5::T%, S%>(#this);
+static method Extension5|method1<T extends core::Object? = core::Object?, S extends core::Object = core::Object>(final self::Extension5|method1::T% #this) → dynamic {}
+static method Extension5|get#method1<T extends core::Object? = core::Object?>(final self::Extension5|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension5|method1<self::Extension5|get#method1::T%, S>(#this);
+static method Extension5|method2<T extends core::Object? = core::Object?, S extends core::String = core::String>(final self::Extension5|method2::T% #this) → dynamic {}
+static method Extension5|get#method2<T extends core::Object? = core::Object?>(final self::Extension5|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension5|method2<self::Extension5|get#method2::T%, S>(#this);
+static method Extension5|method3<T extends core::Object? = core::Object?, S extends dynamic = dynamic>(final self::Extension5|method3::T% #this) → dynamic {}
+static method Extension5|get#method3<T extends core::Object? = core::Object?>(final self::Extension5|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension5|method3<self::Extension5|get#method3::T%, S%>(#this);
+static method Extension5|method4<T extends core::Object? = core::Object?, S extends core::Object? = dynamic>(final self::Extension5|method4::T% #this) → dynamic {}
+static method Extension5|get#method4<T extends core::Object? = core::Object?>(final self::Extension5|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension5|method4<self::Extension5|get#method4::T%, S%>(#this);
+static method Extension5|method5<T extends core::Object? = core::Object?, S extends core::Object? = core::Object?>(final self::Extension5|method5::T% #this) → dynamic {}
+static method Extension5|get#method5<T extends core::Object? = core::Object?>(final self::Extension5|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension5|method5<self::Extension5|get#method5::T%, S%>(#this);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/extension_bounds.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/extension_bounds.dart.strong.transformed.expect
new file mode 100644
index 0000000..0cf68fa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_bounds.dart.strong.transformed.expect
@@ -0,0 +1,140 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+extension Extension1<T extends core::Object = core::Object> on T {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+  method method3 = self::Extension1|method3;
+  tearoff method3 = self::Extension1|get#method3;
+  method method4 = self::Extension1|method4;
+  tearoff method4 = self::Extension1|get#method4;
+  method method5 = self::Extension1|method5;
+  tearoff method5 = self::Extension1|get#method5;
+}
+extension Extension2<T extends core::String = core::String> on T {
+  method method1 = self::Extension2|method1;
+  tearoff method1 = self::Extension2|get#method1;
+  method method2 = self::Extension2|method2;
+  tearoff method2 = self::Extension2|get#method2;
+  method method3 = self::Extension2|method3;
+  tearoff method3 = self::Extension2|get#method3;
+  method method4 = self::Extension2|method4;
+  tearoff method4 = self::Extension2|get#method4;
+  method method5 = self::Extension2|method5;
+  tearoff method5 = self::Extension2|get#method5;
+}
+extension Extension3<T extends dynamic = dynamic> on T% {
+  method method1 = self::Extension3|method1;
+  tearoff method1 = self::Extension3|get#method1;
+  method method2 = self::Extension3|method2;
+  tearoff method2 = self::Extension3|get#method2;
+  method method3 = self::Extension3|method3;
+  tearoff method3 = self::Extension3|get#method3;
+  method method4 = self::Extension3|method4;
+  tearoff method4 = self::Extension3|get#method4;
+  method method5 = self::Extension3|method5;
+  tearoff method5 = self::Extension3|get#method5;
+}
+extension Extension4<T extends core::Object? = dynamic> on T% {
+  method method1 = self::Extension4|method1;
+  tearoff method1 = self::Extension4|get#method1;
+  method method2 = self::Extension4|method2;
+  tearoff method2 = self::Extension4|get#method2;
+  method method3 = self::Extension4|method3;
+  tearoff method3 = self::Extension4|get#method3;
+  method method4 = self::Extension4|method4;
+  tearoff method4 = self::Extension4|get#method4;
+  method method5 = self::Extension4|method5;
+  tearoff method5 = self::Extension4|get#method5;
+}
+extension Extension5<T extends core::Object? = core::Object?> on T% {
+  method method1 = self::Extension5|method1;
+  tearoff method1 = self::Extension5|get#method1;
+  method method2 = self::Extension5|method2;
+  tearoff method2 = self::Extension5|get#method2;
+  method method3 = self::Extension5|method3;
+  tearoff method3 = self::Extension5|get#method3;
+  method method4 = self::Extension5|method4;
+  tearoff method4 = self::Extension5|get#method4;
+  method method5 = self::Extension5|method5;
+  tearoff method5 = self::Extension5|get#method5;
+}
+static method Extension1|method1<T extends core::Object = core::Object, S extends core::Object = core::Object>(final self::Extension1|method1::T #this) → dynamic {}
+static method Extension1|get#method1<T extends core::Object = core::Object>(final self::Extension1|get#method1::T #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension1|method1<self::Extension1|get#method1::T, S>(#this);
+static method Extension1|method2<T extends core::Object = core::Object, S extends core::String = core::String>(final self::Extension1|method2::T #this) → dynamic {}
+static method Extension1|get#method2<T extends core::Object = core::Object>(final self::Extension1|get#method2::T #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension1|method2<self::Extension1|get#method2::T, S>(#this);
+static method Extension1|method3<T extends core::Object = core::Object, S extends dynamic = dynamic>(final self::Extension1|method3::T #this) → dynamic {}
+static method Extension1|get#method3<T extends core::Object = core::Object>(final self::Extension1|get#method3::T #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension1|method3<self::Extension1|get#method3::T, S%>(#this);
+static method Extension1|method4<T extends core::Object = core::Object, S extends core::Object? = dynamic>(final self::Extension1|method4::T #this) → dynamic {}
+static method Extension1|get#method4<T extends core::Object = core::Object>(final self::Extension1|get#method4::T #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension1|method4<self::Extension1|get#method4::T, S%>(#this);
+static method Extension1|method5<T extends core::Object = core::Object, S extends core::Object? = core::Object?>(final self::Extension1|method5::T #this) → dynamic {}
+static method Extension1|get#method5<T extends core::Object = core::Object>(final self::Extension1|get#method5::T #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension1|method5<self::Extension1|get#method5::T, S%>(#this);
+static method Extension2|method1<T extends core::String = core::String, S extends core::Object = core::Object>(final self::Extension2|method1::T #this) → dynamic {}
+static method Extension2|get#method1<T extends core::String = core::String>(final self::Extension2|get#method1::T #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension2|method1<self::Extension2|get#method1::T, S>(#this);
+static method Extension2|method2<T extends core::String = core::String, S extends core::String = core::String>(final self::Extension2|method2::T #this) → dynamic {}
+static method Extension2|get#method2<T extends core::String = core::String>(final self::Extension2|get#method2::T #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension2|method2<self::Extension2|get#method2::T, S>(#this);
+static method Extension2|method3<T extends core::String = core::String, S extends dynamic = dynamic>(final self::Extension2|method3::T #this) → dynamic {}
+static method Extension2|get#method3<T extends core::String = core::String>(final self::Extension2|get#method3::T #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension2|method3<self::Extension2|get#method3::T, S%>(#this);
+static method Extension2|get#method4<T extends core::String = core::String>(final self::Extension2|get#method4::T #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension2|method4<self::Extension2|get#method4::T, S%>(#this);
+static method Extension2|method4<T extends core::String = core::String, S extends core::Object? = dynamic>(final self::Extension2|method4::T #this) → dynamic {}
+static method Extension2|method5<T extends core::String = core::String, S extends core::Object? = core::Object?>(final self::Extension2|method5::T #this) → dynamic {}
+static method Extension2|get#method5<T extends core::String = core::String>(final self::Extension2|get#method5::T #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension2|method5<self::Extension2|get#method5::T, S%>(#this);
+static method Extension3|method1<T extends dynamic = dynamic, S extends core::Object = core::Object>(final self::Extension3|method1::T% #this) → dynamic {}
+static method Extension3|get#method1<T extends dynamic = dynamic>(final self::Extension3|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension3|method1<self::Extension3|get#method1::T%, S>(#this);
+static method Extension3|method2<T extends dynamic = dynamic, S extends core::String = core::String>(final self::Extension3|method2::T% #this) → dynamic {}
+static method Extension3|get#method2<T extends dynamic = dynamic>(final self::Extension3|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension3|method2<self::Extension3|get#method2::T%, S>(#this);
+static method Extension3|method3<T extends dynamic = dynamic, S extends dynamic = dynamic>(final self::Extension3|method3::T% #this) → dynamic {}
+static method Extension3|get#method3<T extends dynamic = dynamic>(final self::Extension3|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension3|method3<self::Extension3|get#method3::T%, S%>(#this);
+static method Extension3|method4<T extends dynamic = dynamic, S extends core::Object? = dynamic>(final self::Extension3|method4::T% #this) → dynamic {}
+static method Extension3|get#method4<T extends dynamic = dynamic>(final self::Extension3|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension3|method4<self::Extension3|get#method4::T%, S%>(#this);
+static method Extension3|method5<T extends dynamic = dynamic, S extends core::Object? = core::Object?>(final self::Extension3|method5::T% #this) → dynamic {}
+static method Extension3|get#method5<T extends dynamic = dynamic>(final self::Extension3|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension3|method5<self::Extension3|get#method5::T%, S%>(#this);
+static method Extension4|method1<T extends core::Object? = dynamic, S extends core::Object = core::Object>(final self::Extension4|method1::T% #this) → dynamic {}
+static method Extension4|get#method1<T extends core::Object? = dynamic>(final self::Extension4|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension4|method1<self::Extension4|get#method1::T%, S>(#this);
+static method Extension4|method2<T extends core::Object? = dynamic, S extends core::String = core::String>(final self::Extension4|method2::T% #this) → dynamic {}
+static method Extension4|get#method2<T extends core::Object? = dynamic>(final self::Extension4|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension4|method2<self::Extension4|get#method2::T%, S>(#this);
+static method Extension4|method3<T extends core::Object? = dynamic, S extends dynamic = dynamic>(final self::Extension4|method3::T% #this) → dynamic {}
+static method Extension4|get#method3<T extends core::Object? = dynamic>(final self::Extension4|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension4|method3<self::Extension4|get#method3::T%, S%>(#this);
+static method Extension4|method4<T extends core::Object? = dynamic, S extends core::Object? = dynamic>(final self::Extension4|method4::T% #this) → dynamic {}
+static method Extension4|get#method4<T extends core::Object? = dynamic>(final self::Extension4|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension4|method4<self::Extension4|get#method4::T%, S%>(#this);
+static method Extension4|method5<T extends core::Object? = dynamic, S extends core::Object? = core::Object?>(final self::Extension4|method5::T% #this) → dynamic {}
+static method Extension4|get#method5<T extends core::Object? = dynamic>(final self::Extension4|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension4|method5<self::Extension4|get#method5::T%, S%>(#this);
+static method Extension5|method1<T extends core::Object? = core::Object?, S extends core::Object = core::Object>(final self::Extension5|method1::T% #this) → dynamic {}
+static method Extension5|get#method1<T extends core::Object? = core::Object?>(final self::Extension5|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension5|method1<self::Extension5|get#method1::T%, S>(#this);
+static method Extension5|method2<T extends core::Object? = core::Object?, S extends core::String = core::String>(final self::Extension5|method2::T% #this) → dynamic {}
+static method Extension5|get#method2<T extends core::Object? = core::Object?>(final self::Extension5|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension5|method2<self::Extension5|get#method2::T%, S>(#this);
+static method Extension5|method3<T extends core::Object? = core::Object?, S extends dynamic = dynamic>(final self::Extension5|method3::T% #this) → dynamic {}
+static method Extension5|get#method3<T extends core::Object? = core::Object?>(final self::Extension5|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension5|method3<self::Extension5|get#method3::T%, S%>(#this);
+static method Extension5|method4<T extends core::Object? = core::Object?, S extends core::Object? = dynamic>(final self::Extension5|method4::T% #this) → dynamic {}
+static method Extension5|get#method4<T extends core::Object? = core::Object?>(final self::Extension5|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension5|method4<self::Extension5|get#method4::T%, S%>(#this);
+static method Extension5|method5<T extends core::Object? = core::Object?, S extends core::Object? = core::Object?>(final self::Extension5|method5::T% #this) → dynamic {}
+static method Extension5|get#method5<T extends core::Object? = core::Object?>(final self::Extension5|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension5|method5<self::Extension5|get#method5::T%, S%>(#this);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline.expect
new file mode 100644
index 0000000..ad8ddc8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline.expect
@@ -0,0 +1,11 @@
+extension Extension1<T extends Object> (){}
+on T (){}
+extension Extension2<T extends String> (){}
+on T (){}
+extension Extension3<T extends dynamic> (){}
+on T (){}
+extension Extension4<T> (){}
+on T (){}
+extension Extension5<T extends Object?> (){}
+on T (){}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/extension_bounds.dart.weak.expect b/pkg/front_end/testcases/nnbd/extension_bounds.dart.weak.expect
new file mode 100644
index 0000000..0cf68fa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_bounds.dart.weak.expect
@@ -0,0 +1,140 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+extension Extension1<T extends core::Object = core::Object> on T {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+  method method3 = self::Extension1|method3;
+  tearoff method3 = self::Extension1|get#method3;
+  method method4 = self::Extension1|method4;
+  tearoff method4 = self::Extension1|get#method4;
+  method method5 = self::Extension1|method5;
+  tearoff method5 = self::Extension1|get#method5;
+}
+extension Extension2<T extends core::String = core::String> on T {
+  method method1 = self::Extension2|method1;
+  tearoff method1 = self::Extension2|get#method1;
+  method method2 = self::Extension2|method2;
+  tearoff method2 = self::Extension2|get#method2;
+  method method3 = self::Extension2|method3;
+  tearoff method3 = self::Extension2|get#method3;
+  method method4 = self::Extension2|method4;
+  tearoff method4 = self::Extension2|get#method4;
+  method method5 = self::Extension2|method5;
+  tearoff method5 = self::Extension2|get#method5;
+}
+extension Extension3<T extends dynamic = dynamic> on T% {
+  method method1 = self::Extension3|method1;
+  tearoff method1 = self::Extension3|get#method1;
+  method method2 = self::Extension3|method2;
+  tearoff method2 = self::Extension3|get#method2;
+  method method3 = self::Extension3|method3;
+  tearoff method3 = self::Extension3|get#method3;
+  method method4 = self::Extension3|method4;
+  tearoff method4 = self::Extension3|get#method4;
+  method method5 = self::Extension3|method5;
+  tearoff method5 = self::Extension3|get#method5;
+}
+extension Extension4<T extends core::Object? = dynamic> on T% {
+  method method1 = self::Extension4|method1;
+  tearoff method1 = self::Extension4|get#method1;
+  method method2 = self::Extension4|method2;
+  tearoff method2 = self::Extension4|get#method2;
+  method method3 = self::Extension4|method3;
+  tearoff method3 = self::Extension4|get#method3;
+  method method4 = self::Extension4|method4;
+  tearoff method4 = self::Extension4|get#method4;
+  method method5 = self::Extension4|method5;
+  tearoff method5 = self::Extension4|get#method5;
+}
+extension Extension5<T extends core::Object? = core::Object?> on T% {
+  method method1 = self::Extension5|method1;
+  tearoff method1 = self::Extension5|get#method1;
+  method method2 = self::Extension5|method2;
+  tearoff method2 = self::Extension5|get#method2;
+  method method3 = self::Extension5|method3;
+  tearoff method3 = self::Extension5|get#method3;
+  method method4 = self::Extension5|method4;
+  tearoff method4 = self::Extension5|get#method4;
+  method method5 = self::Extension5|method5;
+  tearoff method5 = self::Extension5|get#method5;
+}
+static method Extension1|method1<T extends core::Object = core::Object, S extends core::Object = core::Object>(final self::Extension1|method1::T #this) → dynamic {}
+static method Extension1|get#method1<T extends core::Object = core::Object>(final self::Extension1|get#method1::T #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension1|method1<self::Extension1|get#method1::T, S>(#this);
+static method Extension1|method2<T extends core::Object = core::Object, S extends core::String = core::String>(final self::Extension1|method2::T #this) → dynamic {}
+static method Extension1|get#method2<T extends core::Object = core::Object>(final self::Extension1|get#method2::T #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension1|method2<self::Extension1|get#method2::T, S>(#this);
+static method Extension1|method3<T extends core::Object = core::Object, S extends dynamic = dynamic>(final self::Extension1|method3::T #this) → dynamic {}
+static method Extension1|get#method3<T extends core::Object = core::Object>(final self::Extension1|get#method3::T #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension1|method3<self::Extension1|get#method3::T, S%>(#this);
+static method Extension1|method4<T extends core::Object = core::Object, S extends core::Object? = dynamic>(final self::Extension1|method4::T #this) → dynamic {}
+static method Extension1|get#method4<T extends core::Object = core::Object>(final self::Extension1|get#method4::T #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension1|method4<self::Extension1|get#method4::T, S%>(#this);
+static method Extension1|method5<T extends core::Object = core::Object, S extends core::Object? = core::Object?>(final self::Extension1|method5::T #this) → dynamic {}
+static method Extension1|get#method5<T extends core::Object = core::Object>(final self::Extension1|get#method5::T #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension1|method5<self::Extension1|get#method5::T, S%>(#this);
+static method Extension2|method1<T extends core::String = core::String, S extends core::Object = core::Object>(final self::Extension2|method1::T #this) → dynamic {}
+static method Extension2|get#method1<T extends core::String = core::String>(final self::Extension2|get#method1::T #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension2|method1<self::Extension2|get#method1::T, S>(#this);
+static method Extension2|method2<T extends core::String = core::String, S extends core::String = core::String>(final self::Extension2|method2::T #this) → dynamic {}
+static method Extension2|get#method2<T extends core::String = core::String>(final self::Extension2|get#method2::T #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension2|method2<self::Extension2|get#method2::T, S>(#this);
+static method Extension2|method3<T extends core::String = core::String, S extends dynamic = dynamic>(final self::Extension2|method3::T #this) → dynamic {}
+static method Extension2|get#method3<T extends core::String = core::String>(final self::Extension2|get#method3::T #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension2|method3<self::Extension2|get#method3::T, S%>(#this);
+static method Extension2|get#method4<T extends core::String = core::String>(final self::Extension2|get#method4::T #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension2|method4<self::Extension2|get#method4::T, S%>(#this);
+static method Extension2|method4<T extends core::String = core::String, S extends core::Object? = dynamic>(final self::Extension2|method4::T #this) → dynamic {}
+static method Extension2|method5<T extends core::String = core::String, S extends core::Object? = core::Object?>(final self::Extension2|method5::T #this) → dynamic {}
+static method Extension2|get#method5<T extends core::String = core::String>(final self::Extension2|get#method5::T #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension2|method5<self::Extension2|get#method5::T, S%>(#this);
+static method Extension3|method1<T extends dynamic = dynamic, S extends core::Object = core::Object>(final self::Extension3|method1::T% #this) → dynamic {}
+static method Extension3|get#method1<T extends dynamic = dynamic>(final self::Extension3|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension3|method1<self::Extension3|get#method1::T%, S>(#this);
+static method Extension3|method2<T extends dynamic = dynamic, S extends core::String = core::String>(final self::Extension3|method2::T% #this) → dynamic {}
+static method Extension3|get#method2<T extends dynamic = dynamic>(final self::Extension3|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension3|method2<self::Extension3|get#method2::T%, S>(#this);
+static method Extension3|method3<T extends dynamic = dynamic, S extends dynamic = dynamic>(final self::Extension3|method3::T% #this) → dynamic {}
+static method Extension3|get#method3<T extends dynamic = dynamic>(final self::Extension3|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension3|method3<self::Extension3|get#method3::T%, S%>(#this);
+static method Extension3|method4<T extends dynamic = dynamic, S extends core::Object? = dynamic>(final self::Extension3|method4::T% #this) → dynamic {}
+static method Extension3|get#method4<T extends dynamic = dynamic>(final self::Extension3|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension3|method4<self::Extension3|get#method4::T%, S%>(#this);
+static method Extension3|method5<T extends dynamic = dynamic, S extends core::Object? = core::Object?>(final self::Extension3|method5::T% #this) → dynamic {}
+static method Extension3|get#method5<T extends dynamic = dynamic>(final self::Extension3|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension3|method5<self::Extension3|get#method5::T%, S%>(#this);
+static method Extension4|method1<T extends core::Object? = dynamic, S extends core::Object = core::Object>(final self::Extension4|method1::T% #this) → dynamic {}
+static method Extension4|get#method1<T extends core::Object? = dynamic>(final self::Extension4|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension4|method1<self::Extension4|get#method1::T%, S>(#this);
+static method Extension4|method2<T extends core::Object? = dynamic, S extends core::String = core::String>(final self::Extension4|method2::T% #this) → dynamic {}
+static method Extension4|get#method2<T extends core::Object? = dynamic>(final self::Extension4|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension4|method2<self::Extension4|get#method2::T%, S>(#this);
+static method Extension4|method3<T extends core::Object? = dynamic, S extends dynamic = dynamic>(final self::Extension4|method3::T% #this) → dynamic {}
+static method Extension4|get#method3<T extends core::Object? = dynamic>(final self::Extension4|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension4|method3<self::Extension4|get#method3::T%, S%>(#this);
+static method Extension4|method4<T extends core::Object? = dynamic, S extends core::Object? = dynamic>(final self::Extension4|method4::T% #this) → dynamic {}
+static method Extension4|get#method4<T extends core::Object? = dynamic>(final self::Extension4|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension4|method4<self::Extension4|get#method4::T%, S%>(#this);
+static method Extension4|method5<T extends core::Object? = dynamic, S extends core::Object? = core::Object?>(final self::Extension4|method5::T% #this) → dynamic {}
+static method Extension4|get#method5<T extends core::Object? = dynamic>(final self::Extension4|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension4|method5<self::Extension4|get#method5::T%, S%>(#this);
+static method Extension5|method1<T extends core::Object? = core::Object?, S extends core::Object = core::Object>(final self::Extension5|method1::T% #this) → dynamic {}
+static method Extension5|get#method1<T extends core::Object? = core::Object?>(final self::Extension5|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension5|method1<self::Extension5|get#method1::T%, S>(#this);
+static method Extension5|method2<T extends core::Object? = core::Object?, S extends core::String = core::String>(final self::Extension5|method2::T% #this) → dynamic {}
+static method Extension5|get#method2<T extends core::Object? = core::Object?>(final self::Extension5|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension5|method2<self::Extension5|get#method2::T%, S>(#this);
+static method Extension5|method3<T extends core::Object? = core::Object?, S extends dynamic = dynamic>(final self::Extension5|method3::T% #this) → dynamic {}
+static method Extension5|get#method3<T extends core::Object? = core::Object?>(final self::Extension5|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension5|method3<self::Extension5|get#method3::T%, S%>(#this);
+static method Extension5|method4<T extends core::Object? = core::Object?, S extends core::Object? = dynamic>(final self::Extension5|method4::T% #this) → dynamic {}
+static method Extension5|get#method4<T extends core::Object? = core::Object?>(final self::Extension5|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension5|method4<self::Extension5|get#method4::T%, S%>(#this);
+static method Extension5|method5<T extends core::Object? = core::Object?, S extends core::Object? = core::Object?>(final self::Extension5|method5::T% #this) → dynamic {}
+static method Extension5|get#method5<T extends core::Object? = core::Object?>(final self::Extension5|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension5|method5<self::Extension5|get#method5::T%, S%>(#this);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/extension_bounds.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/extension_bounds.dart.weak.transformed.expect
new file mode 100644
index 0000000..0cf68fa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_bounds.dart.weak.transformed.expect
@@ -0,0 +1,140 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+extension Extension1<T extends core::Object = core::Object> on T {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+  method method3 = self::Extension1|method3;
+  tearoff method3 = self::Extension1|get#method3;
+  method method4 = self::Extension1|method4;
+  tearoff method4 = self::Extension1|get#method4;
+  method method5 = self::Extension1|method5;
+  tearoff method5 = self::Extension1|get#method5;
+}
+extension Extension2<T extends core::String = core::String> on T {
+  method method1 = self::Extension2|method1;
+  tearoff method1 = self::Extension2|get#method1;
+  method method2 = self::Extension2|method2;
+  tearoff method2 = self::Extension2|get#method2;
+  method method3 = self::Extension2|method3;
+  tearoff method3 = self::Extension2|get#method3;
+  method method4 = self::Extension2|method4;
+  tearoff method4 = self::Extension2|get#method4;
+  method method5 = self::Extension2|method5;
+  tearoff method5 = self::Extension2|get#method5;
+}
+extension Extension3<T extends dynamic = dynamic> on T% {
+  method method1 = self::Extension3|method1;
+  tearoff method1 = self::Extension3|get#method1;
+  method method2 = self::Extension3|method2;
+  tearoff method2 = self::Extension3|get#method2;
+  method method3 = self::Extension3|method3;
+  tearoff method3 = self::Extension3|get#method3;
+  method method4 = self::Extension3|method4;
+  tearoff method4 = self::Extension3|get#method4;
+  method method5 = self::Extension3|method5;
+  tearoff method5 = self::Extension3|get#method5;
+}
+extension Extension4<T extends core::Object? = dynamic> on T% {
+  method method1 = self::Extension4|method1;
+  tearoff method1 = self::Extension4|get#method1;
+  method method2 = self::Extension4|method2;
+  tearoff method2 = self::Extension4|get#method2;
+  method method3 = self::Extension4|method3;
+  tearoff method3 = self::Extension4|get#method3;
+  method method4 = self::Extension4|method4;
+  tearoff method4 = self::Extension4|get#method4;
+  method method5 = self::Extension4|method5;
+  tearoff method5 = self::Extension4|get#method5;
+}
+extension Extension5<T extends core::Object? = core::Object?> on T% {
+  method method1 = self::Extension5|method1;
+  tearoff method1 = self::Extension5|get#method1;
+  method method2 = self::Extension5|method2;
+  tearoff method2 = self::Extension5|get#method2;
+  method method3 = self::Extension5|method3;
+  tearoff method3 = self::Extension5|get#method3;
+  method method4 = self::Extension5|method4;
+  tearoff method4 = self::Extension5|get#method4;
+  method method5 = self::Extension5|method5;
+  tearoff method5 = self::Extension5|get#method5;
+}
+static method Extension1|method1<T extends core::Object = core::Object, S extends core::Object = core::Object>(final self::Extension1|method1::T #this) → dynamic {}
+static method Extension1|get#method1<T extends core::Object = core::Object>(final self::Extension1|get#method1::T #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension1|method1<self::Extension1|get#method1::T, S>(#this);
+static method Extension1|method2<T extends core::Object = core::Object, S extends core::String = core::String>(final self::Extension1|method2::T #this) → dynamic {}
+static method Extension1|get#method2<T extends core::Object = core::Object>(final self::Extension1|get#method2::T #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension1|method2<self::Extension1|get#method2::T, S>(#this);
+static method Extension1|method3<T extends core::Object = core::Object, S extends dynamic = dynamic>(final self::Extension1|method3::T #this) → dynamic {}
+static method Extension1|get#method3<T extends core::Object = core::Object>(final self::Extension1|get#method3::T #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension1|method3<self::Extension1|get#method3::T, S%>(#this);
+static method Extension1|method4<T extends core::Object = core::Object, S extends core::Object? = dynamic>(final self::Extension1|method4::T #this) → dynamic {}
+static method Extension1|get#method4<T extends core::Object = core::Object>(final self::Extension1|get#method4::T #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension1|method4<self::Extension1|get#method4::T, S%>(#this);
+static method Extension1|method5<T extends core::Object = core::Object, S extends core::Object? = core::Object?>(final self::Extension1|method5::T #this) → dynamic {}
+static method Extension1|get#method5<T extends core::Object = core::Object>(final self::Extension1|get#method5::T #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension1|method5<self::Extension1|get#method5::T, S%>(#this);
+static method Extension2|method1<T extends core::String = core::String, S extends core::Object = core::Object>(final self::Extension2|method1::T #this) → dynamic {}
+static method Extension2|get#method1<T extends core::String = core::String>(final self::Extension2|get#method1::T #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension2|method1<self::Extension2|get#method1::T, S>(#this);
+static method Extension2|method2<T extends core::String = core::String, S extends core::String = core::String>(final self::Extension2|method2::T #this) → dynamic {}
+static method Extension2|get#method2<T extends core::String = core::String>(final self::Extension2|get#method2::T #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension2|method2<self::Extension2|get#method2::T, S>(#this);
+static method Extension2|method3<T extends core::String = core::String, S extends dynamic = dynamic>(final self::Extension2|method3::T #this) → dynamic {}
+static method Extension2|get#method3<T extends core::String = core::String>(final self::Extension2|get#method3::T #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension2|method3<self::Extension2|get#method3::T, S%>(#this);
+static method Extension2|get#method4<T extends core::String = core::String>(final self::Extension2|get#method4::T #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension2|method4<self::Extension2|get#method4::T, S%>(#this);
+static method Extension2|method4<T extends core::String = core::String, S extends core::Object? = dynamic>(final self::Extension2|method4::T #this) → dynamic {}
+static method Extension2|method5<T extends core::String = core::String, S extends core::Object? = core::Object?>(final self::Extension2|method5::T #this) → dynamic {}
+static method Extension2|get#method5<T extends core::String = core::String>(final self::Extension2|get#method5::T #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension2|method5<self::Extension2|get#method5::T, S%>(#this);
+static method Extension3|method1<T extends dynamic = dynamic, S extends core::Object = core::Object>(final self::Extension3|method1::T% #this) → dynamic {}
+static method Extension3|get#method1<T extends dynamic = dynamic>(final self::Extension3|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension3|method1<self::Extension3|get#method1::T%, S>(#this);
+static method Extension3|method2<T extends dynamic = dynamic, S extends core::String = core::String>(final self::Extension3|method2::T% #this) → dynamic {}
+static method Extension3|get#method2<T extends dynamic = dynamic>(final self::Extension3|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension3|method2<self::Extension3|get#method2::T%, S>(#this);
+static method Extension3|method3<T extends dynamic = dynamic, S extends dynamic = dynamic>(final self::Extension3|method3::T% #this) → dynamic {}
+static method Extension3|get#method3<T extends dynamic = dynamic>(final self::Extension3|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension3|method3<self::Extension3|get#method3::T%, S%>(#this);
+static method Extension3|method4<T extends dynamic = dynamic, S extends core::Object? = dynamic>(final self::Extension3|method4::T% #this) → dynamic {}
+static method Extension3|get#method4<T extends dynamic = dynamic>(final self::Extension3|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension3|method4<self::Extension3|get#method4::T%, S%>(#this);
+static method Extension3|method5<T extends dynamic = dynamic, S extends core::Object? = core::Object?>(final self::Extension3|method5::T% #this) → dynamic {}
+static method Extension3|get#method5<T extends dynamic = dynamic>(final self::Extension3|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension3|method5<self::Extension3|get#method5::T%, S%>(#this);
+static method Extension4|method1<T extends core::Object? = dynamic, S extends core::Object = core::Object>(final self::Extension4|method1::T% #this) → dynamic {}
+static method Extension4|get#method1<T extends core::Object? = dynamic>(final self::Extension4|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension4|method1<self::Extension4|get#method1::T%, S>(#this);
+static method Extension4|method2<T extends core::Object? = dynamic, S extends core::String = core::String>(final self::Extension4|method2::T% #this) → dynamic {}
+static method Extension4|get#method2<T extends core::Object? = dynamic>(final self::Extension4|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension4|method2<self::Extension4|get#method2::T%, S>(#this);
+static method Extension4|method3<T extends core::Object? = dynamic, S extends dynamic = dynamic>(final self::Extension4|method3::T% #this) → dynamic {}
+static method Extension4|get#method3<T extends core::Object? = dynamic>(final self::Extension4|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension4|method3<self::Extension4|get#method3::T%, S%>(#this);
+static method Extension4|method4<T extends core::Object? = dynamic, S extends core::Object? = dynamic>(final self::Extension4|method4::T% #this) → dynamic {}
+static method Extension4|get#method4<T extends core::Object? = dynamic>(final self::Extension4|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension4|method4<self::Extension4|get#method4::T%, S%>(#this);
+static method Extension4|method5<T extends core::Object? = dynamic, S extends core::Object? = core::Object?>(final self::Extension4|method5::T% #this) → dynamic {}
+static method Extension4|get#method5<T extends core::Object? = dynamic>(final self::Extension4|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension4|method5<self::Extension4|get#method5::T%, S%>(#this);
+static method Extension5|method1<T extends core::Object? = core::Object?, S extends core::Object = core::Object>(final self::Extension5|method1::T% #this) → dynamic {}
+static method Extension5|get#method1<T extends core::Object? = core::Object?>(final self::Extension5|get#method1::T% #this) → <S extends core::Object = core::Object>() → dynamic
+  return <S extends core::Object = core::Object>() → dynamic => self::Extension5|method1<self::Extension5|get#method1::T%, S>(#this);
+static method Extension5|method2<T extends core::Object? = core::Object?, S extends core::String = core::String>(final self::Extension5|method2::T% #this) → dynamic {}
+static method Extension5|get#method2<T extends core::Object? = core::Object?>(final self::Extension5|get#method2::T% #this) → <S extends core::String = core::String>() → dynamic
+  return <S extends core::String = core::String>() → dynamic => self::Extension5|method2<self::Extension5|get#method2::T%, S>(#this);
+static method Extension5|method3<T extends core::Object? = core::Object?, S extends dynamic = dynamic>(final self::Extension5|method3::T% #this) → dynamic {}
+static method Extension5|get#method3<T extends core::Object? = core::Object?>(final self::Extension5|get#method3::T% #this) → <S extends dynamic = dynamic>() → dynamic
+  return <S extends dynamic = dynamic>() → dynamic => self::Extension5|method3<self::Extension5|get#method3::T%, S%>(#this);
+static method Extension5|method4<T extends core::Object? = core::Object?, S extends core::Object? = dynamic>(final self::Extension5|method4::T% #this) → dynamic {}
+static method Extension5|get#method4<T extends core::Object? = core::Object?>(final self::Extension5|get#method4::T% #this) → <S extends core::Object? = dynamic>() → dynamic
+  return <S extends core::Object? = dynamic>() → dynamic => self::Extension5|method4<self::Extension5|get#method4::T%, S%>(#this);
+static method Extension5|method5<T extends core::Object? = core::Object?, S extends core::Object? = core::Object?>(final self::Extension5|method5::T% #this) → dynamic {}
+static method Extension5|get#method5<T extends core::Object? = core::Object?>(final self::Extension5|get#method5::T% #this) → <S extends core::Object? = core::Object?>() → dynamic
+  return <S extends core::Object? = core::Object?>() → dynamic => self::Extension5|method5<self::Extension5|get#method5::T%, S%>(#this);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart
new file mode 100644
index 0000000..1458379
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2020, 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.
+
+// @dart=2.8
+
+import 'opt_in_lib.dart';
+
+main() {
+  new Class1.redirect();
+  new Class1.constRedirect();
+  const Class1.constRedirect();
+  new Class1.fact();
+
+  new Class2.redirect();
+  new Class2.constRedirect();
+  const Class2.constRedirect();
+  new Class2.fact();
+
+  new Class3.redirect();
+  new Class3.constRedirect();
+  const Class3.constRedirect();
+  new Class3.fact();
+
+  new Class4.redirect();
+  new Class4.constRedirect();
+  const Class4.constRedirect();
+  new Class4.fact();
+
+  new Class5.redirect();
+  new Class5.constRedirect();
+  const Class5.constRedirect();
+  new Class5.fact();
+
+  testOptIn();
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.textual_outline.expect
new file mode 100644
index 0000000..dce6d1c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+// @dart = 2.8
+import 'opt_in_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..dce6d1c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,4 @@
+// @dart = 2.8
+import 'opt_in_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.expect
new file mode 100644
index 0000000..d4f279e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.expect
@@ -0,0 +1,125 @@
+library;
+import self as self;
+import "opt_in_lib.dart" as opt;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///opt_in_lib.dart";
+
+static method main() → dynamic {
+  new opt::Class1::_<core::Object*>();
+  new opt::Class1::_<core::Object*>();
+  #C1;
+  opt::Class1::fact<core::Object*>();
+  new opt::Class2::_<core::Object*>();
+  new opt::Class2::_<core::Object*>();
+  #C2;
+  opt::Class2::fact<core::Object*>();
+  new opt::Class3::_<core::String*>();
+  new opt::Class3::_<core::String*>();
+  #C3;
+  opt::Class3::fact<core::String*>();
+  new opt::Class4::_<dynamic>();
+  new opt::Class4::_<dynamic>();
+  #C4;
+  opt::Class4::fact<dynamic>();
+  new opt::Class5::_<dynamic>();
+  new opt::Class5::_<dynamic>();
+  #C5;
+  opt::Class5::fact<dynamic>();
+  opt::testOptIn();
+}
+
+library /*isNonNullableByDefault*/;
+import self as opt;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = core::Object?> extends core::Object /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::Class1::redirect, opt::Class1::constRedirect]/*isNullableByDefault*/;
+  const constructor _() → opt::Class1<opt::Class1::T%>
+    : super core::Object::•()
+    ;
+  static factory redirect<T extends core::Object? = core::Object?>() → opt::Class1<opt::Class1::redirect::T%>
+    let dynamic #redirecting_factory = opt::Class1::_ in let opt::Class1::redirect::T% #typeArg0 = null in invalid-expression;
+  static factory constRedirect<T extends core::Object? = core::Object?>() → opt::Class1<opt::Class1::constRedirect::T%>
+    let dynamic #redirecting_factory = opt::Class1::_ in let opt::Class1::constRedirect::T% #typeArg0 = null in invalid-expression;
+  static factory fact<T extends core::Object? = core::Object?>() → opt::Class1<opt::Class1::fact::T%>
+    return new opt::Class1::_<opt::Class1::fact::T%>();
+}
+class Class2<T extends core::Object = core::Object> extends core::Object /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::Class2::redirect, opt::Class2::constRedirect]/*isNullableByDefault*/;
+  const constructor _() → opt::Class2<opt::Class2::T>
+    : super core::Object::•()
+    ;
+  static factory redirect<T extends core::Object = core::Object>() → opt::Class2<opt::Class2::redirect::T>
+    let dynamic #redirecting_factory = opt::Class2::_ in let opt::Class2::redirect::T #typeArg0 = null in invalid-expression;
+  static factory constRedirect<T extends core::Object = core::Object>() → opt::Class2<opt::Class2::constRedirect::T>
+    let dynamic #redirecting_factory = opt::Class2::_ in let opt::Class2::constRedirect::T #typeArg0 = null in invalid-expression;
+  static factory fact<T extends core::Object = core::Object>() → opt::Class2<opt::Class2::fact::T>
+    return new opt::Class2::_<opt::Class2::fact::T>();
+}
+class Class3<T extends core::String = core::String> extends core::Object /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::Class3::redirect, opt::Class3::constRedirect]/*isNullableByDefault*/;
+  const constructor _() → opt::Class3<opt::Class3::T>
+    : super core::Object::•()
+    ;
+  static factory redirect<T extends core::String = core::String>() → opt::Class3<opt::Class3::redirect::T>
+    let dynamic #redirecting_factory = opt::Class3::_ in let opt::Class3::redirect::T #typeArg0 = null in invalid-expression;
+  static factory constRedirect<T extends core::String = core::String>() → opt::Class3<opt::Class3::constRedirect::T>
+    let dynamic #redirecting_factory = opt::Class3::_ in let opt::Class3::constRedirect::T #typeArg0 = null in invalid-expression;
+  static factory fact<T extends core::String = core::String>() → opt::Class3<opt::Class3::fact::T>
+    return new opt::Class3::_<opt::Class3::fact::T>();
+}
+class Class4<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::Class4::redirect, opt::Class4::constRedirect]/*isNullableByDefault*/;
+  const constructor _() → opt::Class4<opt::Class4::T%>
+    : super core::Object::•()
+    ;
+  static factory redirect<T extends core::Object? = dynamic>() → opt::Class4<opt::Class4::redirect::T%>
+    let dynamic #redirecting_factory = opt::Class4::_ in let opt::Class4::redirect::T% #typeArg0 = null in invalid-expression;
+  static factory constRedirect<T extends core::Object? = dynamic>() → opt::Class4<opt::Class4::constRedirect::T%>
+    let dynamic #redirecting_factory = opt::Class4::_ in let opt::Class4::constRedirect::T% #typeArg0 = null in invalid-expression;
+  static factory fact<T extends core::Object? = dynamic>() → opt::Class4<opt::Class4::fact::T%>
+    return new opt::Class4::_<opt::Class4::fact::T%>();
+}
+class Class5<T extends dynamic = dynamic> extends core::Object /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::Class5::redirect, opt::Class5::constRedirect]/*isNullableByDefault*/;
+  const constructor _() → opt::Class5<opt::Class5::T%>
+    : super core::Object::•()
+    ;
+  static factory redirect<T extends dynamic = dynamic>() → opt::Class5<opt::Class5::redirect::T%>
+    let dynamic #redirecting_factory = opt::Class5::_ in let opt::Class5::redirect::T% #typeArg0 = null in invalid-expression;
+  static factory constRedirect<T extends dynamic = dynamic>() → opt::Class5<opt::Class5::constRedirect::T%>
+    let dynamic #redirecting_factory = opt::Class5::_ in let opt::Class5::constRedirect::T% #typeArg0 = null in invalid-expression;
+  static factory fact<T extends dynamic = dynamic>() → opt::Class5<opt::Class5::fact::T%>
+    return new opt::Class5::_<opt::Class5::fact::T%>();
+}
+static method testOptIn() → dynamic {
+  new opt::Class1::_<core::Object?>();
+  new opt::Class1::_<core::Object?>();
+  #C1;
+  opt::Class1::fact<core::Object?>();
+  new opt::Class2::_<core::Object>();
+  new opt::Class2::_<core::Object>();
+  #C2;
+  opt::Class2::fact<core::Object>();
+  new opt::Class3::_<core::String>();
+  new opt::Class3::_<core::String>();
+  #C3;
+  opt::Class3::fact<core::String>();
+  new opt::Class4::_<dynamic>();
+  new opt::Class4::_<dynamic>();
+  #C4;
+  opt::Class4::fact<dynamic>();
+  new opt::Class5::_<dynamic>();
+  new opt::Class5::_<dynamic>();
+  #C5;
+  opt::Class5::fact<dynamic>();
+}
+
+constants  {
+  #C1 = opt::Class1<core::Object*> {}
+  #C2 = opt::Class2<core::Object*> {}
+  #C3 = opt::Class3<core::String*> {}
+  #C4 = opt::Class4<dynamic> {}
+  #C5 = opt::Class5<dynamic> {}
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..b06177a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.transformed.expect
@@ -0,0 +1,125 @@
+library;
+import self as self;
+import "opt_in_lib.dart" as opt;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///opt_in_lib.dart";
+
+static method main() → dynamic {
+  new opt::Class1::_<core::Object*>();
+  new opt::Class1::_<core::Object*>();
+  #C1;
+  opt::Class1::fact<core::Object*>();
+  new opt::Class2::_<core::Object*>();
+  new opt::Class2::_<core::Object*>();
+  #C2;
+  opt::Class2::fact<core::Object*>();
+  new opt::Class3::_<core::String*>();
+  new opt::Class3::_<core::String*>();
+  #C3;
+  opt::Class3::fact<core::String*>();
+  new opt::Class4::_<dynamic>();
+  new opt::Class4::_<dynamic>();
+  #C4;
+  opt::Class4::fact<dynamic>();
+  new opt::Class5::_<dynamic>();
+  new opt::Class5::_<dynamic>();
+  #C5;
+  opt::Class5::fact<dynamic>();
+  opt::testOptIn();
+}
+
+library /*isNonNullableByDefault*/;
+import self as opt;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = core::Object?> extends core::Object /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::Class1::redirect, opt::Class1::constRedirect]/*isNullableByDefault*/;
+  const constructor _() → opt::Class1<opt::Class1::T%>
+    : super core::Object::•()
+    ;
+  static factory redirect<T extends core::Object? = core::Object?>() → opt::Class1<opt::Class1::redirect::T%>
+    let<BottomType> #redirecting_factory = opt::Class1::_ in let opt::Class1::redirect::T% #typeArg0 = null in invalid-expression;
+  static factory constRedirect<T extends core::Object? = core::Object?>() → opt::Class1<opt::Class1::constRedirect::T%>
+    let<BottomType> #redirecting_factory = opt::Class1::_ in let opt::Class1::constRedirect::T% #typeArg0 = null in invalid-expression;
+  static factory fact<T extends core::Object? = core::Object?>() → opt::Class1<opt::Class1::fact::T%>
+    return new opt::Class1::_<opt::Class1::fact::T%>();
+}
+class Class2<T extends core::Object = core::Object> extends core::Object /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::Class2::redirect, opt::Class2::constRedirect]/*isNullableByDefault*/;
+  const constructor _() → opt::Class2<opt::Class2::T>
+    : super core::Object::•()
+    ;
+  static factory redirect<T extends core::Object = core::Object>() → opt::Class2<opt::Class2::redirect::T>
+    let<BottomType> #redirecting_factory = opt::Class2::_ in let opt::Class2::redirect::T #typeArg0 = null in invalid-expression;
+  static factory constRedirect<T extends core::Object = core::Object>() → opt::Class2<opt::Class2::constRedirect::T>
+    let<BottomType> #redirecting_factory = opt::Class2::_ in let opt::Class2::constRedirect::T #typeArg0 = null in invalid-expression;
+  static factory fact<T extends core::Object = core::Object>() → opt::Class2<opt::Class2::fact::T>
+    return new opt::Class2::_<opt::Class2::fact::T>();
+}
+class Class3<T extends core::String = core::String> extends core::Object /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::Class3::redirect, opt::Class3::constRedirect]/*isNullableByDefault*/;
+  const constructor _() → opt::Class3<opt::Class3::T>
+    : super core::Object::•()
+    ;
+  static factory redirect<T extends core::String = core::String>() → opt::Class3<opt::Class3::redirect::T>
+    let<BottomType> #redirecting_factory = opt::Class3::_ in let opt::Class3::redirect::T #typeArg0 = null in invalid-expression;
+  static factory constRedirect<T extends core::String = core::String>() → opt::Class3<opt::Class3::constRedirect::T>
+    let<BottomType> #redirecting_factory = opt::Class3::_ in let opt::Class3::constRedirect::T #typeArg0 = null in invalid-expression;
+  static factory fact<T extends core::String = core::String>() → opt::Class3<opt::Class3::fact::T>
+    return new opt::Class3::_<opt::Class3::fact::T>();
+}
+class Class4<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::Class4::redirect, opt::Class4::constRedirect]/*isNullableByDefault*/;
+  const constructor _() → opt::Class4<opt::Class4::T%>
+    : super core::Object::•()
+    ;
+  static factory redirect<T extends core::Object? = dynamic>() → opt::Class4<opt::Class4::redirect::T%>
+    let<BottomType> #redirecting_factory = opt::Class4::_ in let opt::Class4::redirect::T% #typeArg0 = null in invalid-expression;
+  static factory constRedirect<T extends core::Object? = dynamic>() → opt::Class4<opt::Class4::constRedirect::T%>
+    let<BottomType> #redirecting_factory = opt::Class4::_ in let opt::Class4::constRedirect::T% #typeArg0 = null in invalid-expression;
+  static factory fact<T extends core::Object? = dynamic>() → opt::Class4<opt::Class4::fact::T%>
+    return new opt::Class4::_<opt::Class4::fact::T%>();
+}
+class Class5<T extends dynamic = dynamic> extends core::Object /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::Class5::redirect, opt::Class5::constRedirect]/*isNullableByDefault*/;
+  const constructor _() → opt::Class5<opt::Class5::T%>
+    : super core::Object::•()
+    ;
+  static factory redirect<T extends dynamic = dynamic>() → opt::Class5<opt::Class5::redirect::T%>
+    let<BottomType> #redirecting_factory = opt::Class5::_ in let opt::Class5::redirect::T% #typeArg0 = null in invalid-expression;
+  static factory constRedirect<T extends dynamic = dynamic>() → opt::Class5<opt::Class5::constRedirect::T%>
+    let<BottomType> #redirecting_factory = opt::Class5::_ in let opt::Class5::constRedirect::T% #typeArg0 = null in invalid-expression;
+  static factory fact<T extends dynamic = dynamic>() → opt::Class5<opt::Class5::fact::T%>
+    return new opt::Class5::_<opt::Class5::fact::T%>();
+}
+static method testOptIn() → dynamic {
+  new opt::Class1::_<core::Object?>();
+  new opt::Class1::_<core::Object?>();
+  #C1;
+  opt::Class1::fact<core::Object?>();
+  new opt::Class2::_<core::Object>();
+  new opt::Class2::_<core::Object>();
+  #C2;
+  opt::Class2::fact<core::Object>();
+  new opt::Class3::_<core::String>();
+  new opt::Class3::_<core::String>();
+  #C3;
+  opt::Class3::fact<core::String>();
+  new opt::Class4::_<dynamic>();
+  new opt::Class4::_<dynamic>();
+  #C4;
+  opt::Class4::fact<dynamic>();
+  new opt::Class5::_<dynamic>();
+  new opt::Class5::_<dynamic>();
+  #C5;
+  opt::Class5::fact<dynamic>();
+}
+
+constants  {
+  #C1 = opt::Class1<core::Object*> {}
+  #C2 = opt::Class2<core::Object*> {}
+  #C3 = opt::Class3<core::String*> {}
+  #C4 = opt::Class4<dynamic> {}
+  #C5 = opt::Class5<dynamic> {}
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/opt_in_lib.dart b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/opt_in_lib.dart
new file mode 100644
index 0000000..5236adb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/opt_in_lib.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2020, 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 Class1<T extends Object?> {
+  factory Class1.redirect() = Class1._;
+  const factory Class1.constRedirect() = Class1._;
+  factory Class1.fact() => new Class1._();
+
+  const Class1._();
+}
+
+class Class2<T extends Object> {
+  factory Class2.redirect() = Class2._;
+  const factory Class2.constRedirect() = Class2._;
+  factory Class2.fact() => new Class2._();
+
+  const Class2._();
+}
+
+class Class3<T extends String> {
+  factory Class3.redirect() = Class3._;
+  const factory Class3.constRedirect() = Class3._;
+  factory Class3.fact() => new Class3._();
+
+  const Class3._();
+}
+
+class Class4<T> {
+  factory Class4.redirect() = Class4._;
+  const factory Class4.constRedirect() = Class4._;
+  factory Class4.fact() => new Class4._();
+
+  const Class4._();
+}
+
+class Class5<T extends dynamic> {
+  factory Class5.redirect() = Class5._;
+  const factory Class5.constRedirect() = Class5._;
+  factory Class5.fact() => new Class5._();
+
+  const Class5._();
+}
+
+testOptIn() {
+  new Class1.redirect();
+  new Class1.constRedirect();
+  const Class1.constRedirect();
+  new Class1.fact();
+
+  new Class2.redirect();
+  new Class2.constRedirect();
+  const Class2.constRedirect();
+  new Class2.fact();
+
+  new Class3.redirect();
+  new Class3.constRedirect();
+  const Class3.constRedirect();
+  new Class3.fact();
+
+  new Class4.redirect();
+  new Class4.constRedirect();
+  const Class4.constRedirect();
+  new Class4.fact();
+
+  new Class5.redirect();
+  new Class5.constRedirect();
+  const Class5.constRedirect();
+  new Class5.fact();
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart
new file mode 100644
index 0000000..9a94b4d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2020, 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.
+
+// @dart=2.8
+
+import 'opt_in_lib.dart';
+
+class Class {}
+
+class XToken extends Token {
+  const XToken();
+}
+
+const list = [
+  CP(Class),
+  VP.forToken(XToken(), 'Hello World'),
+];
+
+const m = M(list: list);
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.textual_outline.expect
new file mode 100644
index 0000000..b17ae20
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.textual_outline.expect
@@ -0,0 +1,15 @@
+// @dart = 2.8
+import 'opt_in_lib.dart';
+
+class Class {}
+
+class XToken extends Token {
+  const XToken();
+}
+
+const list = [
+  CP(Class),
+  VP.forToken(XToken(), 'Hello World'),
+];
+const m = M(list: list);
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b17ae20
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+// @dart = 2.8
+import 'opt_in_lib.dart';
+
+class Class {}
+
+class XToken extends Token {
+  const XToken();
+}
+
+const list = [
+  CP(Class),
+  VP.forToken(XToken(), 'Hello World'),
+];
+const m = M(list: list);
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.expect
new file mode 100644
index 0000000..cf96979
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.expect
@@ -0,0 +1,88 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "opt_in_lib.dart" as opt;
+
+import "org-dartlang-testcase:///opt_in_lib.dart";
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  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
+}
+class XToken extends opt::Token<core::Object*> /*hasConstConstructor*/  {
+  const constructor •() → self::XToken*
+    : super opt::Token::•()
+    ;
+  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
+}
+static const field core::List<opt::P<core::Object*>*>* list = #C5;
+static const field opt::M* m = #C6;
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as opt;
+import "dart:core" as core;
+
+class P<T extends core::Object = core::Object> extends core::Object /*hasConstConstructor*/  {
+  final field core::Object token;
+  const constructor _(core::Object token) → opt::P<opt::P::T>
+    : opt::P::token = token, super core::Object::•()
+    ;
+}
+class CP<T extends core::Object = core::Object> extends opt::P<opt::CP::T> /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::CP::•]/*isNullableByDefault*/;
+  const constructor _(core::Object token) → opt::CP<opt::CP::T>
+    : super opt::P::_(token)
+    ;
+  static factory •<T extends core::Object = core::Object>(core::Type type) → opt::CP<opt::CP::•::T>
+    let dynamic #redirecting_factory = opt::CP::_ in let opt::CP::•::T #typeArg0 = null in invalid-expression;
+}
+class Token<T extends core::Object = core::Object> extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → opt::Token<opt::Token::T>
+    : super core::Object::•()
+    ;
+}
+class VP<T extends core::Object = core::Object> extends opt::P<opt::VP::T> /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::VP::forToken]/*isNullableByDefault*/;
+  const constructor _(core::Object token, opt::VP::T useValue) → opt::VP<opt::VP::T>
+    : super opt::P::_(token)
+    ;
+  static factory forToken<T extends core::Object = core::Object>(opt::Token<opt::VP::forToken::T> token, opt::VP::forToken::T useValue) → opt::VP<opt::VP::forToken::T>
+    let dynamic #redirecting_factory = opt::VP::_ in let opt::VP::forToken::T #typeArg0 = null in invalid-expression;
+}
+class M extends core::Object /*hasConstConstructor*/  {
+  final field core::List<opt::P<core::Object>> list;
+  const constructor •({core::List<opt::P<core::Object>> list = #C7}) → opt::M
+    : opt::M::list = list, super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = TypeLiteralConstant(self::Class*)
+  #C2 = opt::CP<core::Object*> {token:#C1}
+  #C3 = self::XToken {}
+  #C4 = opt::VP<core::Object*> {token:#C3}
+  #C5 = <opt::P<core::Object*>*>[#C2, #C4]
+  #C6 = opt::M {list:#C5}
+  #C7 = <opt::P<core::Object*>*>[]
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..69f70c8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.transformed.expect
@@ -0,0 +1,88 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "opt_in_lib.dart" as opt;
+
+import "org-dartlang-testcase:///opt_in_lib.dart";
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  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
+}
+class XToken extends opt::Token<core::Object*> /*hasConstConstructor*/  {
+  const constructor •() → self::XToken*
+    : super opt::Token::•()
+    ;
+  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
+}
+static const field core::List<opt::P<core::Object*>*>* list = #C5;
+static const field opt::M* m = #C6;
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as opt;
+import "dart:core" as core;
+
+class P<T extends core::Object = core::Object> extends core::Object /*hasConstConstructor*/  {
+  final field core::Object token;
+  const constructor _(core::Object token) → opt::P<opt::P::T>
+    : opt::P::token = token, super core::Object::•()
+    ;
+}
+class CP<T extends core::Object = core::Object> extends opt::P<opt::CP::T> /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::CP::•]/*isNullableByDefault*/;
+  const constructor _(core::Object token) → opt::CP<opt::CP::T>
+    : super opt::P::_(token)
+    ;
+  static factory •<T extends core::Object = core::Object>(core::Type type) → opt::CP<opt::CP::•::T>
+    let<BottomType> #redirecting_factory = opt::CP::_ in let opt::CP::•::T #typeArg0 = null in invalid-expression;
+}
+class Token<T extends core::Object = core::Object> extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → opt::Token<opt::Token::T>
+    : super core::Object::•()
+    ;
+}
+class VP<T extends core::Object = core::Object> extends opt::P<opt::VP::T> /*hasConstConstructor*/  {
+  static field dynamic _redirecting# = <dynamic>[opt::VP::forToken]/*isNullableByDefault*/;
+  const constructor _(core::Object token, opt::VP::T useValue) → opt::VP<opt::VP::T>
+    : super opt::P::_(token)
+    ;
+  static factory forToken<T extends core::Object = core::Object>(opt::Token<opt::VP::forToken::T> token, opt::VP::forToken::T useValue) → opt::VP<opt::VP::forToken::T>
+    let<BottomType> #redirecting_factory = opt::VP::_ in let opt::VP::forToken::T #typeArg0 = null in invalid-expression;
+}
+class M extends core::Object /*hasConstConstructor*/  {
+  final field core::List<opt::P<core::Object>> list;
+  const constructor •({core::List<opt::P<core::Object>> list = #C7}) → opt::M
+    : opt::M::list = list, super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = TypeLiteralConstant(self::Class*)
+  #C2 = opt::CP<core::Object*> {token:#C1}
+  #C3 = self::XToken {}
+  #C4 = opt::VP<core::Object*> {token:#C3}
+  #C5 = <opt::P<core::Object*>*>[#C2, #C4]
+  #C6 = opt::M {list:#C5}
+  #C7 = <opt::P<core::Object*>*>[]
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/opt_in_lib.dart b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/opt_in_lib.dart
new file mode 100644
index 0000000..0ce39c6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/opt_in_lib.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, 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 P<T extends Object> {
+  final Object token;
+
+  const P._(this.token);
+}
+
+class CP<T extends Object> extends P<T> {
+  const factory CP(Type type) = CP<T>._;
+
+  const CP._(Object token) : super._(token);
+}
+
+class Token<T extends Object> {
+  const Token();
+}
+
+class VP<T extends Object> extends P<T> {
+  const factory VP.forToken(
+    Token<T> token,
+    T useValue,
+  ) = VP<T>._;
+
+  const VP._(
+    Object token,
+    T useValue,
+  ) : super._(token);
+}
+
+class M {
+  final List<P<Object>> list;
+
+  const M({this.list = const []});
+}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index dd67af6..6159e50 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -22,6 +22,7 @@
 
 extensions/ambiguous: FormatterCrash
 extensions/annotations: FormatterCrash
+extensions/bounds: FormatterCrash
 extensions/builtin_identifiers: FormatterCrash
 extensions/call_methods: FormatterCrash
 extensions/check_bounds: FormatterCrash
@@ -167,6 +168,7 @@
 nnbd/abstract_fields_spec: FormatterCrash
 nnbd/abstract_fields: FormatterCrash
 nnbd/covariant_late_field: FormatterCrash
+nnbd/extension_bounds: FormatterCrash
 nnbd/extension_never: FormatterCrash
 nnbd/external_field_errors: FormatterCrash
 nnbd/external_fields_spec: FormatterCrash
diff --git a/pkg/nnbd_migration/lib/src/front_end/region_renderer.dart b/pkg/nnbd_migration/lib/src/front_end/region_renderer.dart
index f719ceb..89f0f84 100644
--- a/pkg/nnbd_migration/lib/src/front_end/region_renderer.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/region_renderer.dart
@@ -92,7 +92,7 @@
       //  for all nodes.
       return '';
     }
-    return pathContext.relative(pathMapper.map(target.filePath), from: unitDir);
+    return pathMapper.map(pathContext.relative(target.filePath, from: unitDir));
   }
 
   /// Return the URL that will navigate to the given [target] in the file at the
diff --git a/pkg/nnbd_migration/test/front_end/region_renderer_test.dart b/pkg/nnbd_migration/test/front_end/region_renderer_test.dart
index bc329d1..9b2cd10 100644
--- a/pkg/nnbd_migration/test/front_end/region_renderer_test.dart
+++ b/pkg/nnbd_migration/test/front_end/region_renderer_test.dart
@@ -6,10 +6,10 @@
 import 'package:nnbd_migration/src/front_end/path_mapper.dart';
 import 'package:nnbd_migration/src/front_end/region_renderer.dart';
 import 'package:nnbd_migration/src/front_end/web/edit_details.dart';
+import 'package:path/path.dart' as p;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../abstract_context.dart';
 import 'nnbd_migration_test_base.dart';
 
 void main() {
@@ -22,12 +22,23 @@
 class RegionRendererTest extends NnbdMigrationTestBase {
   PathMapper pathMapper;
 
+  /// Returns the path of [testFile] used in traces.
+  ///
+  /// On Windows, we display the absolute path of the test file.
+  /// On Posix, we display the path of the target file relative to the current
+  /// file.
+  // TODO(srawlins): I doubt this is intentional. While I don't see a bug,
+  //  the discrepancy could lead to confusion and may be an indicator of bugs.
+  String get _testFilePathForTrace =>
+      resourceProvider.pathContext.style == p.Style.windows
+          ? testFile
+          : resourceProvider.pathContext.basename(testFile);
+
   /// Render the region at [offset], using a [MigrationInfo] which knows only
   /// about the library at `infos.single`.
   EditDetails renderRegion(int offset) {
-    var packageRoot = convertPath('/package');
     var migrationInfo =
-        MigrationInfo(infos, {}, resourceProvider.pathContext, packageRoot);
+        MigrationInfo(infos, {}, resourceProvider.pathContext, projectPath);
     var unitInfo = infos.single;
     var region = unitInfo.regionAt(offset);
     pathMapper = PathMapper(resourceProvider);
@@ -36,6 +47,86 @@
         .render();
   }
 
+  Future<void> test_informationalRegion_containsTrace() async {
+    await buildInfoForSingleTestFile('f(int a) => a.isEven;',
+        migratedContent: 'f(int  a) => a.isEven;');
+    var response = renderRegion(5);
+    expect(response.traces, hasLength(1));
+    var trace = response.traces[0];
+    expect(trace.description, equals('Non-nullability reason'));
+  }
+
+  Future<void> test_informationalRegion_containsTraceEntryDescriptions() async {
+    await buildInfoForSingleTestFile('f(int a) => a.isEven;',
+        migratedContent: 'f(int  a) => a.isEven;');
+    var response = renderRegion(5);
+    expect(response.traces, hasLength(1));
+    var trace = response.traces[0];
+    expect(trace.entries, hasLength(2));
+    expect(trace.entries[0].description,
+        equals('parameter 0 of f ($_testFilePathForTrace:1:3)'));
+    expect(trace.entries[1].description, equals('data flow'));
+  }
+
+  Future<void> test_informationalRegion_containsTraceLinks() async {
+    await buildInfoForSingleTestFile('f(int a) => a.isEven;',
+        migratedContent: 'f(int  a) => a.isEven;');
+    var response = renderRegion(5);
+    expect(response.traces, hasLength(1));
+    var trace = response.traces[0];
+    var entry = trace.entries[0];
+    expect(entry.link, isNotNull);
+    var testFileUriPath = resourceProvider.pathContext.toUri(testFile).path;
+    expect(entry.link.href,
+        equals('$testFileUriPath?offset=2&line=1&authToken=AUTH_TOKEN'));
+    expect(entry.link.path,
+        equals(resourceProvider.pathContext.toUri(_testFilePathForTrace).path));
+  }
+
+  Future<void>
+      test_informationalRegion_containsTraceLinks_separateDrive() async {
+    // See https://github.com/dart-lang/sdk/issues/43178. Linking from a file on
+    // one drive to a file on another drive can cause problems.
+    projectPath = _switchToDriveD(projectPath);
+    testFolder = _switchToDriveD(testFolder);
+    testFile = _switchToDriveD(testFile);
+    await buildInfoForSingleTestFile(r'''
+f(List<int> a) {
+  if (1 == 2) List.from(a);
+}
+g() {
+  f(null);
+}
+''', migratedContent: r'''
+f(List<int >? a) {
+  if (1 == 2) List.from(a!);
+}
+g() {
+  f(null);
+}
+''');
+    var response = renderRegion(44); // The inserted null-check.
+    expect(response.displayPath,
+        equals(_switchToDriveD(convertPath('/home/tests/bin/test.dart'))));
+    expect(response.traces, hasLength(2));
+    var trace = response.traces[1];
+    expect(trace.description, equals('Non-nullability reason'));
+    expect(trace.entries, hasLength(1));
+    var entry = trace.entries[0];
+    expect(entry.link, isNotNull);
+    var sdkCoreLib = convertPath('/sdk/lib/core/core.dart');
+    var sdkCoreLibUriPath = resourceProvider.pathContext.toUri(sdkCoreLib).path;
+    expect(entry.link.href,
+        equals('$sdkCoreLibUriPath?offset=3730&line=166&authToken=AUTH_TOKEN'));
+    // On Windows, the path will simply be the absolute path to the core
+    // library, because there is no relative route from C:\ to D:\. On Posix,
+    // the path is relative.
+    var expectedLinkPath = resourceProvider.pathContext.style == p.Style.windows
+        ? sdkCoreLibUriPath
+        : '../../..$sdkCoreLibUriPath';
+    expect(entry.link.path, equals(expectedLinkPath));
+  }
+
   Future<void> test_modifiedOutput_containsExplanation() async {
     await buildInfoForSingleTestFile('int a = null;',
         migratedContent: 'int? a = null;');
@@ -47,15 +138,27 @@
     await buildInfoForSingleTestFile('int a = null;',
         migratedContent: 'int? a = null;');
     var response = renderRegion(3);
-    expect(response.displayPath,
-        equals(convertPath('${AbstractContextTest.testsPath}/bin/test.dart')));
-    expect(
-        response.uriPath,
-        equals(pathMapper.map(
-            convertPath('${AbstractContextTest.testsPath}/bin/test.dart'))));
+    expect(response.displayPath, equals(testFile));
+    expect(response.uriPath, equals(pathMapper.map(testFile)));
     expect(response.line, equals(1));
   }
 
+  Future<void> test_modifiedOutput_containsTraceForNullabilityReason() async {
+    await buildInfoForSingleTestFile('int a = null;',
+        migratedContent: 'int? a = null;');
+    var response = renderRegion(3);
+    expect(response.traces, hasLength(1));
+    var trace = response.traces[0];
+    expect(trace.description, equals('Nullability reason'));
+    expect(trace.entries, hasLength(4));
+    expect(
+        trace.entries[0].description, equals('a ($_testFilePathForTrace:1:1)'));
+    expect(trace.entries[1].description, equals('data flow'));
+    expect(trace.entries[2].description,
+        equals('null literal ($_testFilePathForTrace:1:9)'));
+    expect(trace.entries[3].description, equals('literal expression'));
+  }
+
   Future<void> test_unmodifiedOutput_containsExplanation() async {
     await buildInfoForSingleTestFile('f(int a) => a.isEven;',
         migratedContent: 'f(int  a) => a.isEven;');
@@ -67,12 +170,17 @@
     await buildInfoForSingleTestFile('f(int a) => a.isEven;',
         migratedContent: 'f(int  a) => a.isEven;');
     var response = renderRegion(5);
-    expect(response.displayPath,
-        equals(convertPath('${AbstractContextTest.testsPath}/bin/test.dart')));
-    expect(
-        response.uriPath,
-        equals(pathMapper.map(
-            convertPath('${AbstractContextTest.testsPath}/bin/test.dart'))));
+    expect(response.displayPath, equals(testFile));
+    expect(response.uriPath, equals(pathMapper.map(testFile)));
     expect(response.line, equals(1));
   }
+
+  /// On Windows, replace the C:\ relative root in [path] with the D:\ relative
+  /// root.
+  ///
+  /// On Posix, nothing is be replaced.
+  String _switchToDriveD(String path) {
+    assert(resourceProvider.pathContext.isAbsolute(path));
+    return path.replaceFirst(RegExp('^C:\\\\'), 'D:\\');
+  }
 }
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index 03a1489..457e9e5 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -431,7 +431,9 @@
   PushNull
   ReturnTOS
 }
+Default function type arguments: CP#0
 ConstantPool {
+  [0] = ObjectRef < dart:core::String* >
 }
 
 
@@ -903,7 +905,7 @@
     }
   }
   class E<P extends dart.core::String* = dart.core::String*> extends dart.core::Object {
-    static factory •<P extends dart.core::String* = dynamic>() → #lib::E<#lib::E::•::P*>*
+    static factory •<P extends dart.core::String* = dart.core::String*>() → #lib::E<#lib::E::•::P*>*
       return null;
     method foo6<generic-covariant-impl T extends #lib::E::P* = #lib::E::P*, U extends dart.core::List<#lib::E::foo6::T*>* = dart.core::List<#lib::E::P*>*>(dart.core::Map<#lib::E::foo6::T*, #lib::E::foo6::U*>* map) → void {}
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
diff --git a/tests/language/if_null/assignment_behavior_test.dart b/tests/language/if_null/assignment_behavior_test.dart
index d83be71..c9c4fb8 100644
--- a/tests/language/if_null/assignment_behavior_test.dart
+++ b/tests/language/if_null/assignment_behavior_test.dart
@@ -125,8 +125,6 @@
 // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL
 // [cfe] The setter 'finalOne' isn't defined for the class 'C'.
 //               ^^^^
-// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-//               ^^^^
 // [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
     yGetValue = 1;
   }
@@ -180,8 +178,6 @@
 // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_TYPE
 // [cfe] Can't assign to a type literal.
 //      ^^^^
-// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-//      ^^^^
 // [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
   h ??= null;
 //^
diff --git a/tests/language/type_object/first_class_types_literals_test.dart b/tests/language/type_object/first_class_types_literals_test.dart
index 663e516..8c761e2 100644
--- a/tests/language/type_object/first_class_types_literals_test.dart
+++ b/tests/language/type_object/first_class_types_literals_test.dart
@@ -53,8 +53,6 @@
   //                                   ^
   // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_TYPE
   // [cfe] Can't assign to a type literal.
-  //                                       ^
-  // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
   Expect.throwsNoSuchMethodError(() => C++);
   //                                   ^
   // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_TYPE
@@ -76,11 +74,13 @@
   Expect.throwsNoSuchMethodError(() => dynamic = 1);
   //                                   ^
   // [cfe] Can't assign to a type literal.
-  //                                             ^
-  // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
+  //                                   ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_TYPE
   Expect.throwsNoSuchMethodError(() => dynamic++);
   //                                   ^
   // [cfe] Can't assign to a type literal.
+  //                                   ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_TYPE
   //                                          ^^
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_OPERATOR
   Expect.throwsNoSuchMethodError(() => dynamic + 1);
diff --git a/tests/language_2/type_object/first_class_types_literals_test.dart b/tests/language_2/type_object/first_class_types_literals_test.dart
index 663e516..8c761e2 100644
--- a/tests/language_2/type_object/first_class_types_literals_test.dart
+++ b/tests/language_2/type_object/first_class_types_literals_test.dart
@@ -53,8 +53,6 @@
   //                                   ^
   // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_TYPE
   // [cfe] Can't assign to a type literal.
-  //                                       ^
-  // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
   Expect.throwsNoSuchMethodError(() => C++);
   //                                   ^
   // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_TYPE
@@ -76,11 +74,13 @@
   Expect.throwsNoSuchMethodError(() => dynamic = 1);
   //                                   ^
   // [cfe] Can't assign to a type literal.
-  //                                             ^
-  // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
+  //                                   ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_TYPE
   Expect.throwsNoSuchMethodError(() => dynamic++);
   //                                   ^
   // [cfe] Can't assign to a type literal.
+  //                                   ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_TYPE
   //                                          ^^
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_OPERATOR
   Expect.throwsNoSuchMethodError(() => dynamic + 1);
diff --git a/tools/VERSION b/tools/VERSION
index 7c8ae1a..59e1d50 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 10
 PATCH 0
-PRERELEASE 69
+PRERELEASE 70
 PRERELEASE_PATCH 0
\ No newline at end of file