[cfe] Remove Nullability.legacy

TEST=existing

Change-Id: Id924e4ef64ddabc1986cb885f558382ff139b481
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/436620
Reviewed-by: Mayank Patke <fishythefish@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Nicholas Shahan <nshahan@google.com>
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index 17b58b0..76b51fe 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -62,10 +62,6 @@
         return baseType;
       case ir.Nullability.nullable:
         return _dartTypes.nullableType(baseType);
-      case ir.Nullability.legacy:
-        throw UnsupportedError(
-          'Unexpected legacy nullability on $nullabilitySource',
-        );
       case ir.Nullability.undetermined:
         // Type parameters may have undetermined nullability since it is derived
         // from the intersection of the declared nullability with the
diff --git a/pkg/dart2bytecode/lib/bytecode_generator.dart b/pkg/dart2bytecode/lib/bytecode_generator.dart
index d4d11f0..35a8a9e 100644
--- a/pkg/dart2bytecode/lib/bytecode_generator.dart
+++ b/pkg/dart2bytecode/lib/bytecode_generator.dart
@@ -2100,8 +2100,9 @@
       final targetTypeParameters = forwardingTarget.function!.typeParameters;
       assert(host.typeParameters.length == targetTypeParameters.length);
       for (int i = 0; i < targetTypeParameters.length; ++i) {
-        map[targetTypeParameters[i]] =
-            new TypeParameterType(host.typeParameters[i], Nullability.legacy);
+        map[targetTypeParameters[i]] = new TypeParameterType(
+            host.typeParameters[i],
+            host.typeParameters[i].computeNullabilityFromBound());
       }
     }
     return Substitution.fromMap(map);
@@ -2287,7 +2288,8 @@
     final DartType bound = (forwardingTypeParameterBounds != null)
         ? forwardingTypeParameterBounds[typeParam]!
         : typeParam.bound;
-    final DartType type = new TypeParameterType(typeParam, Nullability.legacy);
+    final DartType type = new TypeParameterType(
+        typeParam, typeParam.computeNullabilityFromBound());
     _genPushInstantiatorAndFunctionTypeArguments([type, bound]);
     asm.emitPushConstant(cp.addType(type));
     asm.emitPushConstant(cp.addType(bound));
diff --git a/pkg/dart2bytecode/lib/object_table.dart b/pkg/dart2bytecode/lib/object_table.dart
index b4cbb76..dc237b5 100644
--- a/pkg/dart2bytecode/lib/object_table.dart
+++ b/pkg/dart2bytecode/lib/object_table.dart
@@ -71,8 +71,6 @@
 
 String nullabilityToString(Nullability nullability) {
   switch (nullability) {
-    case Nullability.legacy:
-      return '*';
     case Nullability.nullable:
       return '?';
     case Nullability.undetermined:
diff --git a/pkg/dev_compiler/lib/src/kernel/future_or_normalizer.dart b/pkg/dev_compiler/lib/src/kernel/future_or_normalizer.dart
index 1e22604..9f64334 100644
--- a/pkg/dev_compiler/lib/src/kernel/future_or_normalizer.dart
+++ b/pkg/dev_compiler/lib/src/kernel/future_or_normalizer.dart
@@ -43,17 +43,11 @@
         return typeArgument;
       case InterfaceType()
           when typeArgument.classNode == _coreTypes.objectClass:
-        // Normalize FutureOr of Object, Object?, Object*.
-        var nullable =
+        // Normalize FutureOr of Object, Object?.
+        var nullability =
             futureOr.nullability == Nullability.nullable ||
-            typeArgument.nullability == Nullability.nullable;
-        var legacy =
-            futureOr.nullability == Nullability.legacy ||
-            typeArgument.nullability == Nullability.legacy;
-        var nullability = nullable
+                typeArgument.nullability == Nullability.nullable
             ? Nullability.nullable
-            : legacy
-            ? Nullability.legacy
             : Nullability.nonNullable;
         return typeArgument.withDeclaredNullability(nullability);
       case NeverType() when typeArgument.nullability == Nullability.nonNullable:
diff --git a/pkg/dev_compiler/lib/src/kernel/type_recipe_generator.dart b/pkg/dev_compiler/lib/src/kernel/type_recipe_generator.dart
index 47aba39..5fac19b 100644
--- a/pkg/dev_compiler/lib/src/kernel/type_recipe_generator.dart
+++ b/pkg/dev_compiler/lib/src/kernel/type_recipe_generator.dart
@@ -587,8 +587,6 @@
         return Recipe.wrapQuestionString;
       case Nullability.nonNullable:
         return '';
-      case Nullability.legacy:
-        throw UnsupportedError('Legacy nullability.');
     }
   }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/type_table.dart b/pkg/dev_compiler/lib/src/kernel/type_table.dart
index 72942c1..587738d 100644
--- a/pkg/dev_compiler/lib/src/kernel/type_table.dart
+++ b/pkg/dev_compiler/lib/src/kernel/type_table.dart
@@ -61,14 +61,9 @@
 
 /// A name for a type made of JS identifier safe characters.
 ///
-/// 'L' and 'N' are appended to a type name to represent a legacy or nullable
-/// flavor of a type.
+/// 'N' is appended to a type name to represent a nullable flavor of a type.
 String _typeString(DartType type, {bool flat = false}) {
-  var nullability = type.declaredNullability == Nullability.legacy
-      ? 'L'
-      : type.declaredNullability == Nullability.nullable
-      ? 'N'
-      : '';
+  var nullability = type.declaredNullability == Nullability.nullable ? 'N' : '';
   switch (type) {
     case InterfaceType():
       var name = '${type.classNode.name}$nullability';
diff --git a/pkg/front_end/lib/src/api_prototype/expression_compilation_tools.dart b/pkg/front_end/lib/src/api_prototype/expression_compilation_tools.dart
index 7e7d2c5..04e2a12 100644
--- a/pkg/front_end/lib/src/api_prototype/expression_compilation_tools.dart
+++ b/pkg/front_end/lib/src/api_prototype/expression_compilation_tools.dart
@@ -279,7 +279,6 @@
     if (type == ParsedTypeKind.Null) throw "No nullability on the null type";
     if (nullability == 0) return Nullability.nullable;
     if (nullability == 1) return Nullability.nonNullable;
-    if (nullability == 2) return Nullability.legacy;
     throw "Unknown nullability";
   }
 }
diff --git a/pkg/front_end/lib/src/builder/class_builder.dart b/pkg/front_end/lib/src/builder/class_builder.dart
index 3a71ef4..d9a866b 100644
--- a/pkg/front_end/lib/src/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/builder/class_builder.dart
@@ -84,7 +84,6 @@
   @override
   bool isNullClass = false;
 
-  InterfaceType? _legacyRawType;
   InterfaceType? _nullableRawType;
   InterfaceType? _nonNullableRawType;
   InterfaceType? _thisType;
@@ -105,12 +104,6 @@
         getAsTypeArguments(cls.typeParameters, libraryBuilder.library));
   }
 
-  // Coverage-ignore(suite): Not run.
-  InterfaceType get legacyRawType {
-    return _legacyRawType ??= new InterfaceType(cls, Nullability.legacy,
-        new List<DartType>.filled(typeParametersCount, const DynamicType()));
-  }
-
   InterfaceType get nullableRawType {
     return _nullableRawType ??= new InterfaceType(cls, Nullability.nullable,
         new List<DartType>.filled(typeParametersCount, const DynamicType()));
@@ -125,9 +118,6 @@
 
   InterfaceType rawType(Nullability nullability) {
     switch (nullability) {
-      case Nullability.legacy:
-        // Coverage-ignore(suite): Not run.
-        return legacyRawType;
       case Nullability.nullable:
         return nullableRawType;
       case Nullability.nonNullable:
@@ -243,7 +233,7 @@
     if (arguments != null) {
       List<DartType> typeArguments =
           buildAliasedTypeArguments(library, arguments, /* hierarchy = */ null);
-      typeArguments = unaliasTypes(typeArguments, legacyEraseAliases: false)!;
+      typeArguments = unaliasTypes(typeArguments)!;
       return new Supertype(cls, typeArguments);
     } else {
       return new Supertype(
diff --git a/pkg/front_end/lib/src/builder/function_type_builder.dart b/pkg/front_end/lib/src/builder/function_type_builder.dart
index 879a58e..508cc28 100644
--- a/pkg/front_end/lib/src/builder/function_type_builder.dart
+++ b/pkg/front_end/lib/src/builder/function_type_builder.dart
@@ -153,7 +153,7 @@
   DartType _buildInternal(
       LibraryBuilder library, TypeUse typeUse, ClassHierarchyBase? hierarchy) {
     DartType aliasedType = buildAliased(library, typeUse, hierarchy);
-    return unalias(aliasedType, legacyEraseAliases: false);
+    return unalias(aliasedType);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/builder/named_type_builder.dart b/pkg/front_end/lib/src/builder/named_type_builder.dart
index 7d44439..40e47b7 100644
--- a/pkg/front_end/lib/src/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/builder/named_type_builder.dart
@@ -489,7 +489,7 @@
             typeName.fullNameLength);
       }
     }
-    return unaliasing.unalias(aliasedType, legacyEraseAliases: false);
+    return unaliasing.unalias(aliasedType);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/builder/nullability_builder.dart b/pkg/front_end/lib/src/builder/nullability_builder.dart
index f0b5ae9..ce75441 100644
--- a/pkg/front_end/lib/src/builder/nullability_builder.dart
+++ b/pkg/front_end/lib/src/builder/nullability_builder.dart
@@ -39,7 +39,6 @@
     switch (nullability) {
       case Nullability.nullable:
         return const NullabilityBuilder.nullable();
-      case Nullability.legacy:
       case Nullability.nonNullable:
       case Nullability.undetermined:
         return const NullabilityBuilder.omitted();
diff --git a/pkg/front_end/lib/src/builder/record_type_builder.dart b/pkg/front_end/lib/src/builder/record_type_builder.dart
index 35fef24..6b2b631 100644
--- a/pkg/front_end/lib/src/builder/record_type_builder.dart
+++ b/pkg/front_end/lib/src/builder/record_type_builder.dart
@@ -143,7 +143,7 @@
   DartType _buildInternal(
       LibraryBuilder library, TypeUse typeUse, ClassHierarchyBase? hierarchy) {
     DartType aliasedType = buildAliased(library, typeUse, hierarchy);
-    return unalias(aliasedType, legacyEraseAliases: false);
+    return unalias(aliasedType);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/builder/synthesized_type_builder.dart b/pkg/front_end/lib/src/builder/synthesized_type_builder.dart
index e6515a8..c059474 100644
--- a/pkg/front_end/lib/src/builder/synthesized_type_builder.dart
+++ b/pkg/front_end/lib/src/builder/synthesized_type_builder.dart
@@ -96,7 +96,7 @@
       ClassHierarchyBase? hierarchy) {
     DartType aliasedType =
         _buildAliasedInternal(libraryBuilder, typeUse, hierarchy);
-    return unaliasing.unalias(aliasedType, legacyEraseAliases: false);
+    return unaliasing.unalias(aliasedType);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/kernel/constant_evaluator.dart
index 849e8ea..73c17b7 100644
--- a/pkg/front_end/lib/src/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/kernel/constant_evaluator.dart
@@ -4560,14 +4560,7 @@
         //       return NNBD_SUBTYPE(NULL, T)
         //    Otherwise return LEGACY_SUBTYPE(S, T)
         if (constant is NullConstant) {
-          if (type.nullability == Nullability.legacy) {
-            // `null is Null` is handled below.
-            return typeEnvironment.isSubtypeOf(type, const NullType()) ||
-                typeEnvironment.isSubtypeOf(
-                    typeEnvironment.objectNullableRawType, type);
-          } else {
-            return typeEnvironment.isSubtypeOf(const NullType(), type);
-          }
+          return typeEnvironment.isSubtypeOf(const NullType(), type);
         }
         return isSubtype(constant, type);
       }
diff --git a/pkg/front_end/lib/src/kernel/expression_generator.dart b/pkg/front_end/lib/src/kernel/expression_generator.dart
index 0069cad..291a21b 100644
--- a/pkg/front_end/lib/src/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/kernel/expression_generator.dart
@@ -3287,8 +3287,7 @@
                       declarationBuilder.buildAliasedTypeArguments(
                           _helper.libraryBuilder,
                           unaliasedTypeArguments,
-                          /* hierarchy = */ null),
-                      legacyEraseAliases: false)!;
+                          /* hierarchy = */ null))!;
                 }
               } else if (typeArguments != null) {
                 builtTypeArguments = _helper.buildDartTypeArguments(
@@ -3327,9 +3326,8 @@
                         .add(freshTypeParameters.substitute(builtTypeArgument));
                   }
                 }
-                substitutedTypeArguments = unaliasTypes(
-                    substitutedTypeArguments,
-                    legacyEraseAliases: false);
+                substitutedTypeArguments =
+                    unaliasTypes(substitutedTypeArguments);
 
                 tearOffExpression = _helper.forest.createTypedefTearOff(
                     token.charOffset,
@@ -3339,8 +3337,7 @@
               } else {
                 if (builtTypeArguments != null &&
                     builtTypeArguments.isNotEmpty) {
-                  builtTypeArguments = unaliasTypes(builtTypeArguments,
-                      legacyEraseAliases: false)!;
+                  builtTypeArguments = unaliasTypes(builtTypeArguments)!;
 
                   tearOffExpression = _helper.forest.createInstantiation(
                       token.charOffset, tearOffExpression, builtTypeArguments);
diff --git a/pkg/front_end/lib/src/testing/id_testing_utils.dart b/pkg/front_end/lib/src/testing/id_testing_utils.dart
index a18e193..d546349 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -953,13 +953,5 @@
         default:
           return '%';
       }
-    case Nullability.legacy:
-      switch (typeRepresentation) {
-        case TypeRepresentation.legacy:
-          return '';
-        case TypeRepresentation.explicit:
-        case TypeRepresentation.analyzerNonNullableByDefault:
-          return '*';
-      }
   }
 }
diff --git a/pkg/front_end/lib/src/type_inference/factor_type.dart b/pkg/front_end/lib/src/type_inference/factor_type.dart
index 6f71d64..fef2703 100644
--- a/pkg/front_end/lib/src/type_inference/factor_type.dart
+++ b/pkg/front_end/lib/src/type_inference/factor_type.dart
@@ -29,19 +29,6 @@
     }
   }
 
-  // * Else if T is R* and Null <: S then factor(R, S)
-  // * Else if T is R* then factor(R, S)*
-  if (T.declaredNullability == Nullability.legacy) {
-    // Coverage-ignore-block(suite): Not run.
-    DartType R = T.withDeclaredNullability(Nullability.nonNullable);
-    DartType factor_RS = factorType(typeEnvironment, R, S);
-    if (typeEnvironment.isSubtypeOf(const NullType(), S)) {
-      return factor_RS;
-    } else {
-      return factor_RS.withDeclaredNullability(Nullability.legacy);
-    }
-  }
-
   // * Else if T is FutureOr<R> and Future<R> <: S then factor(R, S)
   // * Else if T is FutureOr<R> and R <: S then factor(Future<R>, S)
   if (T is FutureOrType) {
diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart b/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart
index d15bd58..2dcc9cd 100644
--- a/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart
+++ b/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart
@@ -5627,9 +5627,7 @@
             functionType: functionType,
           );
         case Nullability.nullable:
-        // Coverage-ignore(suite): Not run.
-        case Nullability.legacy:
-          // Never? and Never* are equivalent to Null.
+          // Never? is equivalent to Null.
           return visitor.findInterfaceMember(
             const NullType(),
             name,
diff --git a/pkg/front_end/lib/src/type_inference/type_demotion.dart b/pkg/front_end/lib/src/type_inference/type_demotion.dart
index 39f79e9..e31a160 100644
--- a/pkg/front_end/lib/src/type_inference/type_demotion.dart
+++ b/pkg/front_end/lib/src/type_inference/type_demotion.dart
@@ -42,9 +42,6 @@
 
   @override
   Nullability? visitNullability(DartType node) {
-    if (node.declaredNullability == Nullability.legacy) {
-      return Nullability.nonNullable;
-    }
     return null;
   }
 
diff --git a/pkg/front_end/test/type_inference/type_constraint_gatherer_nnbd_test.dart b/pkg/front_end/test/type_inference/type_constraint_gatherer_nnbd_test.dart
index 4c1a3ba..5522cd4 100644
--- a/pkg/front_end/test/type_inference/type_constraint_gatherer_nnbd_test.dart
+++ b/pkg/front_end/test/type_inference/type_constraint_gatherer_nnbd_test.dart
@@ -140,7 +140,7 @@
         '<T extends Object?>() -> dynamic', '() -> dynamic', null);
     // () -> dynamic <: <T>() -> dynamic, never
     checkConstraintsUpper(
-        '() -> dynamic', '<T extends Object?>() ->* dynamic', null);
+        '() -> dynamic', '<T extends Object?>() -> dynamic', null);
     // <T>(T) -> T <: <U>(U) -> U, always
     checkConstraintsUpper(
         '<T extends Object?>(T) -> T', '<U extends Object?>(U) -> U', []);
diff --git a/pkg/front_end/test/type_inference/type_inference_engine_test.dart b/pkg/front_end/test/type_inference/type_inference_engine_test.dart
index 52925f0..f1226a9 100644
--- a/pkg/front_end/test/type_inference/type_inference_engine_test.dart
+++ b/pkg/front_end/test/type_inference/type_inference_engine_test.dart
@@ -25,7 +25,8 @@
   }
 
   bool checkContravariant(DartType type, List<TypeParameter> typeParameters) {
-    return check(new FunctionType([type], const VoidType(), Nullability.legacy),
+    return check(
+        new FunctionType([type], const VoidType(), Nullability.nonNullable),
         typeParameters);
   }
 
@@ -35,113 +36,117 @@
     expect(
         check(
             new FunctionType(
-                [tpt(T), tpt(U)], const VoidType(), Nullability.legacy),
+                [tpt(T), tpt(U)], const VoidType(), Nullability.nonNullable),
             [T]),
         isFalse);
     expect(
         check(
             new FunctionType(
-                [tpt(T), tpt(U)], const VoidType(), Nullability.legacy),
+                [tpt(T), tpt(U)], const VoidType(), Nullability.nonNullable),
             [U]),
         isFalse);
     expect(
         check(
             new FunctionType(
-                [tpt(T), tpt(U)], const VoidType(), Nullability.legacy),
+                [tpt(T), tpt(U)], const VoidType(), Nullability.nonNullable),
             []),
         isFalse);
     expect(
         check(
-            new FunctionType([], const VoidType(), Nullability.legacy,
+            new FunctionType([], const VoidType(), Nullability.nonNullable,
                 namedParameters: [named('a', tpt(T)), named('b', tpt(U))]),
             [T]),
         isFalse);
     expect(
         check(
-            new FunctionType([], const VoidType(), Nullability.legacy,
+            new FunctionType([], const VoidType(), Nullability.nonNullable,
                 namedParameters: [named('a', tpt(T)), named('b', tpt(U))]),
             [U]),
         isFalse);
     expect(
         check(
-            new FunctionType([], const VoidType(), Nullability.legacy,
+            new FunctionType([], const VoidType(), Nullability.nonNullable,
                 namedParameters: [named('a', tpt(T)), named('b', tpt(U))]),
             []),
         isFalse);
-    expect(
-        check(new FunctionType([], tpt(T), Nullability.legacy), [T]), isTrue);
-    expect(
-        check(new FunctionType([], tpt(T), Nullability.legacy), [U]), isFalse);
+    expect(check(new FunctionType([], tpt(T), Nullability.nonNullable), [T]),
+        isTrue);
+    expect(check(new FunctionType([], tpt(T), Nullability.nonNullable), [U]),
+        isFalse);
     expect(
         checkContravariant(
             new FunctionType(
-                [tpt(T), tpt(U)], const VoidType(), Nullability.legacy),
+                [tpt(T), tpt(U)], const VoidType(), Nullability.nonNullable),
             [T]),
         isTrue);
     expect(
         checkContravariant(
             new FunctionType(
-                [tpt(T), tpt(U)], const VoidType(), Nullability.legacy),
+                [tpt(T), tpt(U)], const VoidType(), Nullability.nonNullable),
             [U]),
         isTrue);
     expect(
         checkContravariant(
             new FunctionType(
-                [tpt(T), tpt(U)], const VoidType(), Nullability.legacy),
+                [tpt(T), tpt(U)], const VoidType(), Nullability.nonNullable),
             []),
         isFalse);
     expect(
         checkContravariant(
-            new FunctionType([], const VoidType(), Nullability.legacy,
+            new FunctionType([], const VoidType(), Nullability.nonNullable,
                 namedParameters: [named('a', tpt(T)), named('b', tpt(U))]),
             [T]),
         isTrue);
     expect(
         checkContravariant(
-            new FunctionType([], const VoidType(), Nullability.legacy,
+            new FunctionType([], const VoidType(), Nullability.nonNullable,
                 namedParameters: [named('a', tpt(T)), named('b', tpt(U))]),
             [U]),
         isTrue);
     expect(
         checkContravariant(
-            new FunctionType([], const VoidType(), Nullability.legacy,
+            new FunctionType([], const VoidType(), Nullability.nonNullable,
                 namedParameters: [named('a', tpt(T)), named('b', tpt(U))]),
             []),
         isFalse);
     expect(
         checkContravariant(
-            new FunctionType([], tpt(T), Nullability.legacy), [T]),
+            new FunctionType([], tpt(T), Nullability.nonNullable), [T]),
         isFalse);
     expect(
         checkContravariant(
-            new FunctionType([], tpt(T), Nullability.legacy), [U]),
+            new FunctionType([], tpt(T), Nullability.nonNullable), [U]),
         isFalse);
   }
 
   void test_interface_type() {
     Class cls = new Class(name: 'C', typeParameters: [T, U], fileUri: dummyUri);
     expect(
-        check(
-            new InterfaceType(cls, Nullability.legacy, [tpt(T), tpt(U)]), [T]),
+        check(new InterfaceType(cls, Nullability.nonNullable, [tpt(T), tpt(U)]),
+            [T]),
         isTrue);
     expect(
-        check(
-            new InterfaceType(cls, Nullability.legacy, [tpt(T), tpt(U)]), [U]),
+        check(new InterfaceType(cls, Nullability.nonNullable, [tpt(T), tpt(U)]),
+            [U]),
         isTrue);
     expect(
-        check(new InterfaceType(cls, Nullability.legacy, [tpt(T), tpt(U)]), []),
+        check(new InterfaceType(cls, Nullability.nonNullable, [tpt(T), tpt(U)]),
+            []),
         isFalse);
     expect(
         checkContravariant(
-            new InterfaceType(cls, Nullability.legacy, [tpt(T), tpt(U)]), [T]),
+            new InterfaceType(cls, Nullability.nonNullable, [tpt(T), tpt(U)]),
+            [T]),
         isFalse);
     expect(
         checkContravariant(
-            new InterfaceType(cls, Nullability.legacy, [tpt(T), tpt(U)]), [U]),
+            new InterfaceType(cls, Nullability.nonNullable, [tpt(T), tpt(U)]),
+            [U]),
         isFalse);
     expect(
         checkContravariant(
-            new InterfaceType(cls, Nullability.legacy, [tpt(T), tpt(U)]), []),
+            new InterfaceType(cls, Nullability.nonNullable, [tpt(T), tpt(U)]),
+            []),
         isFalse);
   }
 
@@ -184,48 +189,48 @@
   void test_typedef_type() {
     // typedef U F<T, U>(T x);
     var typedefNode = new Typedef(
-        'F', new FunctionType([tpt(T)], tpt(U), Nullability.legacy),
+        'F', new FunctionType([tpt(T)], tpt(U), Nullability.nonNullable),
         typeParameters: [T, U], fileUri: dummyUri);
     expect(
         check(
-            new TypedefType(typedefNode, Nullability.legacy,
+            new TypedefType(typedefNode, Nullability.nonNullable,
                 [const DynamicType(), const DynamicType()]),
             [V]),
         isFalse);
     expect(
         check(
-            new TypedefType(
-                typedefNode, Nullability.legacy, [tpt(V), const DynamicType()]),
+            new TypedefType(typedefNode, Nullability.nonNullable,
+                [tpt(V), const DynamicType()]),
             [V]),
         isFalse);
     expect(
         check(
-            new TypedefType(
-                typedefNode, Nullability.legacy, [const DynamicType(), tpt(V)]),
+            new TypedefType(typedefNode, Nullability.nonNullable,
+                [const DynamicType(), tpt(V)]),
             [V]),
         isTrue);
     expect(
         checkContravariant(
-            new TypedefType(typedefNode, Nullability.legacy,
+            new TypedefType(typedefNode, Nullability.nonNullable,
                 [const DynamicType(), const DynamicType()]),
             [V]),
         isFalse);
     expect(
         checkContravariant(
-            new TypedefType(
-                typedefNode, Nullability.legacy, [tpt(V), const DynamicType()]),
+            new TypedefType(typedefNode, Nullability.nonNullable,
+                [tpt(V), const DynamicType()]),
             [V]),
         isTrue);
     expect(
         checkContravariant(
-            new TypedefType(
-                typedefNode, Nullability.legacy, [const DynamicType(), tpt(V)]),
+            new TypedefType(typedefNode, Nullability.nonNullable,
+                [const DynamicType(), tpt(V)]),
             [V]),
         isFalse);
   }
 
   TypeParameterType tpt(TypeParameter param, {Variance? variance = null}) {
-    return new TypeParameterType(param, Nullability.legacy)
+    return new TypeParameterType(param, Nullability.nonNullable)
       ..parameter.variance = variance;
   }
 }
diff --git a/pkg/front_end/test/type_inference/type_schema_elimination_test.dart b/pkg/front_end/test/type_inference/type_schema_elimination_test.dart
index 5ab6e64..1294414 100644
--- a/pkg/front_end/test/type_inference/type_schema_elimination_test.dart
+++ b/pkg/front_end/test/type_inference/type_schema_elimination_test.dart
@@ -44,23 +44,23 @@
   }
 
   void test_greatestClosure_contravariant() {
-    testGreatest("(UNKNOWN) ->* dynamic", "(Never) ->* dynamic");
-    testGreatest("({UNKNOWN foo}) ->* dynamic", "({Never foo}) ->* dynamic");
+    testGreatest("(UNKNOWN) -> dynamic", "(Never) -> dynamic");
+    testGreatest("({UNKNOWN foo}) -> dynamic", "({Never foo}) -> dynamic");
   }
 
   void test_greatestClosure_contravariant_contravariant() {
-    testGreatest("((UNKNOWN) ->* dynamic) ->* dynamic",
-        "((dynamic) ->* dynamic) ->* dynamic");
+    testGreatest("((UNKNOWN) -> dynamic) -> dynamic",
+        "((dynamic) -> dynamic) -> dynamic");
   }
 
   void test_greatestClosure_covariant() {
-    testGreatest("() ->* UNKNOWN", "() ->* dynamic");
-    testGreatest("List<UNKNOWN>*", "List<dynamic>*");
+    testGreatest("() -> UNKNOWN", "() -> dynamic");
+    testGreatest("List<UNKNOWN>", "List<dynamic>");
   }
 
   void test_greatestClosure_function_multipleUnknown() {
-    testGreatest("(UNKNOWN, UNKNOWN, {UNKNOWN a, UNKNOWN b}) ->* UNKNOWN",
-        "(Never, Never, {Never a, Never b}) ->* dynamic");
+    testGreatest("(UNKNOWN, UNKNOWN, {UNKNOWN a, UNKNOWN b}) -> UNKNOWN",
+        "(Never, Never, {Never a, Never b}) -> dynamic");
   }
 
   void test_greatestClosure_simple() {
@@ -68,23 +68,23 @@
   }
 
   void test_leastClosure_contravariant() {
-    testLeast("(UNKNOWN) ->* dynamic", "(Object?) ->* dynamic");
-    testLeast("({UNKNOWN foo}) ->* dynamic", "({Object? foo}) ->* dynamic");
+    testLeast("(UNKNOWN) -> dynamic", "(Object?) -> dynamic");
+    testLeast("({UNKNOWN foo}) -> dynamic", "({Object? foo}) -> dynamic");
   }
 
   void test_leastClosure_contravariant_contravariant() {
-    testLeast("((UNKNOWN) ->* UNKNOWN) ->* dynamic",
-        "((Never) ->* Object?) ->* dynamic");
+    testLeast(
+        "((UNKNOWN) -> UNKNOWN) -> dynamic", "((Never) -> Object?) -> dynamic");
   }
 
   void test_leastClosure_covariant() {
-    testLeast("() ->* UNKNOWN", "() ->* Never");
-    testLeast("List<UNKNOWN>*", "List<Never>*");
+    testLeast("() -> UNKNOWN", "() -> Never");
+    testLeast("List<UNKNOWN>", "List<Never>");
   }
 
   void test_leastClosure_function_multipleUnknown() {
-    testLeast("(UNKNOWN, UNKNOWN, {UNKNOWN a, UNKNOWN b}) ->* UNKNOWN",
-        "(Object?, Object?, {Object? a, Object? b}) ->* Never");
+    testLeast("(UNKNOWN, UNKNOWN, {UNKNOWN a, UNKNOWN b}) -> UNKNOWN",
+        "(Object?, Object?, {Object? a, Object? b}) -> Never");
   }
 
   void test_leastClosure_simple() {
diff --git a/pkg/front_end/test/type_inference/type_schema_environment_nnbd_test.dart b/pkg/front_end/test/type_inference/type_schema_environment_nnbd_test.dart
index c0dc080..ff27de7 100644
--- a/pkg/front_end/test/type_inference/type_schema_environment_nnbd_test.dart
+++ b/pkg/front_end/test/type_inference/type_schema_environment_nnbd_test.dart
@@ -29,12 +29,12 @@
     // typeConstraint: EMPTY <: TYPE <: EMPTY
     checkConstraintLowerBound(constraint: "", bound: "UNKNOWN");
 
-    // typeConstraint: B* <: TYPE <: EMPTY
-    checkConstraintLowerBound(constraint: ":> B*", bound: "B*");
+    // typeConstraint: B <: TYPE <: EMPTY
+    checkConstraintLowerBound(constraint: ":> B", bound: "B");
 
-    // typeConstraint: UP(B*, C*) <: TYPE <: EMPTY,
-    //     where UP(B*, C*) = A*
-    checkConstraintLowerBound(constraint: ":> B* :> C*", bound: "A*");
+    // typeConstraint: UP(B, C) <: TYPE <: EMPTY,
+    //     where UP(B, C) = A
+    checkConstraintLowerBound(constraint: ":> B :> C", bound: "A");
   }
 
   void test_addUpperBound() {
@@ -49,16 +49,16 @@
     // typeConstraint: EMPTY <: TYPE <: EMPTY
     checkConstraintUpperBound(constraint: "", bound: "UNKNOWN");
 
-    // typeConstraint: EMPTY <: TYPE <: A*
-    checkConstraintUpperBound(constraint: "<: A*", bound: "A*");
+    // typeConstraint: EMPTY <: TYPE <: A
+    checkConstraintUpperBound(constraint: "<: A", bound: "A");
 
-    // typeConstraint: EMPTY <: TYPE <: DOWN(A*, B*),
-    //     where DOWN(A*, B*) = B*
-    checkConstraintUpperBound(constraint: "<: A* <: B*", bound: "B*");
+    // typeConstraint: EMPTY <: TYPE <: DOWN(A, B),
+    //     where DOWN(A, B) = B
+    checkConstraintUpperBound(constraint: "<: A <: B", bound: "B");
 
-    // typeConstraint: EMPTY <: TYPE <: DOWN(B*, C*),
-    //     where DOWN(B*, C*) = Never*
-    checkConstraintUpperBound(constraint: "<:A* <: B* <: C*", bound: "Never*");
+    // typeConstraint: EMPTY <: TYPE <: DOWN(B, C),
+    //     where DOWN(B, C) = Never
+    checkConstraintUpperBound(constraint: "<:A <: B <: C", bound: "Never");
   }
 
   /// Some of the types satisfying the TOP predicate.
@@ -76,36 +76,23 @@
     "FutureOr<Object>?": null,
     "FutureOr<FutureOr<Object>>?": null,
 
-    // T* where OBJECT(t).
-    "Object*": null,
-    "FutureOr<Object>*": null,
-    "FutureOr<FutureOr<Object>>*": null,
-
     // FutureOr<T> where TOP(T).
     "FutureOr<dynamic>": null,
     "FutureOr<void>": null,
     "FutureOr<Object?>": null,
     "FutureOr<FutureOr<Object>?>": null,
     "FutureOr<FutureOr<FutureOr<Object>>?>": null,
-    "FutureOr<Object*>": null,
-    "FutureOr<FutureOr<Object>*>": null,
-    "FutureOr<FutureOr<FutureOr<Object>>*>": null,
     "FutureOr<FutureOr<dynamic>?>": null,
     "FutureOr<FutureOr<void>?>": null,
     "FutureOr<FutureOr<Object?>?>": null,
     "FutureOr<FutureOr<FutureOr<Object>?>?>": null,
     "FutureOr<FutureOr<FutureOr<FutureOr<Object>>?>?>": null,
-    "FutureOr<FutureOr<Object*>?>": null,
-    "FutureOr<FutureOr<FutureOr<Object>*>?>": null,
-    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>*>?>": null,
-    "FutureOr<FutureOr<dynamic>*>": null,
-    "FutureOr<FutureOr<void>*>": null,
-    "FutureOr<FutureOr<Object?>*>": null,
-    "FutureOr<FutureOr<FutureOr<Object>?>*>": null,
-    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>?>*>": null,
-    "FutureOr<FutureOr<Object*>*>": null,
-    "FutureOr<FutureOr<FutureOr<Object>*>*>": null,
-    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>*>*>": null,
+    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>>?>": null,
+    "FutureOr<FutureOr<dynamic>>": null,
+    "FutureOr<FutureOr<void>>": null,
+    "FutureOr<FutureOr<Object?>>": null,
+    "FutureOr<FutureOr<FutureOr<Object>?>>": null,
+    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>?>>": null,
 
     // T? where TOP(T).
     "FutureOr<dynamic>?": null,
@@ -113,51 +100,19 @@
     "FutureOr<Object?>?": null,
     "FutureOr<FutureOr<Object>?>?": null,
     "FutureOr<FutureOr<FutureOr<Object>>?>?": null,
-    "FutureOr<Object*>?": null,
-    "FutureOr<FutureOr<Object>*>?": null,
-    "FutureOr<FutureOr<FutureOr<Object>>*>?": null,
+    "FutureOr<FutureOr<FutureOr<Object>>>?": null,
     "FutureOr<FutureOr<dynamic>?>?": null,
     "FutureOr<FutureOr<void>?>?": null,
     "FutureOr<FutureOr<Object?>?>?": null,
     "FutureOr<FutureOr<FutureOr<Object>?>?>?": null,
     "FutureOr<FutureOr<FutureOr<FutureOr<Object>>?>?>?": null,
-    "FutureOr<FutureOr<Object*>?>?": null,
-    "FutureOr<FutureOr<FutureOr<Object>*>?>?": null,
-    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>*>?>?": null,
-    "FutureOr<FutureOr<dynamic>*>?": null,
-    "FutureOr<FutureOr<void>*>?": null,
-    "FutureOr<FutureOr<Object?>*>?": null,
-    "FutureOr<FutureOr<FutureOr<Object>?>*>?": null,
-    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>?>*>?": null,
-    "FutureOr<FutureOr<Object*>*>?": null,
-    "FutureOr<FutureOr<FutureOr<Object>*>*>?": null,
-    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>*>*>?": null,
-
-    // T* where TOP(T).
-    "FutureOr<dynamic>*": null,
-    "FutureOr<void>*": null,
-    "FutureOr<Object?>*": null,
-    "FutureOr<FutureOr<Object>?>*": null,
-    "FutureOr<FutureOr<FutureOr<Object>>?>*": null,
-    "FutureOr<Object*>*": null,
-    "FutureOr<FutureOr<Object>*>*": null,
-    "FutureOr<FutureOr<FutureOr<Object>>*>*": null,
-    "FutureOr<FutureOr<dynamic>?>*": null,
-    "FutureOr<FutureOr<void>?>*": null,
-    "FutureOr<FutureOr<Object?>?>*": null,
-    "FutureOr<FutureOr<FutureOr<Object>?>?>*": null,
-    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>?>?>*": null,
-    "FutureOr<FutureOr<Object*>?>*": null,
-    "FutureOr<FutureOr<FutureOr<Object>*>?>*": null,
-    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>*>?>*": null,
-    "FutureOr<FutureOr<dynamic>*>*": null,
-    "FutureOr<FutureOr<void>*>*": null,
-    "FutureOr<FutureOr<Object?>*>*": null,
-    "FutureOr<FutureOr<FutureOr<Object>?>*>*": null,
-    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>?>*>*": null,
-    "FutureOr<FutureOr<Object*>*>*": null,
-    "FutureOr<FutureOr<FutureOr<Object>*>*>*": null,
-    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>*>*>*": null,
+    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>>?>?": null,
+    "FutureOr<FutureOr<dynamic>>?": null,
+    "FutureOr<FutureOr<void>>?": null,
+    "FutureOr<FutureOr<Object?>>?": null,
+    "FutureOr<FutureOr<FutureOr<Object>?>>?": null,
+    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>?>>?": null,
+    "FutureOr<FutureOr<FutureOr<FutureOr<Object>>>>?": null,
   };
 
   /// Some of the types satisfying the OBJECT predicate.
@@ -202,11 +157,6 @@
     "Xn?": "Xn extends Never",
     "Yn?": "Yn extends Zn, Zn extends Never",
 
-    // T* where BOTTOM(T).
-    "Never*": null,
-    "Vn*": "Vn extends Never",
-    "Wn*": "Wn extends Tn, Tn extends Never",
-
     // Null.
     "Null": null,
   };
@@ -222,11 +172,6 @@
   void test_lower_bound_bottom() {
     parseTestLibrary("class A;");
 
-    for (String type in ["A*", "A?", "A"]) {
-      checkLowerBound(type1: "Never", type2: type, lowerBound: "Never");
-      checkLowerBound(type1: type, type2: "Never", lowerBound: "Never");
-    }
-
     // DOWN(T1, T2) where BOTTOM(T1) and BOTTOM(T2) =
     //   T1 if MOREBOTTOM(T1, T2)
     //   T2 otherwise
@@ -249,7 +194,7 @@
     }
 
     // DOWN(T1, T2) = T2 if BOTTOM(T2)
-    for (String type in ["A*", "A?", "A"]) {
+    for (String type in ["A", "A?"]) {
       for (String t2 in bottomPredicateEnumeration.keys) {
         checkLowerBound(
             type1: type,
@@ -261,7 +206,7 @@
 
     // DOWN(T1, T2) = T1 if BOTTOM(T1)
     for (String t1 in bottomPredicateEnumeration.keys) {
-      for (String type in ["A*", "A?", "A"]) {
+      for (String type in ["A", "A?"]) {
         checkLowerBound(
             type1: t1,
             type2: type,
@@ -297,11 +242,6 @@
     for (String t1 in nullPredicateEnumeration.keys) {
       checkLowerBound(
           type1: t1,
-          type2: "A*",
-          lowerBound: t1,
-          typeParameters: nullPredicateEnumeration[t1]);
-      checkLowerBound(
-          type1: t1,
           type2: "A?",
           lowerBound: t1,
           typeParameters: nullPredicateEnumeration[t1]);
@@ -317,11 +257,6 @@
     //   Never otherwise
     for (String t2 in nullPredicateEnumeration.keys) {
       checkLowerBound(
-          type1: "A*",
-          type2: t2,
-          lowerBound: t2,
-          typeParameters: nullPredicateEnumeration[t2]);
-      checkLowerBound(
           type1: "A?",
           type2: t2,
           lowerBound: t2,
@@ -374,54 +309,47 @@
     """);
 
     // TODO(cstefantsova): Test for various nullabilities.
+    checkLowerBound(type1: "() -> A", type2: "() -> B", lowerBound: "() -> B");
     checkLowerBound(
-        type1: "() ->* A*", type2: "() ->* B*", lowerBound: "() ->* B*");
+        type1: "() -> void",
+        type2: "(A, B) -> void",
+        lowerBound: "([A, B]) -> void");
     checkLowerBound(
-        type1: "() ->* void",
-        type2: "(A*, B*) ->* void",
-        lowerBound: "([A*, B*]) ->* void");
+        type1: "(A, B) -> void",
+        type2: "() -> void",
+        lowerBound: "([A, B]) -> void");
     checkLowerBound(
-        type1: "(A*, B*) ->* void",
-        type2: "() ->* void",
-        lowerBound: "([A*, B*]) ->* void");
+        type1: "(A) -> void", type2: "(B) -> void", lowerBound: "(A) -> void");
     checkLowerBound(
-        type1: "(A*) ->* void",
-        type2: "(B*) ->* void",
-        lowerBound: "(A*) ->* void");
+        type1: "(B) -> void", type2: "(A) -> void", lowerBound: "(A) -> void");
     checkLowerBound(
-        type1: "(B*) ->* void",
-        type2: "(A*) ->* void",
-        lowerBound: "(A*) ->* void");
+        type1: "({A a}) -> void",
+        type2: "({B b}) -> void",
+        lowerBound: "({A a, B b}) -> void");
     checkLowerBound(
-        type1: "({A* a}) ->* void",
-        type2: "({B* b}) ->* void",
-        lowerBound: "({A* a, B* b}) ->* void");
+        type1: "({B b}) -> void",
+        type2: "({A a}) -> void",
+        lowerBound: "({A a, B b}) -> void");
     checkLowerBound(
-        type1: "({B* b}) ->* void",
-        type2: "({A* a}) ->* void",
-        lowerBound: "({A* a, B* b}) ->* void");
+        type1: "({A a, A c}) -> void",
+        type2: "({B b, B d}) -> void",
+        lowerBound: "({A a, B b, A c, B d}) -> void");
     checkLowerBound(
-        type1: "({A* a, A* c}) ->* void",
-        type2: "({B* b, B* d}) ->* void",
-        lowerBound: "({A* a, B* b, A* c, B* d}) ->* void");
+        type1: "({A a, B b}) -> void",
+        type2: "({B a, A b}) -> void",
+        lowerBound: "({A a, A b}) -> void");
     checkLowerBound(
-        type1: "({A* a, B* b}) ->* void",
-        type2: "({B* a, A* b}) ->* void",
-        lowerBound: "({A* a, A* b}) ->* void");
+        type1: "({B a, A b}) -> void",
+        type2: "({A a, B b}) -> void",
+        lowerBound: "({A a, A b}) -> void");
     checkLowerBound(
-        type1: "({B* a, A* b}) ->* void",
-        type2: "({A* a, B* b}) ->* void",
-        lowerBound: "({A* a, A* b}) ->* void");
+        type1: "(B, {A a}) -> void",
+        type2: "(B) -> void",
+        lowerBound: "(B, {A a}) -> void");
     checkLowerBound(
-        type1: "(B*, {A* a}) ->* void",
-        type2: "(B*) ->* void",
-        lowerBound: "(B*, {A* a}) ->* void");
+        type1: "({A a}) -> void", type2: "(B) -> void", lowerBound: "Never");
     checkLowerBound(
-        type1: "({A* a}) -> void", type2: "(B*) -> void", lowerBound: "Never");
-    checkLowerBound(
-        type1: "({A* a}) -> void",
-        type2: "([B*]) ->* void",
-        lowerBound: "Never");
+        type1: "({A a}) -> void", type2: "([B]) -> void", lowerBound: "Never");
     checkLowerBound(
         type1: "<X>() -> void",
         type2: "<Y>() -> void",
@@ -481,7 +409,7 @@
         type1: "({A a, B b})", type2: "({A a})", lowerBound: "Never");
 
     checkLowerBound(type1: "(A, B)", type2: "Record", lowerBound: "(A, B)");
-    checkLowerBound(type2: "Record", type1: "(A, B)", lowerBound: "(A, B)");
+    checkLowerBound(type1: "Record", type2: "(A, B)", lowerBound: "(A, B)");
 
     checkLowerBound(
         type1: "(A, B)", type2: "(A, B) -> void", lowerBound: "Never");
@@ -491,9 +419,8 @@
   void test_lower_bound_identical() {
     parseTestLibrary("class A;");
 
-    checkLowerBound(type1: "A*", type2: "A*", lowerBound: "A*");
-    checkLowerBound(type1: "A?", type2: "A?", lowerBound: "A?");
     checkLowerBound(type1: "A", type2: "A", lowerBound: "A");
+    checkLowerBound(type1: "A?", type2: "A?", lowerBound: "A?");
   }
 
   void test_lower_bound_subtype() {
@@ -502,84 +429,42 @@
       class B extends A;
     """);
 
-    checkLowerBound(type1: "A*", type2: "B*", lowerBound: "B*");
-    checkLowerBound(type1: "A*", type2: "B?", lowerBound: "B*");
-    checkLowerBound(type1: "A*", type2: "B", lowerBound: "B");
-
-    checkLowerBound(type1: "A?", type2: "B*", lowerBound: "B*");
-    checkLowerBound(type1: "A?", type2: "B?", lowerBound: "B?");
-    checkLowerBound(type1: "A?", type2: "B", lowerBound: "B");
-
-    checkLowerBound(type1: "A", type2: "B*", lowerBound: "B");
-    checkLowerBound(type1: "A", type2: "B?", lowerBound: "B");
     checkLowerBound(type1: "A", type2: "B", lowerBound: "B");
+    checkLowerBound(type1: "A", type2: "B?", lowerBound: "B");
 
-    checkLowerBound(type1: "B*", type2: "A*", lowerBound: "B*");
-    checkLowerBound(type1: "B?", type2: "A*", lowerBound: "B*");
-    checkLowerBound(type1: "B", type2: "A*", lowerBound: "B");
+    checkLowerBound(type1: "A?", type2: "B", lowerBound: "B");
+    checkLowerBound(type1: "A?", type2: "B?", lowerBound: "B?");
 
-    checkLowerBound(type1: "B*", type2: "A?", lowerBound: "B*");
-    checkLowerBound(type1: "B?", type2: "A?", lowerBound: "B?");
-    checkLowerBound(type1: "B", type2: "A?", lowerBound: "B");
-
-    checkLowerBound(type1: "B*", type2: "A", lowerBound: "B");
-    checkLowerBound(type1: "B?", type2: "A", lowerBound: "B");
     checkLowerBound(type1: "B", type2: "A", lowerBound: "B");
+    checkLowerBound(type1: "B?", type2: "A", lowerBound: "B");
 
-    checkLowerBound(
-        type1: "Iterable<A>*", type2: "List<B>*", lowerBound: "List<B>*");
-    checkLowerBound(
-        type1: "Iterable<A>*", type2: "List<B>?", lowerBound: "List<B>*");
-    checkLowerBound(
-        type1: "Iterable<A>*", type2: "List<B>", lowerBound: "List<B>");
+    checkLowerBound(type1: "B", type2: "A?", lowerBound: "B");
+    checkLowerBound(type1: "B?", type2: "A?", lowerBound: "B?");
 
     checkLowerBound(
-        type1: "Iterable<A>?", type2: "List<B>*", lowerBound: "List<B>*");
-    checkLowerBound(
-        type1: "Iterable<A>?", type2: "List<B>?", lowerBound: "List<B>?");
-    checkLowerBound(
-        type1: "Iterable<A>?", type2: "List<B>", lowerBound: "List<B>");
-
-    checkLowerBound(
-        type1: "Iterable<A>", type2: "List<B>*", lowerBound: "List<B>");
-    checkLowerBound(
-        type1: "Iterable<A>", type2: "List<B>?", lowerBound: "List<B>");
-    checkLowerBound(
         type1: "Iterable<A>", type2: "List<B>", lowerBound: "List<B>");
+    checkLowerBound(
+        type1: "Iterable<A>", type2: "List<B>?", lowerBound: "List<B>");
 
     checkLowerBound(
-        type1: "List<B>*", type2: "Iterable<A>*", lowerBound: "List<B>*");
+        type1: "Iterable<A>?", type2: "List<B>", lowerBound: "List<B>");
     checkLowerBound(
-        type1: "List<B>?", type2: "Iterable<A>*", lowerBound: "List<B>*");
-    checkLowerBound(
-        type1: "List<B>", type2: "Iterable<A>*", lowerBound: "List<B>");
+        type1: "Iterable<A>?", type2: "List<B>?", lowerBound: "List<B>?");
 
     checkLowerBound(
-        type1: "List<B>*", type2: "Iterable<A>?", lowerBound: "List<B>*");
-    checkLowerBound(
-        type1: "List<B>?", type2: "Iterable<A>?", lowerBound: "List<B>?");
-    checkLowerBound(
-        type1: "List<B>", type2: "Iterable<A>?", lowerBound: "List<B>");
-
-    checkLowerBound(
-        type1: "List<B>*", type2: "Iterable<A>", lowerBound: "List<B>");
-    checkLowerBound(
-        type1: "List<B>?", type2: "Iterable<A>", lowerBound: "List<B>");
-    checkLowerBound(
         type1: "List<B>", type2: "Iterable<A>", lowerBound: "List<B>");
+    checkLowerBound(
+        type1: "List<B>?", type2: "Iterable<A>", lowerBound: "List<B>");
+
+    checkLowerBound(
+        type1: "List<B>", type2: "Iterable<A>?", lowerBound: "List<B>");
+    checkLowerBound(
+        type1: "List<B>?", type2: "Iterable<A>?", lowerBound: "List<B>?");
   }
 
   void test_lower_bound_top() {
     parseTestLibrary("class A;");
 
-    // TODO(cstefantsova): Test for various nullabilities.
-    checkLowerBound(type1: "dynamic", type2: "A*", lowerBound: "A*");
-    checkLowerBound(type1: "A*", type2: "dynamic", lowerBound: "A*");
-    checkLowerBound(type1: "Object?", type2: "A*", lowerBound: "A*");
-    checkLowerBound(type1: "A*", type2: "Object?", lowerBound: "A*");
-    checkLowerBound(type1: "void", type2: "A*", lowerBound: "A*");
-    checkLowerBound(type1: "A*", type2: "void", lowerBound: "A*");
-
     // DOWN(T1, T2) where TOP(T1) and TOP(T2) =
     //   T1 if MORETOP(T2, T1)
     //   T2 otherwise
@@ -605,17 +490,17 @@
     for (String t1 in topPredicateEnumeration.keys) {
       checkLowerBound(
           type1: t1,
-          type2: "A*",
-          lowerBound: "A*",
+          type2: "A",
+          lowerBound: "A",
           typeParameters: topPredicateEnumeration[t1]);
     }
 
     // DOWN(T1, T2) = T1 if TOP(T2)
     for (String t2 in topPredicateEnumeration.keys) {
       checkLowerBound(
-          type1: "A*",
+          type1: "A",
           type2: t2,
-          lowerBound: "A*",
+          lowerBound: "A",
           typeParameters: topPredicateEnumeration[t2]);
     }
   }
@@ -623,13 +508,11 @@
   void test_lower_bound_unknown() {
     parseTestLibrary("class A;");
 
-    checkLowerBound(type1: "A*", type2: "UNKNOWN", lowerBound: "A*");
-    checkLowerBound(type1: "A?", type2: "UNKNOWN", lowerBound: "A?");
     checkLowerBound(type1: "A", type2: "UNKNOWN", lowerBound: "A");
+    checkLowerBound(type1: "A?", type2: "UNKNOWN", lowerBound: "A?");
 
-    checkLowerBound(type1: "UNKNOWN", type2: "A*", lowerBound: "A*");
-    checkLowerBound(type1: "UNKNOWN", type2: "A?", lowerBound: "A?");
     checkLowerBound(type1: "UNKNOWN", type2: "A", lowerBound: "A");
+    checkLowerBound(type1: "UNKNOWN", type2: "A?", lowerBound: "A?");
   }
 
   void test_lower_bound_unrelated() {
@@ -638,17 +521,11 @@
       class B;
     """);
 
-    checkLowerBound(type1: "A*", type2: "B*", lowerBound: "Never*");
-    checkLowerBound(type1: "A*", type2: "B?", lowerBound: "Never*");
-    checkLowerBound(type1: "A*", type2: "B", lowerBound: "Never");
-
-    checkLowerBound(type1: "A?", type2: "B*", lowerBound: "Never*");
-    checkLowerBound(type1: "A?", type2: "B?", lowerBound: "Never?");
-    checkLowerBound(type1: "A?", type2: "B", lowerBound: "Never");
-
-    checkLowerBound(type1: "A", type2: "B*", lowerBound: "Never");
-    checkLowerBound(type1: "A", type2: "B?", lowerBound: "Never");
     checkLowerBound(type1: "A", type2: "B", lowerBound: "Never");
+    checkLowerBound(type1: "A", type2: "B?", lowerBound: "Never");
+
+    checkLowerBound(type1: "A?", type2: "B", lowerBound: "Never");
+    checkLowerBound(type1: "A?", type2: "B?", lowerBound: "Never?");
   }
 
   void test_inferGenericFunctionOrType() {
@@ -718,7 +595,7 @@
     checkInference(
         typeParametersToInfer: "T extends Object?",
         functionType: "(T, T) -> List<T>",
-        actualParameterTypes: "int*, double*",
+        actualParameterTypes: "int, double",
         returnContextType: null,
         inferredTypesFromDownwardPhase: "UNKNOWN",
         expectedTypes: "num");
@@ -727,47 +604,47 @@
   void test_inferTypeFromConstraints_applyBound() {
     parseTestLibrary("");
 
-    // Assuming: class A<T extends num*> {}
+    // Assuming: class A<T extends num> {}
 
     // TODO(cstefantsova): Test for various nullabilities.
 
     // With no constraints:
     // Downward inference should infer A<?>
     checkInferenceFromConstraints(
-        typeParameter: "T extends num*",
+        typeParameter: "T extends num",
         constraints: "",
         downwardsInferPhase: true,
         expected: "UNKNOWN");
-    // Upward inference should infer A<num*>
+    // Upward inference should infer A<num>
     checkInferenceFromConstraints(
-        typeParameter: "T extends num*",
+        typeParameter: "T extends num",
         constraints: "",
         downwardsInferPhase: false,
         inferredTypeFromDownwardPhase: "UNKNOWN",
-        expected: "num*");
+        expected: "num");
 
-    // With an upper bound of Object*:
-    // Downward inference should infer A<num*>
+    // With an upper bound of Object:
+    // Downward inference should infer A<num>
     checkInferenceFromConstraints(
-        typeParameter: "T extends num*",
-        constraints: "<: Object*",
+        typeParameter: "T extends num",
+        constraints: "<: Object",
         downwardsInferPhase: true,
-        expected: "num*");
-    // Upward inference should infer A<num*>
+        expected: "num");
+    // Upward inference should infer A<num>
     checkInferenceFromConstraints(
-        typeParameter: "T extends num*",
-        constraints: "<: Object*",
+        typeParameter: "T extends num",
+        constraints: "<: Object",
         downwardsInferPhase: false,
-        inferredTypeFromDownwardPhase: "num*",
-        expected: "num*");
-    // Upward inference should still infer A<num*> even if there are more
+        inferredTypeFromDownwardPhase: "num",
+        expected: "num");
+    // Upward inference should still infer A<num> even if there are more
     // constraints now, because num was finalized during downward inference.
     checkInferenceFromConstraints(
-        typeParameter: "T extends num*",
-        constraints: ":> int* <: int*",
+        typeParameter: "T extends num",
+        constraints: ":> int <: int",
         downwardsInferPhase: false,
-        inferredTypeFromDownwardPhase: "num*",
-        expected: "num*");
+        inferredTypeFromDownwardPhase: "num",
+        expected: "num");
   }
 
   void test_inferTypeFromConstraints_simple() {
@@ -775,14 +652,14 @@
 
     // TODO(cstefantsova): Test for various nullabilities.
 
-    // With an upper bound of List<?>*:
-    // Downwards inference should infer List<List<?>*>*
+    // With an upper bound of List<?>:
+    // Downwards inference should infer List<List<?>>
     checkInferenceFromConstraints(
         typeParameter: "T extends Object?",
         constraints: "<: List<UNKNOWN>",
         downwardsInferPhase: true,
         expected: "List<UNKNOWN>");
-    // Upwards inference should refine that to List<List<Object?>*>*
+    // Upwards inference should refine that to List<List<Object?>>
     checkInferenceFromConstraints(
         typeParameter: "T extends Object?",
         constraints: "<: List<UNKNOWN>",
@@ -812,19 +689,19 @@
     """);
 
     // TODO(cstefantsova): Test for various nullabilities.
-    checkUpperBound(type1: "B*", type2: "E*", upperBound: "B*");
-    checkUpperBound(type1: "D*", type2: "C*", upperBound: "C*");
-    checkUpperBound(type1: "D*", type2: "E*", upperBound: "A*");
-    checkUpperBound(type1: "D*", type2: "A*", upperBound: "A*");
-    checkUpperBound(type1: "B*", type2: "K*", upperBound: "A*");
-    checkUpperBound(type1: "B*", type2: "L*", upperBound: "A*");
+    checkUpperBound(type1: "B", type2: "E", upperBound: "B");
+    checkUpperBound(type1: "D", type2: "C", upperBound: "C");
+    checkUpperBound(type1: "D", type2: "E", upperBound: "A");
+    checkUpperBound(type1: "D", type2: "A", upperBound: "A");
+    checkUpperBound(type1: "B", type2: "K", upperBound: "A");
+    checkUpperBound(type1: "B", type2: "L", upperBound: "A");
   }
 
   void test_upper_bound_commonClass() {
     parseTestLibrary("");
 
     checkUpperBound(
-        type1: "List<int*>", type2: "List<double*>", upperBound: "List<num*>");
+        type1: "List<int>", type2: "List<double>", upperBound: "List<num>");
     checkUpperBound(
         type1: "List<int?>", type2: "List<double>", upperBound: "List<num?>");
   }
@@ -847,57 +724,43 @@
     checkUpperBound(
         type1: "() ->? A", type2: "() -> B?", upperBound: "() ->? A?");
     checkUpperBound(
-        type1: "([A*]) ->* void",
-        type2: "(A*) ->* void",
-        upperBound: "Function*");
+        type1: "([A]) -> void", type2: "(A) -> void", upperBound: "Function");
     checkUpperBound(
-        type1: "() ->* void",
-        type2: "(A*, B*) ->* void",
-        upperBound: "Function*");
+        type1: "() -> void", type2: "(A, B) -> void", upperBound: "Function");
     checkUpperBound(
-        type1: "(A*, B*) ->* void",
-        type2: "() ->* void",
-        upperBound: "Function*");
+        type1: "(A, B) -> void", type2: "() -> void", upperBound: "Function");
     checkUpperBound(
-        type1: "(A*) ->* void",
-        type2: "(B*) ->* void",
-        upperBound: "(B*) ->* void");
+        type1: "(A) -> void", type2: "(B) -> void", upperBound: "(B) -> void");
     checkUpperBound(
-        type1: "(B*) ->* void",
-        type2: "(A*) ->* void",
-        upperBound: "(B*) ->* void");
+        type1: "(B) -> void", type2: "(A) -> void", upperBound: "(B) -> void");
     checkUpperBound(
-        type1: "({A* a}) ->* void",
-        type2: "({B* b}) ->* void",
-        upperBound: "() ->* void");
+        type1: "({A a}) -> void",
+        type2: "({B b}) -> void",
+        upperBound: "() -> void");
     checkUpperBound(
-        type1: "({B* b}) ->* void",
-        type2: "({A* a}) ->* void",
-        upperBound: "() ->* void");
+        type1: "({B b}) -> void",
+        type2: "({A a}) -> void",
+        upperBound: "() -> void");
     checkUpperBound(
-        type1: "({A* a, A* c}) ->* void",
-        type2: "({B* b, B* d}) ->* void",
-        upperBound: "() ->* void");
+        type1: "({A a, A c}) -> void",
+        type2: "({B b, B d}) -> void",
+        upperBound: "() -> void");
     checkUpperBound(
-        type1: "({A* a, B* b}) ->* void",
-        type2: "({B* a, A* b}) ->* void",
-        upperBound: "({B* a, B* b}) ->* void");
+        type1: "({A a, B b}) -> void",
+        type2: "({B a, A b}) -> void",
+        upperBound: "({B a, B b}) -> void");
     checkUpperBound(
-        type1: "({B* a, A* b}) ->* void",
-        type2: "({A* a, B* b}) ->* void",
-        upperBound: "({B* a, B* b}) ->* void");
+        type1: "({B a, A b}) -> void",
+        type2: "({A a, B b}) -> void",
+        upperBound: "({B a, B b}) -> void");
     checkUpperBound(
-        type1: "(B*, {A* a}) ->* void",
-        type2: "(B*) ->* void",
-        upperBound: "(B*) ->* void");
+        type1: "(B, {A a}) -> void",
+        type2: "(B) -> void",
+        upperBound: "(B) -> void");
     checkUpperBound(
-        type1: "({A* a}) ->* void",
-        type2: "(B*) ->* void",
-        upperBound: "Function*");
+        type1: "({A a}) -> void", type2: "(B) -> void", upperBound: "Function");
     checkUpperBound(
-        type1: "() ->* void",
-        type2: "([B*]) ->* void",
-        upperBound: "() ->* void");
+        type1: "() -> void", type2: "([B]) -> void", upperBound: "() -> void");
     checkUpperBound(
         type1: "<X>() -> void",
         type2: "<Y>() -> void",
@@ -962,7 +825,7 @@
         type1: "({A a, B b})", type2: "({A a})", upperBound: "Record");
 
     checkUpperBound(type1: "(A, B)", type2: "Record", upperBound: "Record");
-    checkUpperBound(type2: "Record", type1: "(A, B)", upperBound: "Record");
+    checkUpperBound(type1: "Record", type2: "(A, B)", upperBound: "Record");
 
     checkUpperBound(
         type1: "(A, B)", type2: "(A, B) -> void", upperBound: "Object");
@@ -972,17 +835,11 @@
   void test_upper_bound_identical() {
     parseTestLibrary("class A;");
 
-    checkUpperBound(type1: "A*", type2: "A*", upperBound: "A*");
-    checkUpperBound(type1: "A*", type2: "A?", upperBound: "A?");
-    checkUpperBound(type1: "A*", type2: "A", upperBound: "A*");
-
-    checkUpperBound(type1: "A?", type2: "A*", upperBound: "A?");
-    checkUpperBound(type1: "A?", type2: "A?", upperBound: "A?");
-    checkUpperBound(type1: "A?", type2: "A", upperBound: "A?");
-
-    checkUpperBound(type1: "A", type2: "A*", upperBound: "A*");
-    checkUpperBound(type1: "A", type2: "A?", upperBound: "A?");
     checkUpperBound(type1: "A", type2: "A", upperBound: "A");
+    checkUpperBound(type1: "A", type2: "A?", upperBound: "A?");
+
+    checkUpperBound(type1: "A?", type2: "A", upperBound: "A?");
+    checkUpperBound(type1: "A?", type2: "A?", upperBound: "A?");
   }
 
   void test_upper_bound_sameClass() {
@@ -993,13 +850,9 @@
     """);
 
     checkUpperBound(
-        type1: "Pair<A*, B*>",
-        type2: "Pair<B*, A*>",
-        upperBound: "Pair<A*, A*>");
+        type1: "Pair<A, B>", type2: "Pair<B, A>", upperBound: "Pair<A, A>");
     checkUpperBound(
-        type1: "Pair<A*, B*>",
-        type2: "Pair<B?, A>",
-        upperBound: "Pair<A?, A*>");
+        type1: "Pair<A, B>", type2: "Pair<B?, A>", upperBound: "Pair<A?, A>");
     checkUpperBound(
         type1: "Pair<A?, B?>", type2: "Pair<B, A>", upperBound: "Pair<A?, A?>");
   }
@@ -1013,98 +866,45 @@
     // UP(T1, T2) = T2 if T1 <: T2
     //   Note that both types must be class types at this point
     checkUpperBound(
-        type1: "List<B*>", type2: "Iterable<A*>", upperBound: "Iterable<A*>");
+        type1: "List<B>", type2: "Iterable<A>", upperBound: "Iterable<A>");
     checkUpperBound(
-        type1: "List<B*>", type2: "Iterable<A?>", upperBound: "Iterable<A?>");
+        type1: "List<B>", type2: "Iterable<A?>", upperBound: "Iterable<A?>");
     checkUpperBound(
-        type1: "List<B*>", type2: "Iterable<A>", upperBound: "Iterable<A>");
-    checkUpperBound(
-        type1: "List<B>*", type2: "Iterable<A>*", upperBound: "Iterable<A>*");
-    checkUpperBound(
-        type1: "List<B>*", type2: "Iterable<A>?", upperBound: "Iterable<A>?");
-    checkUpperBound(
-        type1: "List<B>*", type2: "Iterable<A>", upperBound: "Iterable<A>*");
-    checkUpperBound(
-        type1: "List<B>?", type2: "Iterable<A>*", upperBound: "Iterable<A>?");
-    checkUpperBound(
-        type1: "List<B>?", type2: "Iterable<A>?", upperBound: "Iterable<A>?");
+        type1: "List<B>", type2: "Iterable<A>?", upperBound: "Iterable<A>?");
     checkUpperBound(
         type1: "List<B>?", type2: "Iterable<A>", upperBound: "Iterable<A>?");
+    checkUpperBound(
+        type1: "List<B>?", type2: "Iterable<A>?", upperBound: "Iterable<A>?");
 
     // UP(T1, T2) = T2 if T1 <: T2
     //   Note that both types must be class types at this point
     checkUpperBound(
-        type1: "List<B?>", type2: "Iterable<A*>", upperBound: "Iterable<A*>");
-    checkUpperBound(
         type1: "List<B?>", type2: "Iterable<A?>", upperBound: "Iterable<A?>");
-    checkUpperBound(
-        type1: "List<B>?", type2: "Iterable<A>*", upperBound: "Iterable<A>?");
-    checkUpperBound(
-        type1: "List<B>?", type2: "Iterable<A>?", upperBound: "Iterable<A>?");
-    checkUpperBound(
-        type1: "List<B>?", type2: "Iterable<A>", upperBound: "Iterable<A>?");
+
     // UP(C0<T0, ..., Tn>, C1<S0, ..., Sk>)
     //     = least upper bound of two interfaces as in Dart 1.
     checkUpperBound(
         type1: "List<B?>", type2: "Iterable<A>", upperBound: "Object");
 
-    // UP(T1, T2) = T2 if T1 <: T2
-    //   Note that both types must be class types at this point
-    checkUpperBound(
-        type1: "List<B>", type2: "Iterable<A*>", upperBound: "Iterable<A*>");
-    checkUpperBound(
-        type1: "List<B>", type2: "Iterable<A?>", upperBound: "Iterable<A?>");
-    checkUpperBound(
-        type1: "List<B>", type2: "Iterable<A>", upperBound: "Iterable<A>");
-    checkUpperBound(
-        type1: "List<B>", type2: "Iterable<A>*", upperBound: "Iterable<A>*");
-    checkUpperBound(
-        type1: "List<B>", type2: "Iterable<A>?", upperBound: "Iterable<A>?");
-
-    // UP(T1, T2) = T1 if T2 <: T1
-    //   Note that both types must be class types at this point
-    checkUpperBound(
-        type1: "Iterable<A*>", type2: "List<B*>", upperBound: "Iterable<A*>");
-    checkUpperBound(
-        type1: "Iterable<A*>", type2: "List<B?>", upperBound: "Iterable<A*>");
-    checkUpperBound(
-        type1: "Iterable<A*>", type2: "List<B>", upperBound: "Iterable<A*>");
-    checkUpperBound(
-        type1: "Iterable<A>*", type2: "List<B>*", upperBound: "Iterable<A>*");
-    checkUpperBound(
-        type1: "Iterable<A>*", type2: "List<B>?", upperBound: "Iterable<A>?");
-    checkUpperBound(
-        type1: "Iterable<A>*", type2: "List<B>", upperBound: "Iterable<A>*");
-
-    // UP(T1, T2) = T1 if T2 <: T1
-    //   Note that both types must be class types at this point
-    checkUpperBound(
-        type1: "Iterable<A?>", type2: "List<B*>", upperBound: "Iterable<A?>");
-    checkUpperBound(
-        type1: "Iterable<A?>", type2: "List<B?>", upperBound: "Iterable<A?>");
-    checkUpperBound(
-        type1: "Iterable<A?>", type2: "List<B>", upperBound: "Iterable<A?>");
-    checkUpperBound(
-        type1: "Iterable<A>?", type2: "List<B>*", upperBound: "Iterable<A>?");
-    checkUpperBound(
-        type1: "Iterable<A>?", type2: "List<B>?", upperBound: "Iterable<A>?");
-    checkUpperBound(
-        type1: "Iterable<A>?", type2: "List<B>", upperBound: "Iterable<A>?");
-
-    // UP(T1, T2) = T1 if T2 <: T1
-    //   Note that both types must be class types at this point
-    checkUpperBound(
-        type1: "Iterable<A>", type2: "List<B*>", upperBound: "Iterable<A>");
-    checkUpperBound(
-        type1: "Iterable<A>", type2: "List<B>*", upperBound: "Iterable<A>*");
-    // UP(C0<T0, ..., Tn>, C1<S0, ..., Sk>)
-    //     = least upper bound of two interfaces as in Dart 1.
-    checkUpperBound(
-        type1: "Iterable<A>", type2: "List<B?>", upperBound: "Object");
     // UP(T1, T2) = T1 if T2 <: T1
     //   Note that both types must be class types at this point
     checkUpperBound(
         type1: "Iterable<A>", type2: "List<B>", upperBound: "Iterable<A>");
+    checkUpperBound(
+        type1: "Iterable<A>", type2: "List<B?>", upperBound: "Object");
+    checkUpperBound(
+        type1: "Iterable<A>", type2: "List<B>?", upperBound: "Iterable<A>?");
+
+    // UP(T1, T2) = T1 if T2 <: T1
+    //   Note that both types must be class types at this point
+    checkUpperBound(
+        type1: "Iterable<A?>", type2: "List<B>", upperBound: "Iterable<A?>");
+    checkUpperBound(
+        type1: "Iterable<A?>", type2: "List<B?>", upperBound: "Iterable<A?>");
+    checkUpperBound(
+        type1: "Iterable<A>?", type2: "List<B>", upperBound: "Iterable<A>?");
+    checkUpperBound(
+        type1: "Iterable<A>?", type2: "List<B>?", upperBound: "Iterable<A>?");
   }
 
   void test_upper_bound_top() {
@@ -1133,7 +933,7 @@
 
     // UP(T1, T2) = T1 if TOP(T1)
     for (String t1 in topPredicateEnumeration.keys) {
-      for (String t2 in ["A*", "A?", "A"]) {
+      for (String t2 in ["A", "A?"]) {
         checkUpperBound(
             type1: t1,
             type2: t2,
@@ -1143,7 +943,7 @@
     }
 
     // UP(T1, T2) = T2 if TOP(T2)
-    for (String t1 in ["A*", "A?", "A"]) {
+    for (String t1 in ["A", "A?"]) {
       for (String t2 in topPredicateEnumeration.keys) {
         checkUpperBound(
             type1: t1,
@@ -1180,11 +980,6 @@
     for (String t1 in objectPredicateEnumeration.keys) {
       checkUpperBound(
           type1: t1,
-          type2: "A*",
-          upperBound: "${t1}?",
-          typeParameters: objectPredicateEnumeration[t1]);
-      checkUpperBound(
-          type1: t1,
           type2: "A?",
           upperBound: "${t1}?",
           typeParameters: objectPredicateEnumeration[t1]);
@@ -1195,7 +990,6 @@
     //   T2 if T1 is non-nullable
     //   T2? otherwise
     for (String t2 in objectPredicateEnumeration.keys) {
-      checkUpperBound(type1: "A*", type2: t2, upperBound: "${t2}?");
       checkUpperBound(type1: "A?", type2: t2, upperBound: "${t2}?");
       checkUpperBound(type1: "A", type2: t2, upperBound: t2);
     }
@@ -1227,7 +1021,7 @@
 
     // UP(T1, T2) = T2 if BOTTOM(T1)
     for (String t1 in bottomPredicateEnumeration.keys) {
-      for (String t2 in ["A*", "A?", "A"]) {
+      for (String t2 in ["A", "A?"]) {
         checkUpperBound(
             type1: t1,
             type2: t2,
@@ -1237,7 +1031,7 @@
     }
 
     // UP(T1, T2) = T1 if BOTTOM(T2)
-    for (String t1 in ["A*", "A?", "A"]) {
+    for (String t1 in ["A", "A?"]) {
       for (String t2 in bottomPredicateEnumeration.keys) {
         checkUpperBound(
             type1: t1,
@@ -1274,7 +1068,7 @@
     for (String t1 in nullPredicateEnumeration.keys) {
       checkUpperBound(
           type1: t1,
-          type2: "A*",
+          type2: "A",
           upperBound: "A?",
           typeParameters: nullPredicateEnumeration[t1]);
       checkUpperBound(
@@ -1282,11 +1076,6 @@
           type2: "A?",
           upperBound: "A?",
           typeParameters: nullPredicateEnumeration[t1]);
-      checkUpperBound(
-          type1: t1,
-          type2: "A",
-          upperBound: "A?",
-          typeParameters: nullPredicateEnumeration[t1]);
     }
 
     // UP(T1, T2) where NULL(T2) =
@@ -1294,7 +1083,7 @@
     //   T1? otherwise
     for (String t2 in nullPredicateEnumeration.keys) {
       checkUpperBound(
-          type1: "A*",
+          type1: "A",
           type2: t2,
           upperBound: "A?",
           typeParameters: nullPredicateEnumeration[t2]);
@@ -1303,11 +1092,6 @@
           type2: t2,
           upperBound: "A?",
           typeParameters: nullPredicateEnumeration[t2]);
-      checkUpperBound(
-          type1: "A",
-          type2: t2,
-          upperBound: "A?",
-          typeParameters: nullPredicateEnumeration[t2]);
     }
   }
 
@@ -1400,13 +1184,11 @@
   void test_upper_bound_unknown() {
     parseTestLibrary("class A;");
 
-    checkLowerBound(type1: "A*", type2: "UNKNOWN", lowerBound: "A*");
-    checkLowerBound(type1: "A?", type2: "UNKNOWN", lowerBound: "A?");
     checkLowerBound(type1: "A", type2: "UNKNOWN", lowerBound: "A");
+    checkLowerBound(type1: "A?", type2: "UNKNOWN", lowerBound: "A?");
 
-    checkLowerBound(type1: "UNKNOWN", type2: "A*", lowerBound: "A*");
-    checkLowerBound(type1: "UNKNOWN", type2: "A?", lowerBound: "A?");
     checkLowerBound(type1: "UNKNOWN", type2: "A", lowerBound: "A");
+    checkLowerBound(type1: "UNKNOWN", type2: "A?", lowerBound: "A?");
   }
 
   void test_solveTypeConstraint() {
@@ -1426,59 +1208,59 @@
     checkConstraintSolving("", "UNKNOWN", grounded: true);
 
     // Solve(A <: T <: ?) => A
-    checkConstraintSolving(":> A<dynamic>*", "A<dynamic>*", grounded: false);
+    checkConstraintSolving(":> A<dynamic>", "A<dynamic>", grounded: false);
 
     // Solve(A <: T <: ?, grounded) => A
-    checkConstraintSolving(":> A<dynamic>*", "A<dynamic>*", grounded: true);
+    checkConstraintSolving(":> A<dynamic>", "A<dynamic>", grounded: true);
 
-    // Solve(A<?>* <: T <: ?) => A<?>*
-    checkConstraintSolving(":> A<UNKNOWN>*", "A<UNKNOWN>*", grounded: false);
+    // Solve(A<?> <: T <: ?) => A<?>
+    checkConstraintSolving(":> A<UNKNOWN>", "A<UNKNOWN>", grounded: false);
 
-    // Solve(A<?>* <: T <: ?, grounded) => A<Never>*
-    checkConstraintSolving(":> A<UNKNOWN>*", "A<Never>*", grounded: true);
+    // Solve(A<?> <: T <: ?, grounded) => A<Never>
+    checkConstraintSolving(":> A<UNKNOWN>", "A<Never>", grounded: true);
 
-    // Solve(? <: T <: A*) => A*
-    checkConstraintSolving("<: A<dynamic>*", "A<dynamic>*", grounded: false);
+    // Solve(? <: T <: A) => A
+    checkConstraintSolving("<: A<dynamic>", "A<dynamic>", grounded: false);
 
-    // Solve(? <: T <: A*, grounded) => A*
-    checkConstraintSolving("<: A<dynamic>*", "A<dynamic>*", grounded: true);
+    // Solve(? <: T <: A, grounded) => A
+    checkConstraintSolving("<: A<dynamic>", "A<dynamic>", grounded: true);
 
-    // Solve(? <: T <: A<?>*) => A<?>*
-    checkConstraintSolving("<: A<UNKNOWN>*", "A<UNKNOWN>*", grounded: false);
+    // Solve(? <: T <: A<?>) => A<?>
+    checkConstraintSolving("<: A<UNKNOWN>", "A<UNKNOWN>", grounded: false);
 
-    // Solve(? <: T <: A<?>*, grounded) => A<dynamic>*
-    checkConstraintSolving("<: A<UNKNOWN>*", "A<Object?>*", grounded: true);
+    // Solve(? <: T <: A<?>, grounded) => A<dynamic>
+    checkConstraintSolving("<: A<UNKNOWN>", "A<Object?>", grounded: true);
 
-    // Solve(B* <: T <: A*) => B*
-    checkConstraintSolving(":> B<dynamic>* <: A<dynamic>*", "B<dynamic>*",
+    // Solve(B <: T <: A) => B
+    checkConstraintSolving(":> B<dynamic> <: A<dynamic>", "B<dynamic>",
         grounded: false);
 
-    // Solve(B* <: T <: A*, grounded) => B*
-    checkConstraintSolving(":> B<dynamic>* <: A<dynamic>*", "B<dynamic>*",
+    // Solve(B <: T <: A, grounded) => B
+    checkConstraintSolving(":> B<dynamic> <: A<dynamic>", "B<dynamic>",
         grounded: true);
 
-    // Solve(B<?>* <: T <: A*) => A*
-    checkConstraintSolving(":> B<UNKNOWN>* <: A<dynamic>*", "A<dynamic>*",
+    // Solve(B<?> <: T <: A) => A
+    checkConstraintSolving(":> B<UNKNOWN> <: A<dynamic>", "A<dynamic>",
         grounded: false);
 
-    // Solve(B<?>* <: T <: A*, grounded) => A*
-    checkConstraintSolving(":> B<UNKNOWN>* <: A<dynamic>*", "A<dynamic>*",
+    // Solve(B<?> <: T <: A, grounded) => A
+    checkConstraintSolving(":> B<UNKNOWN> <: A<dynamic>", "A<dynamic>",
         grounded: true);
 
-    // Solve(B* <: T <: A<?>*) => B*
-    checkConstraintSolving(":> B<dynamic>* <: A<UNKNOWN>*", "B<dynamic>*",
+    // Solve(B <: T <: A<?>) => B
+    checkConstraintSolving(":> B<dynamic> <: A<UNKNOWN>", "B<dynamic>",
         grounded: false);
 
-    // Solve(B* <: T <: A<?>*, grounded) => B*
-    checkConstraintSolving(":> B<dynamic>* <: A<UNKNOWN>*", "B<dynamic>*",
+    // Solve(B <: T <: A<?>, grounded) => B
+    checkConstraintSolving(":> B<dynamic> <: A<UNKNOWN>", "B<dynamic>",
         grounded: true);
 
-    // Solve(B<?>* <: T <: A<?>*) => B<?>*
-    checkConstraintSolving(":> B<UNKNOWN>* <: A<UNKNOWN>*", "B<UNKNOWN>*",
+    // Solve(B<?> <: T <: A<?>) => B<?>
+    checkConstraintSolving(":> B<UNKNOWN> <: A<UNKNOWN>", "B<UNKNOWN>",
         grounded: false);
 
-    // Solve(B<?>* <: T <: A<?>*, grounded) => B<Never>*
-    checkConstraintSolving(":> B<UNKNOWN>* <: A<UNKNOWN>*", "B<Never>*",
+    // Solve(B<?> <: T <: A<?>, grounded) => B<Never>
+    checkConstraintSolving(":> B<UNKNOWN> <: A<UNKNOWN>", "B<Never>",
         grounded: true);
   }
 
@@ -1497,18 +1279,18 @@
       class E extends D;
     """);
 
-    checkTypeDoesntSatisfyConstraint("A*", ":> D* <: B*");
-    checkTypeSatisfiesConstraint("B*", ":> D* <: B*");
-    checkTypeSatisfiesConstraint("C*", ":> D* <: B*");
-    checkTypeSatisfiesConstraint("D*", ":> D* <: B*");
-    checkTypeDoesntSatisfyConstraint("E*", ":> D* <: B*");
+    checkTypeDoesntSatisfyConstraint("A", ":> D <: B");
+    checkTypeSatisfiesConstraint("B", ":> D <: B");
+    checkTypeSatisfiesConstraint("C", ":> D <: B");
+    checkTypeSatisfiesConstraint("D", ":> D <: B");
+    checkTypeDoesntSatisfyConstraint("E", ":> D <: B");
   }
 
   void test_unknown_at_bottom() {
     parseTestLibrary("class A;");
 
     // TODO(cstefantsova): Test for various nullabilities.
-    checkIsSubtype("UNKNOWN", "A*");
+    checkIsSubtype("UNKNOWN", "A");
   }
 
   void test_unknown_at_top() {
@@ -1517,8 +1299,8 @@
       class Pair<X, Y>;
     """);
 
-    checkIsSubtype("A*", "UNKNOWN");
-    checkIsSubtype("Pair<A*, Null>*", "Pair<UNKNOWN, UNKNOWN>*");
+    checkIsSubtype("A", "UNKNOWN");
+    checkIsSubtype("Pair<A, Null>", "Pair<UNKNOWN, UNKNOWN>");
   }
 
   void test_upper_bound_extension_type() {
diff --git a/pkg/front_end/test/type_inference/type_schema_environment_test.dart b/pkg/front_end/test/type_inference/type_schema_environment_test.dart
index e7170be..31f97af 100644
--- a/pkg/front_end/test/type_inference/type_schema_environment_test.dart
+++ b/pkg/front_end/test/type_inference/type_schema_environment_test.dart
@@ -20,129 +20,120 @@
   void test_addLowerBound() {
     parseTestLibrary("class A; class B extends A; class C extends A;");
     checkConstraintLowerBound(constraint: "", bound: "UNKNOWN");
-    checkConstraintLowerBound(constraint: ":> B*", bound: "B*");
-    checkConstraintLowerBound(constraint: ":> B* :> C*", bound: "A*");
+    checkConstraintLowerBound(constraint: ":> B", bound: "B");
+    checkConstraintLowerBound(constraint: ":> B :> C", bound: "A");
   }
 
   void test_addUpperBound() {
     parseTestLibrary("class A; class B extends A; class C extends A;");
     checkConstraintUpperBound(constraint: "", bound: "UNKNOWN");
-    checkConstraintUpperBound(constraint: "<: A*", bound: "A*");
-    checkConstraintUpperBound(constraint: "<: A* <: B*", bound: "B*");
-    checkConstraintUpperBound(constraint: "<: A* <: B* <: C*", bound: "Never*");
+    checkConstraintUpperBound(constraint: "<: A", bound: "A");
+    checkConstraintUpperBound(constraint: "<: A <: B", bound: "B");
+    checkConstraintUpperBound(constraint: "<: A <: B <: C", bound: "Never");
   }
 
   void test_glb_bottom() {
     parseTestLibrary("class A;");
-    checkLowerBound(type1: "Null", type2: "A*", lowerBound: "Null");
-    checkLowerBound(type1: "A*", type2: "Null", lowerBound: "Null");
+    checkLowerBound(type1: "Null", type2: "A", lowerBound: "Never");
+    checkLowerBound(type1: "A", type2: "Null", lowerBound: "Never");
   }
 
   void test_glb_function() {
     parseTestLibrary("class A; class B extends A;");
 
     // GLB(() -> A, () -> B) = () -> B
-    checkLowerBound(
-        type1: "() ->* A*", type2: "() ->* B*", lowerBound: "() ->* B*");
+    checkLowerBound(type1: "() -> A", type2: "() -> B", lowerBound: "() -> B");
 
     // GLB(() -> void, (A, B) -> void) = ([A, B]) -> void
     checkLowerBound(
-        type1: "() ->* void",
-        type2: "(A*, B*) ->* void",
-        lowerBound: "([A*, B*]) ->* void");
+        type1: "() -> void",
+        type2: "(A, B) -> void",
+        lowerBound: "([A, B]) -> void");
     checkLowerBound(
-        type1: "(A*, B*) ->* void",
-        type2: "() ->* void",
-        lowerBound: "([A*, B*]) ->* void");
+        type1: "(A, B) -> void",
+        type2: "() -> void",
+        lowerBound: "([A, B]) -> void");
 
     // GLB((A) -> void, (B) -> void) = (A) -> void
     checkLowerBound(
-        type1: "(A*) ->* void",
-        type2: "(B*) ->* void",
-        lowerBound: "(A*) ->* void");
+        type1: "(A) -> void", type2: "(B) -> void", lowerBound: "(A) -> void");
     checkLowerBound(
-        type1: "(B*) ->* void",
-        type2: "(A*) ->* void",
-        lowerBound: "(A*) ->* void");
+        type1: "(B) -> void", type2: "(A) -> void", lowerBound: "(A) -> void");
 
     // GLB(({a: A}) -> void, ({b: B}) -> void) = ({a: A, b: B}) -> void
     checkLowerBound(
-        type1: "({A* a}) ->* void",
-        type2: "({B* b}) ->* void",
-        lowerBound: "({A* a, B* b}) ->* void");
+        type1: "({A a}) -> void",
+        type2: "({B b}) -> void",
+        lowerBound: "({A a, B b}) -> void");
     checkLowerBound(
-        type1: "({B* b}) ->* void",
-        type2: "({A* a}) ->* void",
-        lowerBound: "({A* a, B* b}) ->* void");
+        type1: "({B b}) -> void",
+        type2: "({A a}) -> void",
+        lowerBound: "({A a, B b}) -> void");
 
     // GLB(({a: A, c: A}) -> void, ({b: B, d: B}) -> void)
     //     = ({a: A, b: B, c: A, d: B}) -> void
     checkLowerBound(
-        type1: "({A* a, A* c}) ->* void",
-        type2: "({B* b, B* d}) ->* void",
-        lowerBound: "({A* a, B* b, A* c, B* d}) ->* void");
+        type1: "({A a, A c}) -> void",
+        type2: "({B b, B d}) -> void",
+        lowerBound: "({A a, B b, A c, B d}) -> void");
 
     // GLB(({a: A, b: B}) -> void, ({a: B, b: A}) -> void)
     //     = ({a: A, b: A}) -> void
     checkLowerBound(
-        type1: "({A* a, B* b}) ->* void",
-        type2: "({B* a, A* b}) ->* void",
-        lowerBound: "({A* a, A* b}) ->* void");
+        type1: "({A a, B b}) -> void",
+        type2: "({B a, A b}) -> void",
+        lowerBound: "({A a, A b}) -> void");
     checkLowerBound(
-        type1: "({B* a, A* b}) ->* void",
-        type2: "({A* a, B* b}) ->* void",
-        lowerBound: "({A* a, A* b}) ->* void");
+        type1: "({B a, A b}) -> void",
+        type2: "({A a, B b}) -> void",
+        lowerBound: "({A a, A b}) -> void");
 
     // GLB((B, {a: A}) -> void, (B) -> void) = (B, {a: A}) -> void
     checkLowerBound(
-        type1: "(B*, {A* a}) ->* void",
-        type2: "(B*) ->* void",
-        lowerBound: "(B*, {A* a}) ->* void");
+        type1: "(B, {A a}) -> void",
+        type2: "(B) -> void",
+        lowerBound: "(B, {A a}) -> void");
 
     // GLB(({a: A}) -> void, (B) -> void) = bottom
     checkLowerBound(
-        type1: "({A* a}) ->* void",
-        type2: "(B*) ->* void",
-        lowerBound: "Never*");
+        type1: "({A a}) -> void", type2: "(B) -> void", lowerBound: "Never");
 
     // GLB(({a: A}) -> void, ([B]) -> void) = bottom
     checkLowerBound(
-        type1: "({A* a}) ->* void",
-        type2: "([B*]) ->* void",
-        lowerBound: "Never*");
+        type1: "({A a}) -> void", type2: "([B]) -> void", lowerBound: "Never");
   }
 
   void test_glb_identical() {
     parseTestLibrary("class A;");
-    checkLowerBound(type1: "A*", type2: "A*", lowerBound: "A*");
+    checkLowerBound(type1: "A", type2: "A", lowerBound: "A");
   }
 
   void test_glb_subtype() {
     parseTestLibrary("class A; class B extends A;");
 
-    checkLowerBound(type1: "A*", type2: "B*", lowerBound: "B*");
-    checkLowerBound(type1: "B*", type2: "A*", lowerBound: "B*");
+    checkLowerBound(type1: "A", type2: "B", lowerBound: "B");
+    checkLowerBound(type1: "B", type2: "A", lowerBound: "B");
   }
 
   void test_glb_top() {
     parseTestLibrary("class A;");
-    checkLowerBound(type1: "dynamic", type2: "A*", lowerBound: "A*");
-    checkLowerBound(type1: "A*", type2: "dynamic", lowerBound: "A*");
-    checkLowerBound(type1: "Object*", type2: "A*", lowerBound: "A*");
-    checkLowerBound(type1: "A*", type2: "Object*", lowerBound: "A*");
-    checkLowerBound(type1: "void", type2: "A*", lowerBound: "A*");
-    checkLowerBound(type1: "A*", type2: "void", lowerBound: "A*");
+    checkLowerBound(type1: "dynamic", type2: "A", lowerBound: "A");
+    checkLowerBound(type1: "A", type2: "dynamic", lowerBound: "A");
+    checkLowerBound(type1: "Object", type2: "A", lowerBound: "A");
+    checkLowerBound(type1: "A", type2: "Object", lowerBound: "A");
+    checkLowerBound(type1: "void", type2: "A", lowerBound: "A");
+    checkLowerBound(type1: "A", type2: "void", lowerBound: "A");
   }
 
   void test_glb_unknown() {
     parseTestLibrary("class A;");
-    checkLowerBound(type1: "A*", type2: "UNKNOWN", lowerBound: "A*");
-    checkLowerBound(type1: "UNKNOWN", type2: "A*", lowerBound: "A*");
+    checkLowerBound(type1: "A", type2: "UNKNOWN", lowerBound: "A");
+    checkLowerBound(type1: "UNKNOWN", type2: "A", lowerBound: "A");
   }
 
   void test_glb_unrelated() {
     parseTestLibrary("class A; class B;");
-    checkLowerBound(type1: "A*", type2: "B*", lowerBound: "Never*");
+    checkLowerBound(type1: "A", type2: "B", lowerBound: "Never");
   }
 
   void test_inferGenericFunctionOrType() {
@@ -151,16 +142,16 @@
     // Test an instantiation of [1, 2.0] with no context.  This should infer
     // as List<?> during downwards inference.
     checkInference(
-        typeParametersToInfer: "T extends Object*",
-        functionType: "() ->* List<T*>*",
+        typeParametersToInfer: "T extends Object",
+        functionType: "() -> List<T>",
         actualParameterTypes: null,
         returnContextType: null,
         expectedTypes: "UNKNOWN");
     // And upwards inference should refine it to List<num>.
     checkInference(
-        typeParametersToInfer: "T extends Object*",
-        functionType: "(T*, T*) ->* List<T*>*",
-        actualParameterTypes: "int*, double*",
+        typeParametersToInfer: "T extends Object",
+        functionType: "(T, T) -> List<T>",
+        actualParameterTypes: "int, double",
         returnContextType: null,
         inferredTypesFromDownwardPhase: "UNKNOWN",
         expectedTypes: "num");
@@ -168,18 +159,18 @@
     // Test an instantiation of [1, 2.0] with a context of List<Object>.  This
     // should infer as List<Object> during downwards inference.
     checkInference(
-        typeParametersToInfer: "T extends Object*",
-        functionType: "() ->* List<T*>*",
+        typeParametersToInfer: "T extends Object",
+        functionType: "() -> List<T>",
         actualParameterTypes: null,
-        returnContextType: "List<Object*>*",
+        returnContextType: "List<Object>",
         expectedTypes: "Object");
     // And upwards inference should preserve the type.
     checkInference(
-        typeParametersToInfer: "T extends Object*",
-        functionType: "(T*, T*) ->* List<T>",
-        actualParameterTypes: "int*, double*",
-        returnContextType: "List<Object*>*",
-        inferredTypesFromDownwardPhase: "Object*",
+        typeParametersToInfer: "T extends Object",
+        functionType: "(T, T) -> List<T>",
+        actualParameterTypes: "int, double",
+        returnContextType: "List<Object>",
+        inferredTypesFromDownwardPhase: "Object",
         expectedTypes: "Object");
   }
 
@@ -189,40 +180,40 @@
     // With no constraints:
     // Downward inference should infer '?'
     checkInferenceFromConstraints(
-        typeParameter: "T extends num*",
+        typeParameter: "T extends num",
         constraints: "",
         downwardsInferPhase: true,
         expected: "UNKNOWN");
     // Upward inference should infer num
     checkInferenceFromConstraints(
-        typeParameter: "T extends num*",
+        typeParameter: "T extends num",
         constraints: "",
         downwardsInferPhase: false,
         inferredTypeFromDownwardPhase: "UNKNOWN",
-        expected: "num*");
+        expected: "num");
 
     // With an upper bound of Object:
     // Downward inference should infer num.
     checkInferenceFromConstraints(
-        typeParameter: "T extends num*",
-        constraints: "<: Object*",
+        typeParameter: "T extends num",
+        constraints: "<: Object",
         downwardsInferPhase: true,
-        expected: "num*");
+        expected: "num");
     // Upward inference should infer num.
     checkInferenceFromConstraints(
-        typeParameter: "T extends num*",
-        constraints: "<: Object*",
+        typeParameter: "T extends num",
+        constraints: "<: Object",
         downwardsInferPhase: false,
-        inferredTypeFromDownwardPhase: "num*",
-        expected: "num*");
+        inferredTypeFromDownwardPhase: "num",
+        expected: "num");
     // Upward inference should still infer num even if there are more
     // constraints now, because num was finalized during downward inference.
     checkInferenceFromConstraints(
-        typeParameter: "T extends num*",
-        constraints: ":> int* <: int*",
+        typeParameter: "T extends num",
+        constraints: ":> int <: int",
         downwardsInferPhase: false,
-        inferredTypeFromDownwardPhase: "num*",
-        expected: "num*");
+        inferredTypeFromDownwardPhase: "num",
+        expected: "num");
   }
 
   void test_inferTypeFromConstraints_simple() {
@@ -231,17 +222,17 @@
     // With an upper bound of List<?>:
     // Downwards inference should infer List<List<?>>
     checkInferenceFromConstraints(
-        typeParameter: "T extends Object*",
-        constraints: "<: List<UNKNOWN>*",
+        typeParameter: "T extends Object",
+        constraints: "<: List<UNKNOWN>",
         downwardsInferPhase: true,
-        expected: "List<UNKNOWN>*");
+        expected: "List<UNKNOWN>");
     // Upwards inference should refine that to List<List<Object?>>
     checkInferenceFromConstraints(
-        typeParameter: "T extends Object*",
-        constraints: "<: List<UNKNOWN>*",
+        typeParameter: "T extends Object",
+        constraints: "<: List<UNKNOWN>",
         downwardsInferPhase: false,
-        inferredTypeFromDownwardPhase: "List<UNKNOWN>*",
-        expected: "List<Object?>*");
+        inferredTypeFromDownwardPhase: "List<UNKNOWN>",
+        expected: "List<Object?>");
   }
 
   void test_lub_classic() {
@@ -262,136 +253,119 @@
       class E implements B, C;
     """);
 
-    checkUpperBound(type1: "D*", type2: "E*", upperBound: "A*");
+    checkUpperBound(type1: "D", type2: "E", upperBound: "A");
   }
 
   void test_lub_commonClass() {
     parseTestLibrary("");
     checkUpperBound(
-        type1: "List<int*>*",
-        type2: "List<double*>*",
-        upperBound: "List<num*>*");
+        type1: "List<int>", type2: "List<double>", upperBound: "List<num>");
   }
 
   void test_lub_function() {
     parseTestLibrary("class A; class B extends A;");
 
     // LUB(() -> A, () -> B) = () -> A
-    checkUpperBound(
-        type1: "() ->* A*", type2: "() ->* B*", upperBound: "() ->* A*");
+    checkUpperBound(type1: "() -> A", type2: "() -> B", upperBound: "() -> A");
 
     // LUB(([A]) -> void, (A) -> void) = Function
     checkUpperBound(
-        type1: "([A*]) ->* void",
-        type2: "(A*) ->* void",
-        upperBound: "Function*");
+        type1: "([A]) -> void", type2: "(A) -> void", upperBound: "Function");
 
     // LUB(() -> void, (A, B) -> void) = Function
     checkUpperBound(
-        type1: "() ->* void",
-        type2: "(A*, B*) ->* void",
-        upperBound: "Function*");
+        type1: "() -> void", type2: "(A, B) -> void", upperBound: "Function");
     checkUpperBound(
-        type1: "(A*, B*) ->* void",
-        type2: "() ->* void",
-        upperBound: "Function*");
+        type1: "(A, B) -> void", type2: "() -> void", upperBound: "Function");
 
     // LUB((A) -> void, (B) -> void) = (B) -> void
     checkUpperBound(
-        type1: "(A*) ->* void",
-        type2: "(B*) ->* void",
-        upperBound: "(B*) ->* void");
+        type1: "(A) -> void", type2: "(B) -> void", upperBound: "(B) -> void");
     checkUpperBound(
-        type1: "(B*) ->* void",
-        type2: "(A*) ->* void",
-        upperBound: "(B*) ->* void");
+        type1: "(B) -> void", type2: "(A) -> void", upperBound: "(B) -> void");
 
     // LUB(({a: A}) -> void, ({b: B}) -> void) = () -> void
     checkUpperBound(
-        type1: "({A* a}) ->* void",
-        type2: "({B* b}) ->* void",
-        upperBound: "() ->* void");
+        type1: "({A a}) -> void",
+        type2: "({B b}) -> void",
+        upperBound: "() -> void");
     checkUpperBound(
-        type1: "({B* b}) ->* void",
-        type2: "({A* a}) ->* void",
-        upperBound: "() ->* void");
+        type1: "({B b}) -> void",
+        type2: "({A a}) -> void",
+        upperBound: "() -> void");
 
     // LUB(({a: A, c: A}) -> void, ({b: B, d: B}) -> void) = () -> void
     checkUpperBound(
-        type1: "({A* a, A* c}) ->* void",
-        type2: "({B* b, B* d}) ->* void",
-        upperBound: "() ->* void");
+        type1: "({A a, A c}) -> void",
+        type2: "({B b, B d}) -> void",
+        upperBound: "() -> void");
 
     // LUB(({a: A, b: B}) -> void, ({a: B, b: A}) -> void)
     //     = ({a: B, b: B}) -> void
     checkUpperBound(
-        type1: "({A* a, B* b}) ->* void",
-        type2: "({B* a, A* b}) ->* void",
-        upperBound: "({B* a, B* b}) ->* void");
+        type1: "({A a, B b}) -> void",
+        type2: "({B a, A b}) -> void",
+        upperBound: "({B a, B b}) -> void");
     checkUpperBound(
-        type1: "({B* a, A* b}) ->* void",
-        type2: "({A* a, B* b}) ->* void",
-        upperBound: "({B* a, B* b}) ->* void");
+        type1: "({B a, A b}) -> void",
+        type2: "({A a, B b}) -> void",
+        upperBound: "({B a, B b}) -> void");
 
     // LUB((B, {a: A}) -> void, (B) -> void) = (B) -> void
     checkUpperBound(
-        type1: "(B*, {A* a}) ->* void",
-        type2: "(B*) ->* void",
-        upperBound: "(B*) ->* void");
+        type1: "(B, {A a}) -> void",
+        type2: "(B) -> void",
+        upperBound: "(B) -> void");
 
     // LUB(({a: A}) -> void, (B) -> void) = Function
     checkUpperBound(
-        type1: "({A* a}) ->* void",
-        type2: "(B*) ->* void",
-        upperBound: "Function*");
+        type1: "({A a}) -> void", type2: "(B) -> void", upperBound: "Function");
 
     // GLB(({a: A}) -> void, ([B]) -> void) = Function
     checkUpperBound(
-        type1: "({A* a}) ->* void",
-        type2: "([B*]) ->* void",
-        upperBound: "Function*");
+        type1: "({A a}) -> void",
+        type2: "([B]) -> void",
+        upperBound: "Function");
   }
 
   void test_lub_identical() {
     parseTestLibrary("class A;");
-    checkUpperBound(type1: "A*", type2: "A*", upperBound: "A*");
+    checkUpperBound(type1: "A", type2: "A", upperBound: "A");
   }
 
   void test_lub_sameClass() {
     parseTestLibrary("class A; class B extends A; class Map<X, Y>;");
     checkUpperBound(
-        type1: "Map<A*, B*>*",
-        type2: "Map<B*, A*>*",
-        upperBound: "Map<A*, A*>*");
+        type1: "Map<A, B>", type2: "Map<B, A>", upperBound: "Map<A, A>");
   }
 
   void test_lub_subtype() {
     parseTestLibrary("");
     checkUpperBound(
-        type1: "List<int*>*",
-        type2: "Iterable<num*>*",
-        upperBound: "Iterable<num*>*");
+        type1: "List<int>",
+        type2: "Iterable<num>",
+        upperBound: "Iterable<num>");
     checkUpperBound(
-        type1: "Iterable<num*>*",
-        type2: "List<int*>*",
-        upperBound: "Iterable<num*>*");
+        type1: "Iterable<num>",
+        type2: "List<int>",
+        upperBound: "Iterable<num>");
   }
 
   void test_lub_top() {
     parseTestLibrary("class A;");
 
-    checkUpperBound(type1: "dynamic", type2: "A*", upperBound: "dynamic");
-    checkUpperBound(type1: "A*", type2: "dynamic", upperBound: "dynamic");
-    checkUpperBound(type1: "Object*", type2: "A*", upperBound: "Object*");
-    checkUpperBound(type1: "A*", type2: "Object*", upperBound: "Object*");
-    checkUpperBound(type1: "void", type2: "A*", upperBound: "void");
-    checkUpperBound(type1: "A*", type2: "void", upperBound: "void");
-    checkUpperBound(type1: "dynamic", type2: "Object*", upperBound: "dynamic");
-    checkUpperBound(type1: "Object*", type2: "dynamic", upperBound: "dynamic");
+    checkUpperBound(type1: "dynamic", type2: "A", upperBound: "dynamic");
+    checkUpperBound(type1: "A", type2: "dynamic", upperBound: "dynamic");
+    checkUpperBound(type1: "Object", type2: "A", upperBound: "Object");
+    checkUpperBound(type1: "A", type2: "Object", upperBound: "Object");
+    checkUpperBound(type1: "void", type2: "A", upperBound: "void");
+    checkUpperBound(type1: "A", type2: "void", upperBound: "void");
+    checkUpperBound(type1: "dynamic", type2: "Object", upperBound: "dynamic");
+    checkUpperBound(type1: "Object", type2: "dynamic", upperBound: "dynamic");
     checkUpperBound(type1: "dynamic", type2: "void", upperBound: "void");
     checkUpperBound(type1: "void", type2: "dynamic", upperBound: "void");
-    checkUpperBound(type1: "Object*", type2: "void", upperBound: "void");
-    checkUpperBound(type1: "void", type2: "Object*", upperBound: "void");
+    checkUpperBound(type1: "Object", type2: "void", upperBound: "void");
+    checkUpperBound(type1: "void", type2: "Object", upperBound: "void");
   }
 
   void test_lub_typeParameter() {
@@ -399,41 +373,41 @@
 
     // LUB(T, T) = T
     checkUpperBound(
-        type1: "T*",
-        type2: "T*",
-        upperBound: "T*",
-        typeParameters: "T extends List<T*>*");
+        type1: "T",
+        type2: "T",
+        upperBound: "T",
+        typeParameters: "T extends List<T>");
 
     // LUB(T, List<Bottom>) = LUB(List<Object>, List<Bottom>) = List<Object?>
     checkUpperBound(
-        type1: "T*",
-        type2: "List<Null>*",
-        upperBound: "List<Object?>*",
-        typeParameters: "T extends List<T*>*");
+        type1: "T",
+        type2: "List<Null>",
+        upperBound: "List<Object?>",
+        typeParameters: "T extends List<T>");
     checkUpperBound(
-        type1: "List<Null>*",
-        type2: "T*",
-        upperBound: "List<Object?>*",
-        typeParameters: "T extends List<T*>*");
+        type1: "List<Null>",
+        type2: "T",
+        upperBound: "List<Object?>",
+        typeParameters: "T extends List<T>");
 
     // LUB(T, U) = LUB(List<Object>, U) = LUB(List<Object?>, List<Bottom>)
     // = List<Object>
     checkUpperBound(
-        type1: "T*",
-        type2: "U*",
-        upperBound: "List<Object?>*",
-        typeParameters: "T extends List<T*>*, U extends List<Null>*");
+        type1: "T",
+        type2: "U",
+        upperBound: "List<Object?>",
+        typeParameters: "T extends List<T>, U extends List<Null>");
     checkUpperBound(
-        type1: "U*",
-        type2: "T*",
-        upperBound: "List<Object?>*",
-        typeParameters: "T extends List<T*>*, U extends List<Null>*");
+        type1: "U",
+        type2: "T",
+        upperBound: "List<Object?>",
+        typeParameters: "T extends List<T>, U extends List<Null>");
   }
 
   void test_lub_unknown() {
     parseTestLibrary("class A;");
-    checkUpperBound(type1: "A*", type2: "UNKNOWN", upperBound: "A*");
-    checkUpperBound(type1: "UNKNOWN", type2: "A*", upperBound: "A*");
+    checkUpperBound(type1: "A", type2: "UNKNOWN", upperBound: "A");
+    checkUpperBound(type1: "UNKNOWN", type2: "A", upperBound: "A");
   }
 
   void test_solveTypeConstraint() {
@@ -441,8 +415,8 @@
       class A;
       class B extends A;
 
-      class C<T extends Object*>;
-      class D<T extends Object*> extends C<T*>;
+      class C<T extends Object>;
+      class D<T extends Object> extends C<T>;
     """);
 
     // Solve(? <: T <: ?) => ?
@@ -454,57 +428,57 @@
     checkConstraintSolving("", "UNKNOWN", grounded: true);
 
     // Solve(A <: T <: ?) => A
-    checkConstraintSolving(":> A*", "A*", grounded: false);
+    checkConstraintSolving(":> A", "A", grounded: false);
 
     // Solve(A <: T <: ?, grounded) => A
-    checkConstraintSolving(":> A*", "A*", grounded: true);
+    checkConstraintSolving(":> A", "A", grounded: true);
 
     // Solve(A<?> <: T <: ?) => A<?>
-    checkConstraintSolving(":> C<UNKNOWN>*", "C<UNKNOWN>*", grounded: false);
+    checkConstraintSolving(":> C<UNKNOWN>", "C<UNKNOWN>", grounded: false);
 
     // Solve(A<?> <: T <: ?, grounded) => A<Never>
-    checkConstraintSolving(":> C<UNKNOWN>*", "C<Never>*", grounded: true);
+    checkConstraintSolving(":> C<UNKNOWN>", "C<Never>", grounded: true);
 
     // Solve(? <: T <: A) => A
-    checkConstraintSolving("<: A*", "A*", grounded: false);
+    checkConstraintSolving("<: A", "A", grounded: false);
 
     // Solve(? <: T <: A, grounded) => A
-    checkConstraintSolving("<: A*", "A*", grounded: true);
+    checkConstraintSolving("<: A", "A", grounded: true);
 
     // Solve(? <: T <: A<?>) => A<?>
-    checkConstraintSolving("<: C<UNKNOWN>*", "C<UNKNOWN>*", grounded: false);
+    checkConstraintSolving("<: C<UNKNOWN>", "C<UNKNOWN>", grounded: false);
 
     // Solve(? <: T <: A<?>, grounded) => A<Object?>
-    checkConstraintSolving("<: C<UNKNOWN>*", "C<Object?>*", grounded: true);
+    checkConstraintSolving("<: C<UNKNOWN>", "C<Object?>", grounded: true);
 
     // Solve(B <: T <: A) => B
-    checkConstraintSolving(":> B* <: A*", "B*", grounded: false);
+    checkConstraintSolving(":> B <: A", "B", grounded: false);
 
     // Solve(B <: T <: A, grounded) => B
-    checkConstraintSolving(":> B* <: A*", "B*", grounded: true);
+    checkConstraintSolving(":> B <: A", "B", grounded: true);
 
     // Solve(B<?> <: T <: A) => A
-    checkConstraintSolving(":> D<UNKNOWN>* <: C<dynamic>*", "C<dynamic>*",
+    checkConstraintSolving(":> D<UNKNOWN> <: C<dynamic>", "C<dynamic>",
         grounded: false);
 
     // Solve(B<?> <: T <: A, grounded) => A
-    checkConstraintSolving(":> D<UNKNOWN>* <: C<dynamic>*", "C<dynamic>*",
+    checkConstraintSolving(":> D<UNKNOWN> <: C<dynamic>", "C<dynamic>",
         grounded: true);
 
     // Solve(B <: T <: A<?>) => B
-    checkConstraintSolving(":> D<Null>* <: C<UNKNOWN>*", "D<Null>*",
+    checkConstraintSolving(":> D<Null> <: C<UNKNOWN>", "D<Null>",
         grounded: false);
 
     // Solve(B <: T <: A<?>, grounded) => B
-    checkConstraintSolving(":> D<Null>* <: C<UNKNOWN>*", "D<Null>*",
+    checkConstraintSolving(":> D<Null> <: C<UNKNOWN>", "D<Null>",
         grounded: true);
 
     // Solve(B<?> <: T <: A<?>) => B<?>
-    checkConstraintSolving(":> D<UNKNOWN>* <: C<UNKNOWN>*", "D<UNKNOWN>*",
+    checkConstraintSolving(":> D<UNKNOWN> <: C<UNKNOWN>", "D<UNKNOWN>",
         grounded: false);
 
     // Solve(B<?> <: T <: A<?>) => B<Never>
-    checkConstraintSolving(":> D<UNKNOWN>* <: C<UNKNOWN>*", "D<Never>*",
+    checkConstraintSolving(":> D<UNKNOWN> <: C<UNKNOWN>", "D<Never>",
         grounded: true);
   }
 
@@ -523,22 +497,22 @@
       class E extends D;
     """);
 
-    checkTypeDoesntSatisfyConstraint("A*", ":> D* <: B*");
-    checkTypeSatisfiesConstraint("B*", ":> D* <: B*");
-    checkTypeSatisfiesConstraint("C*", ":> D* <: B*");
-    checkTypeSatisfiesConstraint("D*", ":> D* <: B*");
-    checkTypeDoesntSatisfyConstraint("E*", ":> D* <: B*");
+    checkTypeDoesntSatisfyConstraint("A", ":> D <: B");
+    checkTypeSatisfiesConstraint("B", ":> D <: B");
+    checkTypeSatisfiesConstraint("C", ":> D <: B");
+    checkTypeSatisfiesConstraint("D", ":> D <: B");
+    checkTypeDoesntSatisfyConstraint("E", ":> D <: B");
   }
 
   void test_unknown_at_bottom() {
     parseTestLibrary("class A;");
-    checkIsSubtype("UNKNOWN", "A*");
+    checkIsSubtype("UNKNOWN", "A");
   }
 
   void test_unknown_at_top() {
     parseTestLibrary("class A; class Map<X, Y>;");
-    checkIsSubtype("A*", "UNKNOWN");
-    checkIsSubtype("Map<A*, A*>*", "Map<UNKNOWN, UNKNOWN>*");
+    checkIsSubtype("A", "UNKNOWN");
+    checkIsSubtype("Map<A, A>", "Map<UNKNOWN, UNKNOWN>");
   }
 
   void checkUpperBound(
diff --git a/pkg/front_end/test/type_inference/type_schema_environment_test_base.dart b/pkg/front_end/test/type_inference/type_schema_environment_test_base.dart
index 34d0f5c..02154ce 100644
--- a/pkg/front_end/test/type_inference/type_schema_environment_test_base.dart
+++ b/pkg/front_end/test/type_inference/type_schema_environment_test_base.dart
@@ -99,8 +99,7 @@
   void checkIsSubtype(String subtype, String supertype) {
     expect(
         typeSchemaEnvironment
-            .performSubtypeCheck(
-                parseType(subtype), parseType(supertype))
+            .performSubtypeCheck(parseType(subtype), parseType(supertype))
             .isSuccess(),
         isTrue);
   }
@@ -108,8 +107,7 @@
   void checkIsNotSubtype(String subtype, String supertype) {
     expect(
         typeSchemaEnvironment
-            .performSubtypeCheck(
-                parseType(subtype), parseType(supertype))
+            .performSubtypeCheck(parseType(subtype), parseType(supertype))
             .isSuccess(),
         isFalse);
   }
diff --git a/pkg/front_end/test/types/hashcode_test.dart b/pkg/front_end/test/types/hashcode_test.dart
index ffb611b..f402a91 100644
--- a/pkg/front_end/test/types/hashcode_test.dart
+++ b/pkg/front_end/test/types/hashcode_test.dart
@@ -7,15 +7,19 @@
 
 FunctionType createVoidToR() {
   StructuralParameter R = StructuralParameter("R", const DynamicType());
-  return new FunctionType([],
-      new StructuralParameterType(R, Nullability.legacy), Nullability.legacy,
+  return new FunctionType(
+      [],
+      new StructuralParameterType(R, Nullability.undetermined),
+      Nullability.nonNullable,
       typeParameters: [R]);
 }
 
 FunctionType createTTo_VoidToR() {
   StructuralParameter T = new StructuralParameter("T", const DynamicType());
-  return new FunctionType([new StructuralParameterType(T, Nullability.legacy)],
-      createVoidToR(), Nullability.legacy,
+  return new FunctionType(
+      [new StructuralParameterType(T, Nullability.undetermined)],
+      createVoidToR(),
+      Nullability.nonNullable,
       typeParameters: [T]);
 }
 
@@ -40,9 +44,10 @@
   StructuralParameter R = new StructuralParameter("R", const DynamicType());
   return new FunctionType(
       [],
-      new FunctionType([], new StructuralParameterType(R, Nullability.legacy),
-          Nullability.legacy),
-      Nullability.legacy,
+      new FunctionType([],
+          new StructuralParameterType(R, Nullability.undetermined),
+          Nullability.nonNullable),
+      Nullability.nonNullable,
       typeParameters: [R]);
 }
 
diff --git a/pkg/front_end/test/types/shared_type_tests.dart b/pkg/front_end/test/types/shared_type_tests.dart
index 3b22c24..2cdbae2 100644
--- a/pkg/front_end/test/types/shared_type_tests.dart
+++ b/pkg/front_end/test/types/shared_type_tests.dart
@@ -43,111 +43,86 @@
 
   void run() {
     // Tests for subtypes and supertypes of num.
-    isSubtype('int*', 'num*');
-    isSubtype('int*', 'Comparable<num*>*');
-    isSubtype('int*', 'Comparable<Object*>*');
-    isSubtype('int*', 'Object*');
-    isSubtype('double*', 'num*');
+    isSubtype('int', 'num');
+    isSubtype('int', 'Comparable<num>');
+    isSubtype('int', 'Comparable<Object>');
+    isSubtype('int', 'Object');
+    isSubtype('double', 'num');
     isSubtype('num', 'Object');
-    isSubtype('num*', 'Object');
-    isSubtype('Null', 'num*');
+    isNotSubtype('Null', 'num');
     isSubtype('Null', 'num?');
     isSubtype('Never', 'num');
-    isSubtype('Never', 'num*');
     isSubtype('Never', 'num?');
 
-    isNotSubtype('int*', 'double*');
-    isNotSubtype('int*', 'Comparable<int*>*');
-    isNotSubtype('int*', 'Iterable<int*>*');
-    isNotSubtype('Comparable<int*>*', 'Iterable<int*>*');
+    isNotSubtype('int', 'double');
+    isNotSubtype('int', 'Comparable<int>');
+    isNotSubtype('int', 'Iterable<int>');
+    isNotSubtype('Comparable<int>', 'Iterable<int>');
     isNotSubtype('num?', 'Object');
-    isNotSubtype('Null', 'num');
     isNotSubtype('num', 'Never');
 
     // Tests for subtypes and supertypes of List.
-    isSubtype('List<int*>*', 'List<int*>*');
-    isSubtype('List<int*>*', 'Iterable<int*>*');
-    isSubtype('List<int*>*', 'List<num*>*');
-    isSubtype('List<int*>*', 'Iterable<num*>*');
-    isSubtype('List<int*>*', 'List<Object*>*');
-    isSubtype('List<int*>*', 'Iterable<Object*>*');
-    isSubtype('List<int*>*', 'Object*');
-    isSubtype('List<int*>*', 'List<Comparable<Object*>*>*');
-    isSubtype('List<int*>*', 'List<Comparable<num*>*>*');
-    isSubtype('List<int*>*', 'List<Comparable<Comparable<num*>*>*>*');
-    isSubtype('List<int*>', 'Object');
-    isSubtype('List<int*>*', 'Object');
-    isSubtype('Null', 'List<int*>*');
-    isSubtype('Null', 'List<int*>?');
-    isSubtype('Never', 'List<int*>');
-    isSubtype('Never', 'List<int*>*');
-    isSubtype('Never', 'List<int*>?');
-
     isSubtype('List<int>', 'List<int>');
-    isSubtype('List<int>', 'List<int>*');
+    isSubtype('List<int>', 'Iterable<int>');
+    isSubtype('List<int>', 'List<num>');
+    isSubtype('List<int>', 'Iterable<num>');
+    isSubtype('List<int>', 'List<Object>');
+    isSubtype('List<int>', 'Iterable<Object>');
+    isSubtype('List<int>', 'Object');
+    isSubtype('List<int>', 'List<Comparable<Object>>');
+    isSubtype('List<int>', 'List<Comparable<num>>');
+    isSubtype('List<int>', 'List<Comparable<Comparable<num>>>');
+    isNotSubtype('Null', 'List<int>');
+    isSubtype('Null', 'List<int>?');
+    isSubtype('Never', 'List<int>');
+    isSubtype('Never', 'List<int>?');
+
     isSubtype('List<int>', 'List<int>?');
-    isSubtype('List<int>*', 'List<int>');
-    isSubtype('List<int>*', 'List<int>*');
-    isSubtype('List<int>*', 'List<int>?');
     isNotSubtype('List<int>?', 'List<int>');
-    isSubtype('List<int>?', 'List<int>*');
     isSubtype('List<int>?', 'List<int>?');
 
-    isSubtype('List<int>', 'List<int*>');
     isSubtype('List<int>', 'List<int?>');
     // TODO(cstefantsova):  Uncomment the following when type arguments are
     // allowed to be intersection types.
 //    isSubtype('List<X & int>', 'List<X>',
 //        typeParameters: 'X extends Object?');
-    isSubtype('List<int*>', 'List<int>');
-    isSubtype('List<int*>', 'List<int*>');
-    isSubtype('List<int*>', 'List<int?>');
     isNotSubtype('List<int?>', 'List<int>');
-    isSubtype('List<int?>', 'List<int*>');
     isSubtype('List<int?>', 'List<int?>');
     // TODO(cstefantsova):  Uncomment the following when type arguments are
     // allowed to be intersection types.
 //    isSubtype('List<X & int?>', 'List<X>',
 //        typeParameters: 'X extends Object?');
 
-    isNotSubtype('List<int*>*', 'List<double*>*');
-    isNotSubtype('List<int*>*', 'Iterable<double*>*');
-    isNotSubtype('List<int*>*', 'Comparable<int*>*');
-    isNotSubtype('List<int*>*', 'List<Comparable<int*>*>*');
-    isNotSubtype('List<int*>*', 'List<Comparable<Comparable<int*>*>*>*');
-    isNotSubtype('List<int*>?', 'Object');
-    isNotSubtype('Null', 'List<int*>');
-    isNotSubtype('List<int*>', 'Never');
+    isNotSubtype('List<int>', 'List<double>');
+    isNotSubtype('List<int>', 'Iterable<double>');
+    isNotSubtype('List<int>', 'Comparable<int>');
+    isNotSubtype('List<int>', 'List<Comparable<int>>');
+    isNotSubtype('List<int>', 'List<Comparable<Comparable<int>>>');
+    isNotSubtype('List<int>?', 'Object');
+    isNotSubtype('List<int>', 'Never');
 
     isNotSubtype('T?', 'List<int>', typeParameters: 'T extends List<int>');
     isNotSubtype('T?', 'List<int>',
         functionTypeTypeParameters: 'T extends List<int>');
 
     // Tests for non-generic one-argument function types.
-    isSubtype('(num*) ->* num*', '(int*) ->* num*');
-    isSubtype('(num*) ->* int*', '(num*) ->* num*');
-    isSubtype('(num*) ->* int*', '(int*) ->* num*');
-    isNotSubtype('(int*) ->* int*', '(num*) ->* num*');
-    isSubtype('Null', '(int*) ->* num*');
-    isSubtype('Null', '(int*) ->? num*');
-    isSubtype('Never', '(int*) -> num*');
-    isSubtype('Never', '(int*) ->* num*');
-    isSubtype('Never', '(int*) ->? num*');
-    isSubtype('(num*) ->* num*', 'Object');
-    isSubtype('(num*) -> num*', 'Object');
-    isNotSubtype('(num*) ->? num*', 'Object');
-    isNotSubtype('Null', '(int*) -> num*');
-    isNotSubtype('(int*) -> num*', 'Never');
+    isSubtype('(num) -> num', '(int) -> num');
+    isSubtype('(num) -> int', '(num) -> num');
+    isSubtype('(num) -> int', '(int) -> num');
+    isNotSubtype('(int) -> int', '(num) -> num');
+    isSubtype('Null', '(int) ->? num');
+    isSubtype('Never', '(int) -> num');
+    isSubtype('Never', '(int) ->? num');
+    isSubtype('(num) -> num', 'Object');
+    isNotSubtype('(num) ->? num', 'Object');
+    isNotSubtype('Null', '(int) -> num');
+    isNotSubtype('(int) -> num', 'Never');
     isNotSubtype('num', '(num) -> num');
     isNotSubtype('Object', '(num) -> num');
-    isNotSubtype('Object*', '(num) -> num');
     isNotSubtype('Object?', '(num) -> num');
     isNotSubtype('dynamic', '(num) -> num');
 
-    isSubtype('(num) -> num', '(num) ->* num');
-    isSubtype('(num) ->* num', '(num) -> num');
-    isSubtype('(num) ->? num', '(num) ->* num');
-    isSubtype('(num) ->* num', '(num) ->? num');
+    isSubtype('(num) -> num', '(num) -> num');
     isSubtype('(num) -> num', '(num) ->? num');
     isNotSubtype('(num) ->? num', '(num) -> num');
 
@@ -157,14 +132,14 @@
     isNotSubtype('(num) -> num', '(num?) -> num?');
 
     // Tests for non-generic two-argument curried function types.
-    isSubtype('(num*) ->* (num*) ->* num*', '(num*) ->* (int*) ->* num*');
-    isNotSubtype('(num*) ->* (int*) ->* int*', '(num*) ->* (num*) ->* num*');
+    isSubtype('(num) -> (num) -> num', '(num) -> (int) -> num');
+    isNotSubtype('(num) -> (int) -> int', '(num) -> (num) -> num');
 
     // Tests for non-generic one-argument function types with named parameters.
-    isSubtype('({num* x}) ->* num*', '({int* x}) ->* num*');
-    isSubtype('(num*, {num* x}) ->* num*', '(int*, {int* x}) ->* num*');
-    isSubtype('({num* x}) ->* int*', '({num* x}) ->* num*');
-    isNotSubtype('({int* x}) ->* int*', '({num* x}) ->* num*');
+    isSubtype('({num x}) -> num', '({int x}) -> num');
+    isSubtype('(num, {num x}) -> num', '(int, {int x}) -> num');
+    isSubtype('({num x}) -> int', '({num x}) -> num');
+    isNotSubtype('({int x}) -> int', '({num x}) -> num');
 
     isSubtype('({num x}) -> num', '({num x}) -> num?');
     isSubtype('({num? x}) -> num', '({num x}) -> num');
@@ -179,58 +154,51 @@
     isNotSubtype('([num]) -> num', '([num?]) -> num?');
 
     // Tests for function types with type parameters.
-    isSubtype('<E>(E) ->* int*', '<E>(E) ->* num*');
-    isSubtype('<E>(num*) ->* E', '<E>(int*) ->* E');
-    isSubtype('<E>(E,num*) ->* E', '<E>(E,int*) ->* E');
-    isNotSubtype('<E>(E,num*) ->* E', '<E>(E,E) ->* E');
+    isSubtype('<E>(E) -> int', '<E>(E) -> num');
+    isSubtype('<E>(num) -> E', '<E>(int) -> E');
+    isSubtype('<E>(E,num) -> E', '<E>(E,int) -> E');
+    isNotSubtype('<E>(E,num) -> E', '<E>(E,E) -> E');
 
     // Tests for curried function types with type parameters.
-    isSubtype('<E>(E) ->* (E) ->* E', '<F>(F) ->* (F) ->* F');
-    isSubtype('<E>(E, (int*,E) ->* E) ->* E', '<E>(E, (int*,E) ->* E) ->* E');
-    isSubtype('<E>(E, (int*,E) ->* E) ->* E', '<E>(E, (num*,E) ->* E) ->* E');
-    isNotSubtype('<E,F>(E) ->* (F) ->* E', '<E>(E) ->* <F>(F) ->* E');
-    isNotSubtype('<E,F>(E) ->* (F) ->* E', '<F,E>(E) ->* (F) ->* E');
+    isSubtype('<E>(E) -> (E) -> E', '<F>(F) -> (F) -> F');
+    isSubtype('<E>(E, (int,E) -> E) -> E', '<E>(E, (int,E) -> E) -> E');
+    isSubtype('<E>(E, (int,E) -> E) -> E', '<E>(E, (num,E) -> E) -> E');
+    isNotSubtype('<E,F>(E) -> (F) -> E', '<E>(E) -> <F>(F) -> E');
+    isNotSubtype('<E,F>(E) -> (F) -> E', '<F,E>(E) -> (F) -> E');
 
-    isNotSubtype('<E>(E,num*) ->* E', '<E extends num*>(E*,E*) ->* E*');
-    isNotSubtype(
-        '<E extends num*>(E*) ->* int*', '<E extends int*>(E*) ->* int*');
-    isNotSubtype('<E extends num*>(E*) ->* E*', '<E extends int*>(E*) ->* E*');
-    isNotSubtype(
-        '<E extends num*>(int*) ->* E*', '<E extends int*>(int*) ->* E*');
-    isSubtype('<E extends num*>(E*) ->* E*', '<F extends num*>(F*) ->* num*');
-    isSubtype('<E extends int*>(E*) ->* E*', '<F extends int*>(F*) ->* num*');
-    isSubtype('<E extends int*>(E*) ->* E*', '<F extends int*>(F*) ->* int*');
-    isNotSubtype('<E>(int*) ->* int*', '(int*) ->* int*');
-    isNotSubtype('<E,F>(int*) ->* int*', '<E>(int*) ->* int*');
+    isNotSubtype('<E>(E,num) -> E', '<E extends num>(E,E) -> E');
+    isNotSubtype('<E extends num>(E) -> int', '<E extends int>(E) -> int');
+    isNotSubtype('<E extends num>(E) -> E', '<E extends int>(E) -> E');
+    isNotSubtype('<E extends num>(int) -> E', '<E extends int>(int) -> E');
+    isSubtype('<E extends num>(E) -> E', '<F extends num>(F) -> num');
+    isSubtype('<E extends int>(E) -> E', '<F extends int>(F) -> num');
+    isSubtype('<E extends int>(E) -> E', '<F extends int>(F) -> int');
+    isNotSubtype('<E>(int) -> int', '(int) -> int');
+    isNotSubtype('<E,F>(int) -> int', '<E>(int) -> int');
 
     // Tests for generic function types with bounded type parameters.
-    isSubtype(
-        '<E extends List<E*>*>(E*) ->* E*', '<F extends List<F*>*>(F*) ->* F*');
-    isNotSubtype('<E extends Iterable<E*>*>(E*) ->* E*',
-        '<F extends List<F*>*>(F*) ->* F*');
+    isSubtype('<E extends List<E>>(E) -> E', '<F extends List<F>>(F) -> F');
     isNotSubtype(
-        '<E>(E,List<Object*>*) ->* E*', '<F extends List<F*>*>(F*,F*) ->* F*');
-    isNotSubtype('<E>(E,List<Object*>*) ->* List<E>*',
-        '<F extends List<F*>*>(F*,F*) ->* F*');
-    isNotSubtype('<E>(E,List<Object*>*) ->* int*',
-        '<F extends List<F*>*>(F*,F*) ->* F*');
+        '<E extends Iterable<E>>(E) -> E', '<F extends List<F>>(F) -> F');
+    isNotSubtype('<E>(E,List<Object>) -> E', '<F extends List<F>>(F,F) -> F');
     isNotSubtype(
-        '<E>(E,List<Object*>*) ->* E', '<F extends List<F*>*>(F*,F*) ->* void');
+        '<E>(E,List<Object>) -> List<E>', '<F extends List<F>>(F,F) -> F');
+    isNotSubtype('<E>(E,List<Object>) -> int', '<F extends List<F>>(F,F) -> F');
+    isNotSubtype(
+        '<E>(E,List<Object>) -> E', '<F extends List<F>>(F,F) -> void');
 
-    isSubtype('<E extends num>(E) -> E', '<F extends num*>(F*) -> F*');
-    isSubtype('<E extends num*>(E*) -> E*', '<F extends num>(F) -> F');
-    isSubtype('<E extends num?>(E) -> E', '<F extends num*>(F*) -> F*');
-    isSubtype('<E extends num*>(E*) -> E*', '<F extends num?>(F) -> F');
+    isSubtype('<E extends num>(E) -> E', '<F extends num>(F) -> F');
+    isNotSubtype('<E extends num?>(E) -> E', '<F extends num>(F) -> F');
     isNotSubtype('<E extends num>(E) -> E', '<F extends num?>(F) -> F');
 
     // Tests for FutureOr.
-    isSubtype('int*', 'FutureOr<int*>*');
-    isSubtype('int*', 'FutureOr<num*>*');
-    isSubtype('Future<int*>*', 'FutureOr<int*>*');
-    isSubtype('Future<int*>*', 'FutureOr<num*>*');
-    isSubtype('Future<int*>*', 'FutureOr<Object*>*');
-    isSubtype('FutureOr<int*>*', 'FutureOr<int*>*');
-    isSubtype('FutureOr<int*>*', 'Object*');
+    isSubtype('int', 'FutureOr<int>');
+    isSubtype('int', 'FutureOr<num>');
+    isSubtype('Future<int>', 'FutureOr<int>');
+    isSubtype('Future<int>', 'FutureOr<num>');
+    isSubtype('Future<int>', 'FutureOr<Object>');
+    isSubtype('FutureOr<int>', 'FutureOr<int>');
+    isSubtype('FutureOr<int>', 'Object');
     isSubtype('Null', 'FutureOr<num?>');
     isSubtype('Null', 'FutureOr<num>?');
     isSubtype('num?', 'FutureOr<num?>');
@@ -248,19 +216,14 @@
     isSubtype('FutureOr<X>', 'FutureOr<Future<X>>',
         functionTypeTypeParameters: 'X extends Future<Future<X>>');
 
-    isSubtype('FutureOr<int*>*', 'FutureOr<num*>*');
+    isSubtype('FutureOr<int>', 'FutureOr<num>');
     isSubtype('FutureOr<A>', 'FutureOr<B>', typeParameters: 'B,A extends B');
     isSubtype('FutureOr<A>', 'FutureOr<B>',
         functionTypeTypeParameters: 'B,A extends B');
 
+    isSubtype('X', 'FutureOr<int>', typeParameters: 'X extends FutureOr<int>');
     isSubtype('X', 'FutureOr<int>',
-        typeParameters: 'X extends FutureOr<int*>*');
-    isSubtype('X', 'FutureOr<int>',
-        functionTypeTypeParameters: 'X extends FutureOr<int*>*');
-    isSubtype('X*', 'FutureOr<int>',
-        typeParameters: 'X extends FutureOr<int*>*');
-    isSubtype('X*', 'FutureOr<int>',
-        functionTypeTypeParameters: 'X extends FutureOr<int*>*');
+        functionTypeTypeParameters: 'X extends FutureOr<int>');
 
     isSubtype('num?', 'FutureOr<FutureOr<FutureOr<num>>?>');
     isSubtype('Future<num>?', 'FutureOr<FutureOr<FutureOr<num>>?>');
@@ -297,32 +260,20 @@
     isSubtype('dynamic', 'FutureOr<Object>?');
     isSubtype('void', 'FutureOr<Object?>');
     isSubtype('void', 'FutureOr<Object>?');
-    isSubtype('Object*', 'FutureOr<Object?>');
-    isSubtype('Object*', 'FutureOr<Object>?');
-    isSubtype('Object?', 'FutureOr<Object?>');
-    isSubtype('Object?', 'FutureOr<Object>?');
     isSubtype('Object', 'FutureOr<Object?>');
     isSubtype('Object', 'FutureOr<Object>?');
+    isSubtype('Object?', 'FutureOr<Object?>');
+    isSubtype('Object?', 'FutureOr<Object>?');
     isNotSubtype('dynamic', 'FutureOr<Object>');
     isNotSubtype('void', 'FutureOr<Object>');
     isNotSubtype('Object?', 'FutureOr<Object>');
     isSubtype('Object', 'FutureOr<Object>');
 
-    isSubtype('FutureOr<int>', 'Object');
-    isSubtype('FutureOr<int>', 'Object*');
     isSubtype('FutureOr<int>', 'Object?');
-    isSubtype('FutureOr<int>*', 'Object');
-    isSubtype('FutureOr<int>*', 'Object*');
-    isSubtype('FutureOr<int>*', 'Object?');
     isNotSubtype('FutureOr<int>?', 'Object');
-    isSubtype('FutureOr<int>?', 'Object*');
     isSubtype('FutureOr<int>?', 'Object?');
 
-    isSubtype('FutureOr<int*>', 'Object');
-    isSubtype('FutureOr<int*>', 'Object*');
-    isSubtype('FutureOr<int*>', 'Object?');
     isNotSubtype('FutureOr<int?>', 'Object');
-    isSubtype('FutureOr<int?>', 'Object*');
     isSubtype('FutureOr<int?>', 'Object?');
 
     isSubtype('FutureOr<Future<Object>>', 'Future<Object>');
@@ -330,20 +281,20 @@
     isNotSubtype('FutureOr<Future<Object>?>', 'Future<Object>');
     isNotSubtype('FutureOr<Future<Object>?>?', 'Future<Object>');
 
-    isNotSubtype('int*', 'FutureOr<double*>*');
-    isNotSubtype('FutureOr<double*>*', 'int*');
-    isNotSubtype('FutureOr<int*>*', 'Future<num*>*');
-    isNotSubtype('FutureOr<int*>*', 'num*');
-    isSubtype('Null', 'FutureOr<int*>*');
-    isSubtype('Null', 'Future<int*>*');
-    isSubtype('dynamic', 'FutureOr<dynamic>*');
-    isNotSubtype('dynamic', 'FutureOr<String*>*');
-    isSubtype('void', 'FutureOr<void>*');
-    isNotSubtype('void', 'FutureOr<String*>*');
+    isNotSubtype('int', 'FutureOr<double>');
+    isNotSubtype('FutureOr<double>', 'int');
+    isNotSubtype('FutureOr<int>', 'Future<num>');
+    isNotSubtype('FutureOr<int>', 'num');
+    isNotSubtype('Null', 'FutureOr<int>');
+    isNotSubtype('Null', 'Future<int>');
+    isSubtype('dynamic', 'FutureOr<dynamic>');
+    isNotSubtype('dynamic', 'FutureOr<String>');
+    isSubtype('void', 'FutureOr<void>');
+    isNotSubtype('void', 'FutureOr<String>');
 
-    isSubtype('E*', 'FutureOr<E*>*', typeParameters: 'E extends Object*');
-    isSubtype('E*', 'FutureOr<E*>*',
-        functionTypeTypeParameters: 'E extends Object*');
+    isSubtype('E', 'FutureOr<E>', typeParameters: 'E extends Object');
+    isSubtype('E', 'FutureOr<E>',
+        functionTypeTypeParameters: 'E extends Object');
     isSubtype('E?', 'FutureOr<E>?', typeParameters: 'E extends Object');
     isSubtype('E?', 'FutureOr<E>?',
         functionTypeTypeParameters: 'E extends Object');
@@ -362,10 +313,9 @@
     isSubtype('E', 'FutureOr<E>', typeParameters: 'E extends Object?');
     isSubtype('E', 'FutureOr<E>',
         functionTypeTypeParameters: 'E extends Object?');
-    isNotSubtype('E*', 'FutureOr<String*>*',
-        typeParameters: 'E extends Object*');
-    isNotSubtype('E*', 'FutureOr<String*>*',
-        functionTypeTypeParameters: 'E extends Object*');
+    isNotSubtype('E', 'FutureOr<String>', typeParameters: 'E extends Object');
+    isNotSubtype('E', 'FutureOr<String>',
+        functionTypeTypeParameters: 'E extends Object');
     isSubtype('E?', 'FutureOr<String>?', typeParameters: 'E extends String');
     isSubtype('E?', 'FutureOr<String>?',
         functionTypeTypeParameters: 'E extends String');
@@ -398,20 +348,15 @@
     isSubtype('FutureOr<X>', 'FutureOr<FutureOr<X>>',
         functionTypeTypeParameters: 'X extends num?');
 
-    isSubtype('() ->* String*', 'FutureOr<() ->* void>*');
     isSubtype('() -> String', 'FutureOr<() -> void>');
     isSubtype('() -> String', 'FutureOr<() ->? void>');
     isSubtype('() -> String', 'FutureOr<() -> void>?');
     isSubtype('() ->? String', 'FutureOr<() ->? void>');
     isSubtype('() ->? String', 'FutureOr<() -> void>?');
     isNotSubtype('() ->? String', 'FutureOr<() -> void>');
-    isNotSubtype('() ->? String', 'FutureOr<() -> void>');
-    isNotSubtype('() ->* void', 'FutureOr<() ->* String>*');
-    isSubtype('FutureOr<int*>*', 'FutureOr<num*>*');
-    isNotSubtype('FutureOr<num*>*', 'FutureOr<int*>*');
+    isNotSubtype('() -> void', 'FutureOr<() -> String>');
+    isNotSubtype('FutureOr<num>', 'FutureOr<int>');
 
-    isSubtype('T* & int*', 'FutureOr<num*>*',
-        typeParameters: 'T extends Object*');
     isSubtype('T & int', 'FutureOr<num>', typeParameters: 'T extends Object');
     isSubtype('T & int', 'FutureOr<num?>', typeParameters: 'T extends Object');
     isSubtype('T & int', 'FutureOr<num>?', typeParameters: 'T extends Object');
@@ -431,10 +376,8 @@
     isSubtype('T & S', 'FutureOr<Object>?',
         typeParameters: 'T extends Object?, S extends T');
 
-    isSubtype('T* & Future<num*>*', 'FutureOr<num*>*',
-        typeParameters: 'T extends Object*');
-    isSubtype('T* & Future<int*>*', 'FutureOr<num*>*',
-        typeParameters: 'T extends Object*');
+    isSubtype('T & Future<num>', 'FutureOr<num>',
+        typeParameters: 'T extends Object');
     isSubtype('T & Future<int>', 'FutureOr<num>',
         typeParameters: 'T extends Object');
     isSubtype('T & Future<int>', 'FutureOr<num?>',
@@ -469,30 +412,28 @@
         functionTypeTypeParameters: 'T extends FutureOr<T?>?');
 
     if (!skipFutureOrPromotion) {
-      isSubtype('T & FutureOr<int*>*', 'FutureOr<num*>*', typeParameters: 'T');
-      isSubtype('T & FutureOr<num*>*', 'FutureOr<num*>*', typeParameters: 'T');
-      isSubtype('T* & String*', 'FutureOr<num*>*',
-          typeParameters: 'T extends int*');
-      isSubtype('T* & Future<String*>*', 'FutureOr<num*>*',
-          typeParameters: 'T extends Future<num*>*');
-      isSubtype('T* & FutureOr<String*>*', 'FutureOr<num*>*',
-          typeParameters: 'T extends FutureOr<int*>*');
-      isSubtype('T* & FutureOr<String*>*', 'FutureOr<num*>*',
-          typeParameters: 'T extends FutureOr<num*>*');
+      isSubtype('T & FutureOr<int>', 'FutureOr<num>', typeParameters: 'T');
+      isSubtype('T & FutureOr<num>', 'FutureOr<num>', typeParameters: 'T');
+      isSubtype('T & String', 'FutureOr<num>', typeParameters: 'T extends int');
+      isSubtype('T & Future<String>', 'FutureOr<num>',
+          typeParameters: 'T extends Future<num>');
+      isSubtype('T & FutureOr<String>', 'FutureOr<num>',
+          typeParameters: 'T extends FutureOr<int>');
+      isSubtype('T & FutureOr<String>', 'FutureOr<num>',
+          typeParameters: 'T extends FutureOr<num>');
       isNotSubtype('FutureOr<num>', 'T & FutureOr<num>',
           typeParameters: 'T extends FutureOr<num>');
     }
-    isNotSubtype('T & num*', 'FutureOr<int*>*', typeParameters: 'T');
-    isNotSubtype('T & Future<num*>*', 'FutureOr<int*>*', typeParameters: 'T');
-    isNotSubtype('T & FutureOr<num*>*', 'FutureOr<int*>*', typeParameters: 'T');
-    isNotSubtype('T* & String*', 'FutureOr<int*>*',
-        typeParameters: 'T extends num*');
-    isNotSubtype('T* & Future<String*>*', 'FutureOr<int*>*',
-        typeParameters: 'T extends Future<num*>*');
-    isNotSubtype('T* & FutureOr<String*>*', 'FutureOr<int*>*',
-        typeParameters: 'T extends FutureOr<num*>*');
+    isNotSubtype('T & num', 'FutureOr<int>', typeParameters: 'T');
+    isNotSubtype('T & Future<num>', 'FutureOr<int>', typeParameters: 'T');
+    isNotSubtype('T & FutureOr<num>', 'FutureOr<int>', typeParameters: 'T');
+    isNotSubtype('T & String', 'FutureOr<int>',
+        typeParameters: 'T extends num');
+    isNotSubtype('T & Future<String>', 'FutureOr<int>',
+        typeParameters: 'T extends Future<num>');
+    isNotSubtype('T & FutureOr<String>', 'FutureOr<int>',
+        typeParameters: 'T extends FutureOr<num>');
 
-    isSubtype('Id<int*>*', 'FutureOr<num*>*');
     isSubtype('Id<int>', 'FutureOr<num>');
     isNotSubtype('Id<int?>', 'FutureOr<num>');
     isSubtype('Id<int?>', 'FutureOr<num?>');
@@ -500,29 +441,24 @@
     isNotSubtype('Id<int>?', 'FutureOr<num>');
     isSubtype('Id<int>?', 'FutureOr<num?>');
     isSubtype('Id<int>?', 'FutureOr<num>?');
-    isNotSubtype('Id<num*>*', 'FutureOr<int*>*');
+    isNotSubtype('Id<num>', 'FutureOr<int>');
 
-    isSubtype('FutureOr<Object*>*', 'FutureOr<FutureOr<Object*>*>*');
-    isSubtype('FutureOr<num>*', 'Object');
+    isSubtype('FutureOr<Object>', 'FutureOr<FutureOr<Object>>');
     isSubtype('FutureOr<num>', 'Object');
     isNotSubtype('FutureOr<num>?', 'Object');
     isSubtype('Never', 'FutureOr<num>');
-    isSubtype('Never', 'FutureOr<num*>');
-    isSubtype('Never', 'FutureOr<num>*');
     isSubtype('Never', 'FutureOr<num?>');
     isSubtype('Never', 'FutureOr<num>?');
     isNotSubtype('FutureOr<num>', 'Never');
 
     // Testing bottom types against an intersection type.
-    isSubtype('Null', 'T* & num*', typeParameters: 'T extends Object*');
-    isSubtype('Never', 'T* & num*', typeParameters: 'T extends Object*');
     isSubtype('Never', 'T & num', typeParameters: 'T extends Object');
     isNotSubtype('Null', 'T & num', typeParameters: 'T extends Object?');
     isNotSubtype('Null', 'T & num?', typeParameters: 'T extends Object?');
     isNotSubtype('Null', 'T & num', typeParameters: 'T extends Object');
     isNotSubtype('Null', 'T & S',
         typeParameters: 'T extends Object?, S extends T');
-    isNotSubtype('T* & num*', 'Never', typeParameters: 'T extends Object*');
+    isNotSubtype('T & num', 'Never', typeParameters: 'T extends Object');
     isSubtype('T', 'Never', typeParameters: 'T extends Never');
     isSubtype('T', 'Never', functionTypeTypeParameters: 'T extends Never');
     isSubtype('T & Never', 'Never', typeParameters: 'T extends Object');
@@ -555,8 +491,6 @@
     isNotSubtype('T', 'Null', functionTypeTypeParameters: 'T extends Object');
     isNotSubtype('T', 'Null', typeParameters: 'T extends Object?');
     isNotSubtype('T', 'Null', functionTypeTypeParameters: 'T extends Object?');
-    isSubtype('T', 'Never', typeParameters: 'T extends Never');
-    isSubtype('T', 'Never', functionTypeTypeParameters: 'T extends Never');
     isNotSubtype('T', 'Never', typeParameters: 'T extends Never?');
     isNotSubtype('T', 'Never', functionTypeTypeParameters: 'T extends Never?');
     isNotSubtype('T?', 'Never', typeParameters: 'T extends Never');
@@ -570,12 +504,11 @@
 
     // Trivial tests for type-parameter types and intersection types.
     // T & B <: T & A if B <: A
-    isSubtype('T* & int*', 'T* & int*', typeParameters: 'T extends Object*');
-    isSubtype('T* & int*', 'T* & num*', typeParameters: 'T extends Object*');
-    isSubtype('T* & num*', 'T* & num*', typeParameters: 'T extends Object*');
-    isNotSubtype('T* & num*', 'T* & int*', typeParameters: 'T extends Object*');
-
+    isSubtype('T & int', 'T & int', typeParameters: 'T extends Object');
     isSubtype('T & int', 'T & num', typeParameters: 'T extends Object');
+    isSubtype('T & num', 'T & num', typeParameters: 'T extends Object');
+    isNotSubtype('T & num', 'T & int', typeParameters: 'T extends Object');
+
     isSubtype('T & int', 'T & num', typeParameters: 'T extends Object?');
     isSubtype('T & int?', 'T & num?', typeParameters: 'T extends Object?');
     isNotSubtype('T & int?', 'T & num', typeParameters: 'T extends Object?');
@@ -583,36 +516,31 @@
     // T & B <: T extends A if B <: A
     // (Trivially satisfied since promoted bounds are always a isSubtype of the
     // original bound)
-    isSubtype('T* & int*', 'T*', typeParameters: 'T extends int*');
-    isSubtype('T* & int*', 'T*', typeParameters: 'T extends num*');
-    isSubtype('T* & num*', 'T*', typeParameters: 'T extends num*');
+    isSubtype('T & int', 'T', typeParameters: 'T extends int');
+    isSubtype('T & int', 'T', typeParameters: 'T extends num');
+    isSubtype('T & num', 'T', typeParameters: 'T extends num');
 
     // T extends B <: T & A if B <: A
-    isSubtype('T*', 'T* & int*', typeParameters: 'T extends int*');
     isSubtype('T', 'T & int', typeParameters: 'T extends int');
     isNotSubtype('T?', 'T & int', typeParameters: 'T extends int');
     isNotSubtype('T', 'T & int', typeParameters: 'T extends int?');
     isSubtype('T', 'T & int?', typeParameters: 'T extends int?');
     isNotSubtype('T?', 'T & int?', typeParameters: 'T extends int?');
 
-    isSubtype('T*', 'T* & num*', typeParameters: 'T extends int*');
     isSubtype('T', 'T & num', typeParameters: 'T extends int');
     isNotSubtype('T', 'T & num', typeParameters: 'T extends int?');
     isSubtype('T', 'T & num?', typeParameters: 'T extends int?');
     isNotSubtype('T?', 'T & num?', typeParameters: 'T extends int?');
 
-    isSubtype('T*', 'T* & num*', typeParameters: 'T extends num*');
     isSubtype('T', 'T & num', typeParameters: 'T extends num');
     isNotSubtype('T?', 'T & num', typeParameters: 'T extends num');
     isNotSubtype('T', 'T & num', typeParameters: 'T extends num?');
     isSubtype('T', 'T & num?', typeParameters: 'T extends num?');
     isNotSubtype('T?', 'T & num?', typeParameters: 'T extends num?');
 
-    isNotSubtype('T*', 'T* & int*', typeParameters: 'T extends num*');
+    isNotSubtype('T', 'T & int', typeParameters: 'T extends num');
 
     // T extends A <: T extends A
-    isSubtype('T*', 'T*', typeParameters: 'T extends num*');
-    isSubtype('T*', 'T*', functionTypeTypeParameters: 'T extends num*');
     isSubtype('T', 'T', typeParameters: 'T extends num');
     isSubtype('T', 'T', functionTypeTypeParameters: 'T extends num');
     isSubtype('T', 'T', typeParameters: 'T extends num?');
@@ -627,12 +555,12 @@
     isNotSubtype('S', 'T', typeParameters: 'S, T');
     isNotSubtype('S', 'T', functionTypeTypeParameters: 'S, T');
 
-    isSubtype('T*', 'T*', typeParameters: 'T extends Object*');
-    isSubtype('T*', 'T*', functionTypeTypeParameters: 'T extends Object*');
-    isNotSubtype('S*', 'T*',
-        typeParameters: 'S extends Object*, T extends Object*');
-    isNotSubtype('S*', 'T*',
-        functionTypeTypeParameters: 'S extends Object*, T extends Object*');
+    isSubtype('T', 'T', typeParameters: 'T extends Object');
+    isSubtype('T', 'T', functionTypeTypeParameters: 'T extends Object');
+    isNotSubtype('S', 'T',
+        typeParameters: 'S extends Object, T extends Object');
+    isNotSubtype('S', 'T',
+        functionTypeTypeParameters: 'S extends Object, T extends Object');
 
     isSubtype('T', 'T', typeParameters: 'T extends dynamic');
     isSubtype('T', 'T', functionTypeTypeParameters: 'T extends dynamic');
@@ -644,13 +572,10 @@
     // S <: T extends S
     isNotSubtype('S', 'T', typeParameters: 'S, T extends S');
     isNotSubtype('S', 'T', functionTypeTypeParameters: 'S, T extends S');
-    isSubtype('T*', 'S*', typeParameters: 'S extends Object*, T extends S*');
-    isSubtype('T*', 'S*',
-        functionTypeTypeParameters: 'S extends Object*, T extends S*');
-
     isSubtype('T', 'S', typeParameters: 'S extends Object, T extends S');
     isSubtype('T', 'S',
         functionTypeTypeParameters: 'S extends Object, T extends S');
+
     isSubtype('T', 'S?', typeParameters: 'S extends Object, T extends S');
     isSubtype('T', 'S?',
         functionTypeTypeParameters: 'S extends Object, T extends S');
@@ -700,8 +625,6 @@
     isSubtype('T?', 'S?',
         functionTypeTypeParameters: 'S extends Object, T extends S?');
 
-    isSubtype('T* & V*', 'S*',
-        typeParameters: 'S extends Object*, T extends S*, V extends S*');
     isSubtype('T & V', 'S',
         typeParameters: 'S extends Object, T extends S, V extends S');
     isSubtype('T & V?', 'S?',
@@ -715,82 +638,55 @@
 
     // Non-trivial tests for intersection types.
     // S & B <: A if B <: A, A is not S (or a promotion thereof)
-    isSubtype('S & int*', 'int*', typeParameters: 'S');
-    isSubtype('S & int*', 'num*', typeParameters: 'S');
-    isSubtype('S & num*', 'num*', typeParameters: 'S');
-    isNotSubtype('S & num*', 'int*', typeParameters: 'S');
-    isNotSubtype('S & num*', 'T', typeParameters: 'S, T');
-    isNotSubtype('S & num*', 'T & num*', typeParameters: 'S, T');
+    isSubtype('S & int', 'int', typeParameters: 'S');
+    isSubtype('S & int', 'num', typeParameters: 'S');
+    isSubtype('S & num', 'num', typeParameters: 'S');
+    isNotSubtype('S & num', 'int', typeParameters: 'S');
+    isNotSubtype('S & num', 'T', typeParameters: 'S, T');
+    isNotSubtype('S & num', 'T & num', typeParameters: 'S, T');
     isSubtype('S & num', 'num', typeParameters: 'S extends Object?');
     isNotSubtype('S & num?', 'num', typeParameters: 'S extends Object?');
     isSubtype('S & num?', 'num?', typeParameters: 'S extends Object?');
-    isSubtype('S & num?', 'num*', typeParameters: 'S extends Object?');
 
     // S extends B <: A if B <: A, A is not S (or a promotion thereof)
-    isSubtype('S*', 'int*', typeParameters: 'S extends int*');
-    isSubtype('S*', 'num*', typeParameters: 'S extends int*');
-    isSubtype('S*', 'num*', typeParameters: 'S extends num*');
-    isSubtype('S*', 'Object', typeParameters: 'S extends num*');
+    isSubtype('S', 'int', typeParameters: 'S extends int');
+    isSubtype('S', 'num', typeParameters: 'S extends int');
+    isSubtype('S', 'num', typeParameters: 'S extends num');
     isSubtype('S', 'Object', typeParameters: 'S extends num');
-    isNotSubtype('S*', 'int*', typeParameters: 'S extends num*');
-    isNotSubtype('S*', 'T', typeParameters: 'S extends num*, T');
-    isNotSubtype('S*', 'T & num*', typeParameters: 'S extends num*, T');
+    isNotSubtype('S', 'int', typeParameters: 'S extends num');
+    isNotSubtype('S', 'T', typeParameters: 'S extends num, T');
+    isNotSubtype('S', 'T & num', typeParameters: 'S extends num, T');
     isNotSubtype('S?', 'Object', typeParameters: 'S extends num');
     isNotSubtype('S', 'Object', typeParameters: 'S extends num?');
     isNotSubtype('S?', 'Object', typeParameters: 'S extends num?');
 
     isNotSubtype('dynamic', 'int');
-    isNotSubtype('dynamic', 'int*');
     isNotSubtype('dynamic', 'int?');
     isNotSubtype('void', 'int');
-    isNotSubtype('void', 'int*');
     isNotSubtype('void', 'int?');
     isNotSubtype('Object', 'int');
-    isNotSubtype('Object', 'int*');
     isNotSubtype('Object', 'int?');
-    isNotSubtype('Object*', 'int');
-    isNotSubtype('Object*', 'int*');
-    isNotSubtype('Object*', 'int?');
     isNotSubtype('Object?', 'int');
-    isNotSubtype('Object?', 'int*');
     isNotSubtype('Object?', 'int?');
-    isNotSubtype('() ->* int*', 'int*');
-    isNotSubtype('Typedef<Object*>*', 'int*');
+    isNotSubtype('() -> int', 'int');
+    isNotSubtype('Typedef<Object>', 'int');
 
-    isSubtype('() -> int*', 'Function');
-    isSubtype('() -> int*', 'Function*');
-    isSubtype('() -> int*', 'Function?');
-    isSubtype('() ->* int*', 'Function');
-    isSubtype('() ->* int*', 'Function*');
-    isSubtype('() ->* int*', 'Function?');
-    isNotSubtype('() ->? int*', 'Function');
-    isSubtype('() ->? int*', 'Function*');
-    isSubtype('() ->? int*', 'Function?');
+    isSubtype('() -> int', 'Function');
+    isSubtype('() -> int', 'Function?');
+    isNotSubtype('() ->? int', 'Function');
+    isSubtype('() ->? int', 'Function?');
 
-    isSubtype('() -> int*', 'Object');
-    isSubtype('() -> int*', 'Object*');
-    isSubtype('() -> int*', 'Object?');
-    isSubtype('() ->* int*', 'Object');
-    isSubtype('() ->* int*', 'Object*');
-    isSubtype('() ->* int*', 'Object?');
-    isNotSubtype('() ->? int*', 'Object');
-    isSubtype('() ->? int*', 'Object*');
-    isSubtype('() ->? int*', 'Object?');
+    isSubtype('() -> int', 'Object');
+    isSubtype('() -> int', 'Object?');
+    isNotSubtype('() ->? int', 'Object');
+    isSubtype('() ->? int', 'Object?');
 
     // Tests for "Null".
-    isSubtype('Null', 'double*');
-    isSubtype('Null', 'Comparable<Object*>*');
-    isSubtype('Null', 'Comparable<Object*>?');
-    isSubtype('Null', 'Typedef<Object*>*');
-    isSubtype('Null', 'Typedef<Object*>?');
-    isSubtype('Null', 'T', typeParameters: 'T extends Object*');
-    isSubtype('Null', 'T', functionTypeTypeParameters: 'T extends Object*');
-    isSubtype('Null', 'T?', typeParameters: 'T extends Object');
-    isSubtype('Null', 'T?', functionTypeTypeParameters: 'T extends Object');
-    isNotSubtype('Null', 'T', typeParameters: 'T extends Object?');
-    isNotSubtype('Null', 'T', functionTypeTypeParameters: 'T extends Object?');
-    isNotSubtype('Null', 'T', typeParameters: 'T extends Object');
-    isNotSubtype('Null', 'T', functionTypeTypeParameters: 'T extends Object');
+    isNotSubtype('Null', 'double');
+    isNotSubtype('Null', 'Comparable<Object>');
+    isSubtype('Null', 'Comparable<Object>?');
+    isNotSubtype('Null', 'Typedef<Object>');
+    isSubtype('Null', 'Typedef<Object>?');
     isNotSubtype('Null', 'Object');
 
     // Tests for bottom and top types.
@@ -804,67 +700,52 @@
     isSubtype('Never', 'Never?');
     isNotSubtype('Never?', 'Never');
 
-    isSubtype('Object*', 'Object*');
-    isSubtype('Object*', 'dynamic');
-    isSubtype('Object*', 'void');
-    isSubtype('Object*', 'Object?');
-    isSubtype('dynamic', 'Object*');
+    isSubtype('Object', 'Object');
+    isSubtype('Object', 'dynamic');
+    isSubtype('Object', 'void');
+    isSubtype('Object', 'Object?');
+    isNotSubtype('dynamic', 'Object');
     isSubtype('dynamic', 'dynamic');
     isSubtype('dynamic', 'void');
     isSubtype('dynamic', 'Object?');
-    isSubtype('void', 'Object*');
+    isNotSubtype('void', 'Object');
     isSubtype('void', 'dynamic');
     isSubtype('void', 'void');
     isSubtype('void', 'Object?');
-    isSubtype('Object?', 'Object*');
+    isNotSubtype('Object?', 'Object');
     isSubtype('Object?', 'dynamic');
     isSubtype('Object?', 'void');
     isSubtype('Object?', 'Object?');
 
     isSubtype('Never', 'Object?');
-    isSubtype('Never', 'Object*');
+    isSubtype('Never', 'Object');
     isSubtype('Never', 'dynamic');
     isSubtype('Never', 'void');
     isSubtype('Null', 'Object?');
-    isSubtype('Null', 'Object*');
     isSubtype('Null', 'dynamic');
     isSubtype('Null', 'void');
 
     isNotSubtype('Object?', 'Never');
     isNotSubtype('Object?', 'Null');
-    isNotSubtype('Object*', 'Never');
-    isNotSubtype('Object*', 'Null');
+    isNotSubtype('Object', 'Never');
+    isNotSubtype('Object', 'Null');
     isNotSubtype('dynamic', 'Never');
     isNotSubtype('dynamic', 'Null');
     isNotSubtype('void', 'Never');
     isNotSubtype('void', 'Null');
 
-    // Tests for Object against the top and the bottom types.
-    isSubtype('Never', 'Object');
-    isSubtype('Object', 'dynamic');
-    isSubtype('Object', 'void');
-    isSubtype('Object', 'Object?');
-    isSubtype('Object', 'Object*');
-    isSubtype('Object*', 'Object');
-
-    isNotSubtype('Object', 'Null');
-    isNotSubtype('Object', 'Never');
-    isNotSubtype('dynamic', 'Object');
-    isNotSubtype('void', 'Object');
-    isNotSubtype('Object?', 'Object');
-
     // Check that the top types are equivalent.
     isSubtype(
-        '<S extends Object*, T extends void, R extends Object?>'
-            '(S, T, R) ->* void',
-        '<U extends dynamic, V extends Object*, W extends void>'
-            '(U, V, W) ->* void');
+        '<S extends dynamic, T extends void, R extends Object?>'
+            '(S, T, R) -> void',
+        '<U extends void, V extends Object?, W extends dynamic>'
+            '(U, V, W) -> void');
 
     {
-      String d = '<T extends void>() ->* T';
-      String e = '<T extends Object?>() ->* T';
-      String f = '<T extends dynamic>() ->* T';
-      String g = '<T extends Object*>() ->* T*';
+      String d = '<T extends void>() -> T';
+      String e = '<T extends Object?>() -> T';
+      String f = '<T extends dynamic>() -> T';
+      String g = '<T extends Object>() -> T';
 
       // d = e.
       isSubtype(d, e);
@@ -875,91 +756,87 @@
       isSubtype(f, e);
 
       // f = g.
-      isSubtype(f, g);
-      isSubtype(g, f);
+      isNotSubtype(f, g);
+      isNotSubtype(g, f);
     }
 
     {
-      String h = '<T extends List<dynamic>*>() ->* T*';
-      String i = '<T extends List<Object*>*>() ->* T*';
-      String j = '<T extends List<void>*>() ->* T*';
-      String k = '<T extends List<Object?>*>() ->* T*';
-      isSubtype(h, i);
+      String h = '<T extends List<dynamic>>() -> T';
+      String i = '<T extends List<Object>>() -> T';
+      String j = '<T extends List<void>>() -> T';
+      String k = '<T extends List<Object?>>() -> T';
+      isNotSubtype(h, i);
       isSubtype(h, j);
       isSubtype(h, k);
-      isSubtype(i, h);
-      isSubtype(i, j);
-      isSubtype(i, k);
+      isNotSubtype(i, h);
+      isNotSubtype(i, j);
+      isNotSubtype(i, k);
       isSubtype(j, h);
-      isSubtype(j, i);
+      isNotSubtype(j, i);
       isSubtype(j, k);
       isSubtype(k, h);
-      isSubtype(k, i);
+      isNotSubtype(k, i);
       isSubtype(k, j);
     }
 
     // Tests for checking function types against other kinds of types.
-    isNotSubtype('dynamic', '() ->* dynamic');
-    isNotSubtype('FutureOr<() ->* void>*', '() ->* void');
-    isSubtype('T & () ->* void', '() ->* void', typeParameters: 'T');
-    isSubtype('T & () ->* void', '() ->* dynamic', typeParameters: 'T');
-    isSubtype('T & () ->* void', '() ->* Object*', typeParameters: 'T');
+    isNotSubtype('dynamic', '() -> dynamic');
+    isNotSubtype('FutureOr<() -> void>', '() -> void');
+    isSubtype('T & () -> void', '() -> void', typeParameters: 'T');
+    isSubtype('T & () -> void', '() -> dynamic', typeParameters: 'T');
+    isNotSubtype('T & () -> void', '() -> Object', typeParameters: 'T');
 
-    isSubtype('T & (void) ->* void', '(void) ->* void', typeParameters: 'T');
-    isSubtype('T & (void) ->* void', '(dynamic) ->* dynamic',
+    isSubtype('T & (void) -> void', '(void) -> void', typeParameters: 'T');
+    isSubtype('T & (void) -> void', '(dynamic) -> dynamic',
         typeParameters: 'T');
-    isSubtype('T & (void) ->* void', '(Object*) ->* Object*',
+    isSubtype('T & (void) -> void', '(Object?) -> Object?',
+        typeParameters: 'T');
+    isNotSubtype('T & (void) -> void', '(Object) -> Object',
         typeParameters: 'T');
 
-    isSubtype('T & (void) ->* void', '(void) ->* void', typeParameters: 'T');
-    isSubtype('T & (void) ->* void', '(Iterable<int*>*) ->* dynamic',
+    isSubtype('T & (void) -> void', '(Iterable<int>) -> dynamic',
         typeParameters: 'T');
-    isSubtype('T & (void) ->* void', '(int*) ->* Object*', typeParameters: 'T');
+    isSubtype('T & (void) -> void', '(int) -> Object?', typeParameters: 'T');
 
-    isNotSubtype('T & (void) ->* void', '(int*) ->* int*', typeParameters: 'T');
+    isNotSubtype('T & (void) -> void', '(int) -> int', typeParameters: 'T');
 
-    isSubtype('T*', '() ->* void', typeParameters: 'T extends () ->* void');
-    isSubtype('T*', '() ->* void',
-        functionTypeTypeParameters: 'T extends () ->* void');
     isSubtype('T', '() -> void', typeParameters: 'T extends () -> void');
     isSubtype('T', '() -> void',
         functionTypeTypeParameters: 'T extends () -> void');
     isNotSubtype('T?', '() -> void', typeParameters: 'T extends () -> void');
     isNotSubtype('T?', '() -> void',
         functionTypeTypeParameters: 'T extends () -> void');
-    isNotSubtype('T', '() ->* void', typeParameters: 'T');
-    isNotSubtype('T', '() ->* void', functionTypeTypeParameters: 'T');
-    isNotSubtype('Typedef<void>*', '() ->* void');
-    isSubtype('VoidFunction*', '() ->* void');
+    isNotSubtype('T', '() -> void', typeParameters: 'T');
+    isNotSubtype('T', '() -> void', functionTypeTypeParameters: 'T');
+    isNotSubtype('Typedef<void>', '() -> void');
+    isSubtype('VoidFunction', '() -> void');
     isNotSubtype(
-        'DefaultTypes<void, void, List<void>*, List<void>*, '
-            'int*, (int*) ->* void, () ->* int>*',
-        '() ->* void');
-    isNotSubtype('void', '() ->* void');
+        'DefaultTypes<void, void, List<void>, List<void>, '
+            'int, (int) -> void, () -> int>',
+        '() -> void');
+    isNotSubtype('void', '() -> void');
 
     // Tests for checking typedef-types against other kinds of types.
     isNotSubtype('dynamic', 'T', typeParameters: 'T');
     isNotSubtype('dynamic', 'T', functionTypeTypeParameters: 'T');
-    isNotSubtype('Iterable<T>*', 'T', typeParameters: 'T');
-    isNotSubtype('Iterable<T>*', 'T', functionTypeTypeParameters: 'T');
-    isNotSubtype('() ->* void', 'T', typeParameters: 'T');
-    isNotSubtype('() ->* void', 'T', functionTypeTypeParameters: 'T');
-    isNotSubtype('FutureOr<T>*', 'T', typeParameters: 'T');
-    isNotSubtype('FutureOr<T>*', 'T', functionTypeTypeParameters: 'T');
-    isSubtype('Id<T>*', 'T', typeParameters: 'T');
-    isSubtype('Id<T>*', 'T', functionTypeTypeParameters: 'T');
-    isNotSubtype('VoidFunction*', 'T*',
-        typeParameters: 'T extends () ->* void');
-    isNotSubtype('VoidFunction*', 'T*',
-        functionTypeTypeParameters: 'T extends () ->* void');
+    isNotSubtype('Iterable<T>', 'T', typeParameters: 'T');
+    isNotSubtype('Iterable<T>', 'T', functionTypeTypeParameters: 'T');
+    isNotSubtype('() -> void', 'T', typeParameters: 'T');
+    isNotSubtype('() -> void', 'T', functionTypeTypeParameters: 'T');
+    isNotSubtype('FutureOr<T>', 'T', typeParameters: 'T');
+    isNotSubtype('FutureOr<T>', 'T', functionTypeTypeParameters: 'T');
+    isSubtype('Id<T>', 'T', typeParameters: 'T');
+    isSubtype('Id<T>', 'T', functionTypeTypeParameters: 'T');
+    isNotSubtype('VoidFunction', 'T', typeParameters: 'T extends () -> void');
+    isNotSubtype('VoidFunction', 'T',
+        functionTypeTypeParameters: 'T extends () -> void');
     isNotSubtype('void', 'T', typeParameters: 'T extends void');
     isNotSubtype('void', 'T', functionTypeTypeParameters: 'T extends void');
 
     // Tests for checking typedef types against other kinds of types.
-    isSubtype('dynamic', 'Id<dynamic>*');
-    isNotSubtype('dynamic', 'Id<int*>*');
+    isSubtype('dynamic', 'Id<dynamic>');
+    isNotSubtype('dynamic', 'Id<int>');
 
-    isSubtype('() ->* void', 'Id<() ->* void>*');
     isSubtype('() -> void', 'Id<() -> void>');
     isSubtype('() -> void', 'Id<() ->? void>');
     isSubtype('() ->? void', 'Id<() ->? void>');
@@ -969,17 +846,15 @@
     isSubtype('() -> void', 'VoidFunction?');
     isSubtype('() ->? void', 'VoidFunction?');
 
-    isNotSubtype('() ->* void', 'Id<() ->* int>*');
-    isNotSubtype('FutureOr<() ->* void>*', 'Id<() ->* void>*');
-    isSubtype('FutureOr<() ->* void>*', 'Id<FutureOr<() ->* void>*>*');
-    isSubtype('int*', 'Id<int*>*');
-    isSubtype('T & () ->* void', 'Id<() ->* void>*', typeParameters: 'T');
-    isSubtype('T & () ->* void', 'Id<() ->* dynamic>*', typeParameters: 'T');
-    isSubtype('T & () ->* void', 'Id<() ->* Object*>*', typeParameters: 'T');
+    isNotSubtype('() -> void', 'Id<() -> int>');
+    isNotSubtype('FutureOr<() -> void>', 'Id<() -> void>');
+    isSubtype('FutureOr<() -> void>', 'Id<FutureOr<() -> void>>');
+    isSubtype('int', 'Id<int>');
+    isSubtype('T & () -> void', 'Id<() -> void>', typeParameters: 'T');
+    isSubtype('T & () -> void', 'Id<() -> dynamic>', typeParameters: 'T');
+    isSubtype('T & () -> void', 'Id<() -> Object?>', typeParameters: 'T');
     isSubtype('Object', 'Id<Object>');
     isSubtype('Id<Object>', 'Object');
-    isSubtype('Object*', 'Id<Object>');
-    isSubtype('Id<Object>', 'Object*');
     isNotSubtype('dynamic', 'Id<Object>');
     isSubtype('Id<Object>', 'dynamic');
     isNotSubtype('void', 'Id<Object>');
@@ -995,41 +870,32 @@
     isNotSubtype('Id<int?>', 'num');
     isNotSubtype('Id<int>?', 'num');
     isNotSubtype('Id<int?>?', 'num');
-    isSubtype('Id<int>', 'num*');
-    isSubtype('Id<int?>', 'num*');
-    isSubtype('Id<int>?', 'num*');
-    isSubtype('Id<int?>?', 'num*');
     isSubtype('Id<int>', 'num?');
     isSubtype('Id<int?>', 'num?');
     isSubtype('Id<int>?', 'num?');
     isSubtype('Id<int?>?', 'num?');
 
-    isSubtype('T & (void) ->* void', 'Id<(void) ->* void>*',
+    isSubtype('T & (void) -> void', 'Id<(void) -> void>', typeParameters: 'T');
+    isSubtype('T & (void) -> void', 'Id<(dynamic) -> dynamic>',
         typeParameters: 'T');
-    isSubtype('T & (void) ->* void', 'Id<(dynamic) ->* dynamic>*',
-        typeParameters: 'T');
-    isSubtype('T & (void) ->* void', 'Id<(Object*) ->* Object*>*',
+    isSubtype('T & (void) -> void', 'Id<(Object?) -> Object?>',
         typeParameters: 'T');
 
-    isSubtype('T & (void) ->* void', 'Id<(void) ->* void>*',
+    isSubtype('T & (void) -> void', 'Id<(Iterable<int>) -> dynamic>',
         typeParameters: 'T');
-    isSubtype('T & (void) ->* void', 'Id<(Iterable<int*>*) ->* dynamic>*',
-        typeParameters: 'T');
-    isSubtype('T & (void) ->* void', 'Id<(int*) ->* Object*>*',
+    isSubtype('T & (void) -> void', 'Id<(int) -> Object?>',
         typeParameters: 'T');
 
-    isNotSubtype('T & (void) ->* void', 'Id<(int*) ->* int*>*',
-        typeParameters: 'T');
+    isNotSubtype('T & (void) -> void', 'Id<(int) -> int>', typeParameters: 'T');
     isNotSubtype('dynamic', 'T & dynamic', typeParameters: 'T extends dynamic');
-    isNotSubtype('() ->* T*', 'T* & () ->* T*',
-        typeParameters: 'T extends Object*');
+    isNotSubtype('() -> T', 'T & () -> T', typeParameters: 'T extends Object');
 
-    isNotSubtype('FutureOr<T & String*>*', 'T & String*', typeParameters: 'T');
+    isNotSubtype('FutureOr<T & String>', 'T & String', typeParameters: 'T');
 
     // TODO(cstefantsova): Uncomment the following when type arguments are
     // allowed to be intersection types.
-//    isSubtype('Id<T* & String*>*', 'T* & String*',
-//        typeParameters: 'T extends Object*');
+//    isSubtype('Id<T & String>', 'T & String',
+//        typeParameters: 'T extends Object');
 //    isSubtype('Id<T & String>', 'T & String',
 //        typeParameters: 'T extends Object');
 //    isSubtype('Id<T & String>', 'T & String',
@@ -1045,124 +911,114 @@
 //    isNotSubtype('Id<T & String>?', 'T & String?',
 //        typeParameters: 'T extends Object');
 //
-//    isSubtype('Id<T* & String*>*', 'T*', typeParameters: 'T extends Object*');
+//    isSubtype('Id<T & String>', 'T', typeParameters: 'T extends Object');
 //    isSubtype('Id<T & String>', 'T', typeParameters: 'T extends Object');
 //    isSubtype('Id<T & String>', 'T?', typeParameters: 'T extends Object');
 //    isSubtype('Id<T & String>', 'T', typeParameters: 'T extends Object?');
 //    isSubtype('Id<T & String?>', 'T', typeParameters: 'T extends Object?');
 //    isSubtype('Id<T & String>?', 'T?', typeParameters: 'T extends Object?');
 //
-//    isSubtype('Id<T* & String*>*', 'String*',
-//        typeParameters: 'T extends Object*');
-//    isNotSubtype('Id<T & String*>*', 'S & String*', typeParameters: 'T, S');
+//    isSubtype('Id<T & String>', 'String',
+//        typeParameters: 'T extends Object');
+//    isNotSubtype('Id<T & String>', 'S & String', typeParameters: 'T, S');
 
-    isNotSubtype('void', 'T* & void', typeParameters: 'T extends Object*');
+    isNotSubtype('void', 'T & void', typeParameters: 'T extends Object');
     isNotSubtype('void', 'T & void', typeParameters: 'T extends void');
     isNotSubtype('Object', 'T & Object', typeParameters: 'T extends Object');
     isNotSubtype('Object?', 'T & Object', typeParameters: 'T extends Object?');
     isNotSubtype('Object?', 'T & Object?', typeParameters: 'T extends Object?');
-    isNotSubtype('Object*', 'T & Object*', typeParameters: 'T extends Object*');
     isNotSubtype('num', 'T & num', typeParameters: 'T extends num');
     isNotSubtype('FutureOr<num>', 'T & num', typeParameters: 'T extends num');
 
-    isSubtype('T', 'Id<T>*', typeParameters: 'T');
-    isSubtype('T', 'Id<T>*', functionTypeTypeParameters: 'T');
-    isSubtype('T', 'Id<Object*>*', typeParameters: 'T');
-    isSubtype('T', 'Id<Object*>*', functionTypeTypeParameters: 'T');
-    isNotSubtype('T', 'Id<Comparable<int*>*>*', typeParameters: 'T');
-    isNotSubtype('T', 'Id<Comparable<int*>*>*',
-        functionTypeTypeParameters: 'T');
-    isSubtype('T*', 'Id<Comparable<int*>*>*',
-        typeParameters: 'T extends Comparable<int*>*');
-    isSubtype('T*', 'Id<Comparable<int*>*>*',
-        functionTypeTypeParameters: 'T extends Comparable<int*>*');
+    isSubtype('T', 'Id<T>', typeParameters: 'T');
+    isSubtype('T', 'Id<T>', functionTypeTypeParameters: 'T');
+    isSubtype('T', 'Id<Object?>', typeParameters: 'T');
+    isSubtype('T', 'Id<Object?>', functionTypeTypeParameters: 'T');
+    isNotSubtype('T', 'Id<Comparable<int>>', typeParameters: 'T');
+    isNotSubtype('T', 'Id<Comparable<int>>', functionTypeTypeParameters: 'T');
+    isSubtype('T', 'Id<Comparable<int>>',
+        typeParameters: 'T extends Comparable<int>');
+    isSubtype('T', 'Id<Comparable<int>>',
+        functionTypeTypeParameters: 'T extends Comparable<int>');
 
-    isSubtype('Id<int*>*', 'Id<int*>*');
-    isSubtype('Id<int*>*', 'Id<Object*>*');
-    isNotSubtype('Id<Object*>*', 'Id<int*>*');
-    isSubtype('Id<() ->* int*>*', 'Id<() ->* int*>*');
-    isSubtype('Id<() ->* int*>*', 'Id<() ->* Object*>*');
-    isNotSubtype('Id<() ->* Object*>*', 'Id<() ->* int*>*');
+    isSubtype('Id<int>', 'Id<int>');
+    isSubtype('Id<int>', 'Id<Object>');
+    isNotSubtype('Id<Object>', 'Id<int>');
+    isSubtype('Id<() -> int>', 'Id<() -> int>');
+    isSubtype('Id<() -> int>', 'Id<() -> Object>');
+    isNotSubtype('Id<() -> Object>', 'Id<() -> int>');
 
-    isSubtype('void', 'Id<void>*');
-    isNotSubtype('void', 'Id<Null>*');
+    isSubtype('void', 'Id<void>');
+    isNotSubtype('void', 'Id<Null>');
 
     // The following function type tests are derived from
     // ../../../../../pkg/compiler/test/model/subtype_test.dart.
-    isSubtype("() ->* int*", 'Function*');
-    isNotSubtype('Function*', "() ->* int*");
+    isNotSubtype('Function', "() -> int");
 
-    isSubtype("() ->* dynamic", "() ->* dynamic");
-    isSubtype("() ->* dynamic", "() ->* void");
-    isSubtype("() ->* void", "() ->* dynamic");
+    isSubtype("() -> dynamic", "() -> dynamic");
+    isSubtype("() -> dynamic", "() -> void");
+    isSubtype("() -> void", "() -> dynamic");
 
-    isSubtype("() ->* int*", "() ->* void");
-    isNotSubtype("() ->* void", "() ->* int*");
-    isSubtype("() ->* void", "() ->* void");
-    isSubtype("() ->* int*", "() ->* int*");
-    isSubtype("() ->* int*", "() ->* Object*");
-    isNotSubtype("() ->* int*", "() ->* double*");
-    isNotSubtype("() ->* int*", "(int*) ->* void");
-    isNotSubtype("() ->* void", "(int*) ->* int*");
-    isNotSubtype("() ->* void", "(int*) ->* void");
-    isSubtype("(int*) ->* int*", "(int*) ->* int*");
-    isSubtype("(Object*) ->* int*", "(int*) ->* Object*");
-    isNotSubtype("(int*) ->* int*", "(double*) ->* int*");
-    isNotSubtype("() ->* int*", "(int*) ->* int*");
-    isNotSubtype("(int*) ->* int*", "(int*, int*) ->* int*");
-    isNotSubtype("(int*, int*) ->* int*", "(int*) ->* int*");
-    isNotSubtype("(() ->* void) ->* void", "((int*) ->* void) ->* void");
-    isNotSubtype("((int*) ->* void) ->* void", "(() ->* void) ->* void");
+    isSubtype("() -> int", "() -> void");
+    isNotSubtype("() -> void", "() -> int");
+    isSubtype("() -> void", "() -> void");
+    isSubtype("() -> int", "() -> int");
+    isSubtype("() -> int", "() -> Object");
+    isNotSubtype("() -> int", "() -> double");
+    isNotSubtype("() -> int", "(int) -> void");
+    isNotSubtype("() -> void", "(int) -> int");
+    isNotSubtype("() -> void", "(int) -> void");
+    isSubtype("(int) -> int", "(int) -> int");
+    isSubtype("(Object) -> int", "(int) -> Object");
+    isNotSubtype("(int) -> int", "(double) -> int");
+    isNotSubtype("() -> int", "(int) -> int");
+    isNotSubtype("(int) -> int", "(int, int) -> int");
+    isNotSubtype("(int, int) -> int", "(int) -> int");
+    isNotSubtype("(() -> void) -> void", "((int) -> void) -> void");
+    isNotSubtype("((int) -> void) -> void", "(() -> void) -> void");
 
     // Optional positional parameters.
-    isSubtype("([int*]) ->* void", "() ->* void");
-    isSubtype("([int*]) ->* void", "(int*) ->* void");
-    isNotSubtype("(int*) ->* void", "([int*]) ->* void");
-    isSubtype("([int*]) ->* void", "([int*]) ->* void");
-    isSubtype("([Object*]) ->* void", "([int*]) ->* void");
-    isNotSubtype("([int*]) ->* void", "([Object*]) ->* void");
-    isSubtype("(int*, [int*]) ->* void", "(int*) ->* void");
-    isSubtype("(int*, [int*]) ->* void", "(int*, [int*]) ->* void");
-    isNotSubtype("(int*) ->* void", "([int*]) ->* void");
-    isSubtype("([int*, int*]) ->* void", "(int*) ->* void");
-    isSubtype("([int*, int*]) ->* void", "(int*, [int*]) ->* void");
-    isNotSubtype("([int*, int*]) ->* void", "(int*, [int*, int*]) ->* void");
-    isSubtype("([int*, int*, int*]) ->* void", "(int*, [int*, int*]) ->* void");
-    isNotSubtype("([int*]) ->* void", "(double*) ->* void");
-    isNotSubtype("([int*]) ->* void", "([int*, int*]) ->* void");
-    isSubtype("([int*, int*]) ->* void", "([int*]) ->* void");
-    isSubtype("([Object*, int*]) ->* void", "([int*]) ->* void");
+    isSubtype("([int]) -> void", "() -> void");
+    isSubtype("([int]) -> void", "(int) -> void");
+    isNotSubtype("(int) -> void", "([int]) -> void");
+    isSubtype("([int]) -> void", "([int]) -> void");
+    isSubtype("([Object]) -> void", "([int]) -> void");
+    isNotSubtype("([int]) -> void", "([Object]) -> void");
+    isSubtype("(int, [int]) -> void", "(int) -> void");
+    isSubtype("(int, [int]) -> void", "(int, [int]) -> void");
+    isSubtype("([int, int]) -> void", "(int) -> void");
+    isSubtype("([int, int]) -> void", "(int, [int]) -> void");
+    isNotSubtype("([int, int]) -> void", "(int, [int, int]) -> void");
+    isSubtype("([int, int, int]) -> void", "(int, [int, int]) -> void");
+    isNotSubtype("([int]) -> void", "(double) -> void");
+    isNotSubtype("([int]) -> void", "([int, int]) -> void");
+    isSubtype("([int, int]) -> void", "([int]) -> void");
+    isSubtype("([Object, int]) -> void", "([int]) -> void");
 
     // Optional named parameters.
-    isSubtype("({int* a}) ->* void", "() ->* void");
-    isNotSubtype("({int* a}) ->* void", "(int*) ->* void");
-    isNotSubtype("(int*) ->* void", "({int* a}) ->* void");
-    isSubtype("({int* a}) ->* void", "({int* a}) ->* void");
-    isNotSubtype("({int* a}) ->* void", "({int* b}) ->* void");
-    isSubtype("({Object* a}) ->* void", "({int* a}) ->* void");
-    isNotSubtype("({int* a}) ->* void", "({Object* a}) ->* void");
-    isSubtype("(int*, {int* a}) ->* void", "(int*, {int* a}) ->* void");
-    isNotSubtype("({int* a}) ->* void", "({double* a}) ->* void");
-    isNotSubtype("({int* a}) ->* void", "({int* a, int* b}) ->* void");
-    isSubtype("({int* a, int* b}) ->* void", "({int* a}) ->* void");
-    isSubtype(
-        "({int* a, int* b, int* c}) ->* void", "({int* a, int* c}) ->* void");
-    isSubtype(
-        "({int* c, int* b, int* a}) ->* void", "({int* a, int* c}) ->* void");
-    isSubtype(
-        "({int* a, int* b, int* c}) ->* void", "({int* b, int* c}) ->* void");
-    isSubtype(
-        "({int* c, int* b, int* a}) ->* void", "({int* b, int* c}) ->* void");
-    isSubtype("({int* a, int* b, int* c}) ->* void", "({int* c}) ->* void");
-    isSubtype("({int* c, int* b, int* a}) ->* void", "({int* c}) ->* void");
+    isSubtype("({int a}) -> void", "() -> void");
+    isNotSubtype("({int a}) -> void", "(int) -> void");
+    isNotSubtype("(int) -> void", "({int a}) -> void");
+    isSubtype("({int a}) -> void", "({int a}) -> void");
+    isNotSubtype("({int a}) -> void", "({int b}) -> void");
+    isSubtype("({Object a}) -> void", "({int a}) -> void");
+    isNotSubtype("({int a}) -> void", "({Object a}) -> void");
+    isSubtype("(int, {int a}) -> void", "(int, {int a}) -> void");
+    isNotSubtype("({int a}) -> void", "({double a}) -> void");
+    isNotSubtype("({int a}) -> void", "({int a, int b}) -> void");
+    isSubtype("({int a, int b}) -> void", "({int a}) -> void");
+    isSubtype("({int a, int b, int c}) -> void", "({int a, int c}) -> void");
+    isSubtype("({int c, int b, int a}) -> void", "({int a, int c}) -> void");
+    isSubtype("({int a, int b, int c}) -> void", "({int b, int c}) -> void");
+    isSubtype("({int c, int b, int a}) -> void", "({int b, int c}) -> void");
+    isSubtype("({int a, int b, int c}) -> void", "({int c}) -> void");
+    isSubtype("({int c, int b, int a}) -> void", "({int c}) -> void");
 
     // Parsing of nullable and legacy types.
     isSubtype("int?", "int?");
-    isSubtype("int*", "int*");
+    isSubtype("int", "int");
     isSubtype("(int) ->? int", "(int) ->? int");
-    isSubtype("(int) ->* int", "(int) ->* int");
-    isSubtype("(int, int*, int?) -> int?", "(int, int*, int?) -> int?");
-    isSubtype("List<int>?", "List<int>?");
+    isSubtype("(int, int, int?) -> int?", "(int, int, int?) -> int?");
     isSubtype("List<int?>?", "List<int?>?");
     isSubtype("T & int?", "T & int?", typeParameters: "T extends Object?");
     isSubtype("T? & int?", "T? & int?", typeParameters: "T extends Object");
@@ -1224,7 +1080,6 @@
     isSubtype("(int, String)", "(int, String)?");
     isNotSubtype("(int, String)?", "(int, String)");
     isSubtype("Null", "(int, String)?");
-    isNotSubtype("Null", "(int, String)");
     isNotSubtype("(int, String)?", "Record");
 
     // Tests for extension types.
@@ -1282,7 +1137,6 @@
     isSubtype("NonNullableGenericExtensionType<Object>", "void");
     isSubtype("NonNullableGenericExtensionType<Object>", "Object?");
     isSubtype("NonNullableGenericExtensionType<Object>", "FutureOr<dynamic>");
-    isSubtype("NonNullableGenericExtensionType<Object>", "Object");
     isNotSubtype("NonNullableGenericExtensionType<Object>?", "Object");
 
     isSubtype("GenericExtensionTypeImplements<Object>", "dynamic");
@@ -1328,12 +1182,8 @@
         typeParameters: "T extends Object");
     isNotSubtype("PotentiallyNullableNestedGenericExtensionType<T>", "Object",
         typeParameters: "T extends Object");
-    isSubtype("NonNullableNestedGenericExtensionType<T>", "Object",
-        typeParameters: "T extends Object");
     isNotSubtype("PotentiallyNullableNestedGenericExtensionType<T>?", "Object",
         typeParameters: "T extends Object");
-    isNotSubtype("NonNullableNestedGenericExtensionType<T>?", "Object",
-        typeParameters: "T extends Object");
 
     isNotSubtype("dynamic", "NullableExtensionType");
     isNotSubtype("void", "NullableExtensionType");
@@ -1348,14 +1198,8 @@
     isNotSubtype("Object", "NonNullableExtensionType");
 
     isSubtype("NullableExtensionType?", "Object?");
-    isSubtype("NonNullableExtensionType", "Object?");
     isSubtype("NonNullableExtensionType?", "Object?");
 
-    isNotSubtype("NonNullableExtensionType?", "Object");
-    isNotSubtype("NonNullableGenericExtensionType<Object>?", "Object");
-    isNotSubtype("GenericExtensionTypeImplements<Object>?", "Object");
-    isNotSubtype("GenericSubExtensionTypeImplements<Object>?", "Object");
-
     isSubtype("PotentiallyNullableGenericExtensionType<Object>",
         "PotentiallyNullableGenericExtensionType<Object>");
     isSubtype("PotentiallyNullableGenericExtensionType<num>",
diff --git a/pkg/front_end/tool/bench_maker.dart b/pkg/front_end/tool/bench_maker.dart
index 50a0cb2..20a8240 100644
--- a/pkg/front_end/tool/bench_maker.dart
+++ b/pkg/front_end/tool/bench_maker.dart
@@ -347,9 +347,6 @@
       case Nullability.nullable:
         sb.write("?");
         break;
-      case Nullability.legacy:
-        sb.write("*");
-        break;
       case Nullability.undetermined:
         sb.write("%");
         break;
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index d457818..5e79b94 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -147,7 +147,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 124;
+  UInt32 formatVersion = 125;
   Byte[10] shortSdkHash;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
@@ -1527,7 +1527,7 @@
   FunctionNode function;
 }
 
-enum Nullability { nullable = 0, nonNullable = 1, neither = 2, legacy = 3, }
+enum Nullability { nullable = 0, nonNullable = 1, neither = 2, }
 
 enum Variance { unrelated = 0, covariant = 1, contravariant = 2, invariant = 3, legacyCovariant = 4, }
 
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 7947aa2..270d2e5 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -142,12 +142,7 @@
   List<CanonicalName> get linkTable => _linkTable;
 
   late Map<int, DartType?> _cachedSimpleInterfaceTypes;
-  List<FunctionType?> _voidFunctionFunctionTypesCache = [
-    null,
-    null,
-    null,
-    null
-  ];
+  List<FunctionType?> _voidFunctionFunctionTypesCache = [null, null, null];
   int _transformerFlags = 0;
   Library? _currentLibrary;
   int _componentStartOffset = 0;
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index fd5260d..81ded05 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -226,7 +226,7 @@
   /// Internal version of kernel binary format.
   /// Bump it when making incompatible changes in kernel binaries.
   /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
-  static const int BinaryFormatVersion = 124;
+  static const int BinaryFormatVersion = 125;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index 437f72d..c24e8ad 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -352,7 +352,6 @@
       case Nullability.nonNullable:
         return objectNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -383,7 +382,6 @@
       case Nullability.nonNullable:
         return boolNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -407,7 +405,6 @@
       case Nullability.nonNullable:
         return intNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -431,7 +428,6 @@
       case Nullability.nonNullable:
         return numNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -456,7 +452,6 @@
       case Nullability.nonNullable:
         return doubleNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -481,7 +476,6 @@
       case Nullability.nonNullable:
         return stringNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -506,7 +500,6 @@
       case Nullability.nonNullable:
         return listNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -531,7 +524,6 @@
       case Nullability.nonNullable:
         return setNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -556,7 +548,6 @@
       case Nullability.nonNullable:
         return mapNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -581,7 +572,6 @@
       case Nullability.nonNullable:
         return iterableNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -606,7 +596,6 @@
       case Nullability.nonNullable:
         return iteratorNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -631,7 +620,6 @@
       case Nullability.nonNullable:
         return symbolNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -655,7 +643,6 @@
       case Nullability.nonNullable:
         return typeNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -680,7 +667,6 @@
       case Nullability.nonNullable:
         return functionNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -705,7 +691,6 @@
       case Nullability.nonNullable:
         return recordNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -730,7 +715,6 @@
       case Nullability.nonNullable:
         return invocationNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -755,7 +739,6 @@
       case Nullability.nonNullable:
         return invocationMirrorNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -780,7 +763,6 @@
       case Nullability.nonNullable:
         return futureNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -805,7 +787,6 @@
       case Nullability.nonNullable:
         return stackTraceNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -830,7 +811,6 @@
       case Nullability.nonNullable:
         return streamNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -855,7 +835,6 @@
       case Nullability.nonNullable:
         return pragmaNonNullableRawType;
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -888,7 +867,6 @@
       case Nullability.nonNullable:
         return nonNullableRawType(klass);
       case Nullability.undetermined:
-      case Nullability.legacy:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
     }
@@ -964,9 +942,7 @@
     if (type is VoidType) return true;
 
     // TOP(T?) is true iff TOP(T) or OBJECT(T).
-    // TOP(T*) is true iff TOP(T) or OBJECT(T).
-    if (type.declaredNullability == Nullability.nullable ||
-        type.declaredNullability == Nullability.legacy) {
+    if (type.declaredNullability == Nullability.nullable) {
       DartType nonNullableType =
           type_algebra.unwrapNullabilityConstructor(type);
       if (!identical(type, nonNullableType)) {
@@ -1025,8 +1001,7 @@
 
     // NULL(T?) is true iff NULL(T) or BOTTOM(T).
     // NULL(T*) is true iff NULL(T) or BOTTOM(T).
-    if (type.nullability == Nullability.nullable ||
-        type.nullability == Nullability.legacy) {
+    if (type.nullability == Nullability.nullable) {
       DartType nonNullableType =
           type.withDeclaredNullability(Nullability.nonNullable);
       return isBottom(nonNullableType);
diff --git a/pkg/kernel/lib/src/ast/types.dart b/pkg/kernel/lib/src/ast/types.dart
index 54e5559..5325987 100644
--- a/pkg/kernel/lib/src/ast/types.dart
+++ b/pkg/kernel/lib/src/ast/types.dart
@@ -35,12 +35,6 @@
   /// that some types denoted by a type parameter without the '?' modifier can
   /// be something else rather than non-nullable.
   nonNullable,
-
-  /// Types in opt-out libraries are 'legacy' types.
-  ///
-  /// They are both subtypes and supertypes of the nullable and non-nullable
-  /// versions of the type.
-  legacy
 }
 
 /// Declaration of a type variable.
@@ -778,8 +772,6 @@
 
   const NeverType.nonNullable() : this.internal(Nullability.nonNullable);
 
-  const NeverType.legacy() : this.internal(Nullability.legacy);
-
   const NeverType.internal(this.declaredNullability)
       : assert(declaredNullability != Nullability.undetermined);
 
@@ -789,8 +781,6 @@
         return const NeverType.nullable();
       case Nullability.nonNullable:
         return const NeverType.nonNullable();
-      case Nullability.legacy:
-        return const NeverType.legacy();
       case Nullability.undetermined:
         throw new StateError("Unsupported nullability for 'NeverType': "
             "'${nullability}'");
@@ -808,7 +798,6 @@
         Nullability.undetermined => false,
         Nullability.nullable => false,
         Nullability.nonNullable => true,
-        Nullability.legacy => true,
       };
 
   @override
@@ -927,7 +916,6 @@
         Nullability.undetermined => false,
         Nullability.nullable => false,
         Nullability.nonNullable => true,
-        Nullability.legacy => true,
       };
 
   @override
@@ -1041,7 +1029,6 @@
         Nullability.undetermined => false,
         Nullability.nullable => false,
         Nullability.nonNullable => true,
-        Nullability.legacy => true,
       };
 
   @override
@@ -1479,7 +1466,6 @@
         Nullability.undetermined => true,
         Nullability.nullable => false,
         Nullability.nonNullable => true,
-        Nullability.legacy => true,
       };
 
   static List<DartType> _defaultTypeArguments(
@@ -1679,8 +1665,6 @@
                 rightNullability == Nullability.nonNullable) ||
             (leftNullability == Nullability.nonNullable &&
                 rightNullability == Nullability.undetermined) ||
-            (leftNullability == Nullability.legacy &&
-                rightNullability == Nullability.legacy) ||
             (leftNullability == Nullability.undetermined &&
                 rightNullability == Nullability.nonNullable) ||
             (leftNullability == Nullability.undetermined &&
@@ -1715,8 +1699,7 @@
             // inference/infer_types_on_loop_indices_for_each_loop
             // inference/infer_types_on_loop_indices_for_each_loop_async
             // replicated in nnbd_mixed/type_parameter_nullability
-            (leftNullability == Nullability.legacy &&
-                rightNullability == Nullability.nonNullable) ||
+            (rightNullability == Nullability.nonNullable) ||
             // pkg/front_end/test/incremental_hello_test
             // pkg/front_end/tool/cfe_perf_test
             // replicated in nnbd_mixed/type_parameter_nullability
@@ -1727,20 +1710,17 @@
             //
             // pkg/front_end/test/types/kernel_type_parser_test
             // pkg/front_end/test/types/cfe_types_test
-            (leftNullability == Nullability.legacy &&
-                rightNullability == Nullability.nullable) ||
+            (rightNullability == Nullability.nullable) ||
             // pkg/front_end/test/types/kernel_type_parser_test
             // pkg/front_end/test/types/cfe_types_test
             (leftNullability == Nullability.nonNullable &&
                 rightNullability == Nullability.nullable) ||
             // pkg/front_end/test/types/kernel_type_parser_test
             // pkg/front_end/test/types/cfe_types_test
-            (leftNullability == Nullability.undetermined &&
-                rightNullability == Nullability.legacy) ||
+            (leftNullability == Nullability.undetermined) ||
             // pkg/kernel/test/clone_test
             // The legacy nullability is due to RHS being InvalidType.
-            (leftNullability == Nullability.nonNullable &&
-                rightNullability == Nullability.legacy),
+            (leftNullability == Nullability.nonNullable),
         "Unexpected nullabilities for ${left} & ${right}: "
         "leftNullability = ${leftNullability}, "
         "rightNullability = ${rightNullability}.");
@@ -1842,8 +1822,6 @@
                 rhsNullability == Nullability.nonNullable) ||
             (lhsNullability == Nullability.nonNullable &&
                 rhsNullability == Nullability.undetermined) ||
-            (lhsNullability == Nullability.legacy &&
-                rhsNullability == Nullability.legacy) ||
             (lhsNullability == Nullability.undetermined &&
                 rhsNullability == Nullability.nonNullable) ||
             (lhsNullability == Nullability.undetermined &&
@@ -1875,8 +1853,7 @@
             // inference/constructors_infer_from_arguments_factory
             // inference/infer_types_on_loop_indices_for_each_loop
             // inference/infer_types_on_loop_indices_for_each_loop_async
-            (lhsNullability == Nullability.legacy &&
-                rhsNullability == Nullability.nonNullable) ||
+            (rhsNullability == Nullability.nonNullable) ||
             // pkg/front_end/test/incremental_hello_test
             // pkg/front_end/tool/cfe_perf_test
             // pkg/front_end/test/incremental_hello_test
@@ -1889,8 +1866,7 @@
 
             // pkg/front_end/test/types/kernel_type_parser_test
             // pkg/front_end/test/types/cfe_types_test
-            (lhsNullability == Nullability.undetermined &&
-                rhsNullability == Nullability.legacy) ||
+            (lhsNullability == Nullability.undetermined) ||
             // pkg/front_end/test/types/kernel_type_parser_test
             // pkg/front_end/test/types/cfe_types_test
             (lhsNullability == Nullability.nonNullable &&
@@ -1906,12 +1882,11 @@
     //
     // The code below uses the following extension of the table function:
     //
-    // | LHS \ RHS |  !  |  ?  |  *  |  %  |
-    // |-----------|-----|-----|-----|-----|
-    // |     !     |  !  |  !  |  !  |  !  |
-    // |     ?     | (!) | (?) |  *  | (%) |
-    // |     *     | (*) |  *  |  *  |  %  |
-    // |     %     |  !  |  %  |  %  |  %  |
+    // | LHS \ RHS |  !  |  ?  |  %  |
+    // |-----------|-----|-----|-----|
+    // |     !     |  !  |  !  |  !  |
+    // |     ?     | (!) | (?) | (%) |
+    // |     %     |  !  |  %  |  %  |
 
     if (lhsNullability == Nullability.nullable &&
         rhsNullability == Nullability.nonNullable) {
@@ -1923,11 +1898,6 @@
       return Nullability.nullable;
     }
 
-    if (lhsNullability == Nullability.legacy &&
-        rhsNullability == Nullability.nonNullable) {
-      return Nullability.legacy;
-    }
-
     if (lhsNullability == Nullability.nullable &&
         rhsNullability == Nullability.undetermined) {
       return Nullability.undetermined;
@@ -1963,7 +1933,8 @@
       return Nullability.undetermined;
     }
 
-    return Nullability.legacy;
+    throw new StateError("Unsupported combination '${lhsNullability}' (LHS) "
+        "and '${rhsNullability}' (RHS).");
   }
 
   @override
@@ -2230,7 +2201,6 @@
         Nullability.undetermined => false,
         Nullability.nullable => false,
         Nullability.nonNullable => true,
-        Nullability.legacy => true,
       };
 
   @override
diff --git a/pkg/kernel/lib/src/legacy_erasure.dart b/pkg/kernel/lib/src/legacy_erasure.dart
deleted file mode 100644
index d70307f..0000000
--- a/pkg/kernel/lib/src/legacy_erasure.dart
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import '../ast.dart';
-import 'replacement_visitor.dart';
-
-/// Returns legacy erasure of [type], that is, the type in which all nnbd
-/// nullabilities have been replaced with legacy nullability, and all required
-/// named parameters are not required.
-DartType legacyErasure(DartType type) {
-  return rawLegacyErasure(type) ?? type;
-}
-
-/// Returns legacy erasure of [type], that is, the type in which all nnbd
-/// nullabilities have been replaced with legacy nullability, and all required
-/// named parameters are not required.
-///
-/// Returns `null` if the type wasn't changed.
-DartType? rawLegacyErasure(DartType type) {
-  return type.accept1(const _LegacyErasure(), Variance.covariant);
-}
-
-/// Returns legacy erasure of [supertype], that is, the type in which all nnbd
-/// nullabilities have been replaced with legacy nullability, and all required
-/// named parameters are not required.
-Supertype legacyErasureSupertype(Supertype supertype) {
-  if (supertype.typeArguments.isEmpty) {
-    return supertype;
-  }
-  List<DartType>? newTypeArguments;
-  for (int i = 0; i < supertype.typeArguments.length; i++) {
-    DartType typeArgument = supertype.typeArguments[i];
-    DartType? newTypeArgument =
-        typeArgument.accept1(const _LegacyErasure(), Variance.covariant);
-    if (newTypeArgument != null) {
-      newTypeArguments ??= supertype.typeArguments.toList(growable: false);
-      newTypeArguments[i] = newTypeArgument;
-    }
-  }
-  if (newTypeArguments != null) {
-    return new Supertype(supertype.classNode, newTypeArguments);
-  }
-  return supertype;
-}
-
-/// Visitor that replaces all nnbd nullabilities with legacy nullabilities and
-/// all required named parameters with optional named parameters.
-///
-/// The visitor returns `null` if the type wasn't changed.
-class _LegacyErasure extends ReplacementVisitor {
-  const _LegacyErasure();
-
-  @override
-  Nullability? visitNullability(DartType node) {
-    if (node.declaredNullability != Nullability.legacy) {
-      return Nullability.legacy;
-    }
-    return null;
-  }
-
-  @override
-  NamedType? createNamedType(NamedType node, DartType? newType) {
-    if (node.isRequired || newType != null) {
-      return new NamedType(node.name, newType ?? node.type, isRequired: false);
-    }
-    return null;
-  }
-
-  @override
-  DartType visitNeverType(NeverType node, Variance variance) {
-    return const NullType();
-  }
-}
diff --git a/pkg/kernel/lib/src/nnbd_top_merge.dart b/pkg/kernel/lib/src/nnbd_top_merge.dart
index 0c8afa7..76fa0e7 100644
--- a/pkg/kernel/lib/src/nnbd_top_merge.dart
+++ b/pkg/kernel/lib/src/nnbd_top_merge.dart
@@ -42,10 +42,6 @@
   Nullability? mergeNullability(Nullability a, Nullability b) {
     if (a == b) {
       return a;
-    } else if (a == Nullability.legacy) {
-      return b;
-    } else if (b == Nullability.legacy) {
-      return a;
     }
     return null;
   }
@@ -96,22 +92,4 @@
     }
     return super.visitDynamicType(a, b);
   }
-
-  @override
-  DartType? visitNeverType(NeverType a, DartType b) {
-    if (a.nullability == Nullability.legacy && b is NullType) {
-      // NNBD_TOP_MERGE(Never*, Null) = Null
-      return const NullType();
-    }
-    return super.visitNeverType(a, b);
-  }
-
-  @override
-  DartType? visitNullType(NullType a, DartType b) {
-    if (b is NeverType && b.nullability == Nullability.legacy) {
-      // NNBD_TOP_MERGE(Null, Never*) = Null
-      return const NullType();
-    }
-    return super.visitNullType(a, b);
-  }
 }
diff --git a/pkg/kernel/lib/src/norm.dart b/pkg/kernel/lib/src/norm.dart
index f57c169..26fcc18 100644
--- a/pkg/kernel/lib/src/norm.dart
+++ b/pkg/kernel/lib/src/norm.dart
@@ -52,8 +52,7 @@
     DartType typeArgument = node.typeArgument;
     typeArgument = typeArgument.accept1(this, variance) ?? typeArgument;
     if (coreTypes.isTop(typeArgument)) {
-      assert(typeArgument.nullability == Nullability.nullable ||
-          typeArgument.nullability == Nullability.legacy);
+      assert(typeArgument.nullability == Nullability.nullable);
       // [typeArgument] is nullable because it's a top type.  No need to unite
       // the nullabilities of [node] and [typeArgument].
       return typeArgument;
diff --git a/pkg/kernel/lib/src/printer.dart b/pkg/kernel/lib/src/printer.dart
index 496bf72..16f2479 100644
--- a/pkg/kernel/lib/src/printer.dart
+++ b/pkg/kernel/lib/src/printer.dart
@@ -329,8 +329,7 @@
             Uri uri = type.classNode.enclosingLibrary.importUri;
             return uri.isScheme('dart') &&
                 uri.path == 'core' &&
-                (type.nullability == Nullability.legacy ||
-                    type.nullability == Nullability.nullable);
+                type.nullability == Nullability.nullable;
           }
           return false;
         }
@@ -367,8 +366,7 @@
             Uri uri = type.classNode.enclosingLibrary.importUri;
             return uri.isScheme('dart') &&
                 uri.path == 'core' &&
-                (type.nullability == Nullability.legacy ||
-                    type.nullability == Nullability.nullable);
+                type.nullability == Nullability.nullable;
           }
           return false;
         }
diff --git a/pkg/kernel/lib/src/standard_bounds.dart b/pkg/kernel/lib/src/standard_bounds.dart
index c8dcd0d..98dc7c9 100644
--- a/pkg/kernel/lib/src/standard_bounds.dart
+++ b/pkg/kernel/lib/src/standard_bounds.dart
@@ -66,33 +66,6 @@
           when tClassNode == coreTypes.objectClass:
         return false;
 
-      // MORETOP(S*, T*) = MORETOP(S, T).
-      case (
-          DartType(declaredNullability: Nullability.legacy),
-          DartType(declaredNullability: Nullability.legacy)
-        ):
-        DartType nonNullableS =
-            s.withDeclaredNullability(Nullability.nonNullable);
-        assert(!identical(s, nonNullableS));
-        DartType nonNullableT =
-            t.withDeclaredNullability(Nullability.nonNullable);
-        assert(!identical(t, nonNullableT));
-        return moretop(nonNullableS, nonNullableT);
-
-      // MORETOP(S, T*) = true.
-      case (
-          DartType(declaredNullability: Nullability.nonNullable),
-          DartType(declaredNullability: Nullability.legacy)
-        ):
-        return true;
-
-      // MORETOP(S*, T) = false.
-      case (
-          DartType(declaredNullability: Nullability.legacy),
-          DartType(declaredNullability: Nullability.nonNullable)
-        ):
-        return false;
-
       // MORETOP(S?, T?) == MORETOP(S, T).
       case (
           DartType(declaredNullability: Nullability.nullable),
@@ -120,20 +93,6 @@
         ):
         return false;
 
-      // TODO(cstefantsova): Update the following after the spec is updated.
-      case (
-          DartType(declaredNullability: Nullability.nullable),
-          DartType(declaredNullability: Nullability.legacy)
-        ):
-        return true;
-
-      // TODO(cstefantsova): Update the following after the spec is updated.
-      case (
-          DartType(declaredNullability: Nullability.legacy),
-          DartType(declaredNullability: Nullability.nullable)
-        ):
-        return false;
-
       // MORETOP(FutureOr<S>, FutureOr<T>) = MORETOP(S, T).
       case (
           FutureOrType(
@@ -228,47 +187,6 @@
         ):
         return false;
 
-      // MOREBOTTOM(S*, T*) = MOREBOTTOM(S, T)
-      case (
-          DartType(declaredNullability: Nullability.legacy),
-          DartType(declaredNullability: Nullability.legacy)
-        ):
-        DartType nonNullableS =
-            s.withDeclaredNullability(Nullability.nonNullable);
-        assert(s != nonNullableS);
-        DartType nonNullableT =
-            t.withDeclaredNullability(Nullability.nonNullable);
-        assert(t != nonNullableT);
-        return morebottom(nonNullableS, nonNullableT);
-
-      // MOREBOTTOM(S, T*) = true.
-      case (
-          DartType(declaredNullability: Nullability.nonNullable),
-          DartType(declaredNullability: Nullability.legacy)
-        ):
-        return true;
-
-      // MOREBOTTOM(S*, T) = false.
-      case (
-          DartType(declaredNullability: Nullability.legacy),
-          DartType(declaredNullability: Nullability.nonNullable)
-        ):
-        return false;
-
-      // TODO(cstefantsova): Update the following after the spec is updated.
-      case (
-          DartType(declaredNullability: Nullability.nullable),
-          DartType(declaredNullability: Nullability.legacy)
-        ):
-        return true;
-
-      // TODO(cstefantsova): Update the following after the spec is updated.
-      case (
-          DartType(declaredNullability: Nullability.legacy),
-          DartType(declaredNullability: Nullability.nullable)
-        ):
-        return false;
-
       // MOREBOTTOM(X&S, Y&T) = MOREBOTTOM(S, T).
       case (
           IntersectionType(right: DartType sRight),
@@ -411,74 +329,30 @@
           NeverType(nullability: Nullability.nullable),
           NeverType(nullability: Nullability.nullable)
         ):
-      case (
-          NeverType(nullability: Nullability.nullable),
-          NeverType(nullability: Nullability.legacy)
-        ):
-      case (
-          NeverType(nullability: Nullability.legacy),
-          NeverType(nullability: Nullability.nullable)
-        ):
-      case (
-          NeverType(nullability: Nullability.legacy),
-          NeverType(nullability: Nullability.legacy)
-        ):
       case (_, _) when coreTypes.isNull(type1) && coreTypes.isNull(type2):
         return morebottom(type1, type2) ? type1 : type2;
       case (NullType(), DartType(declaredNullability: Nullability.nullable)):
-      case (NullType(), DartType(declaredNullability: Nullability.legacy)):
       case (
           NeverType(nullability: Nullability.nullable),
           DartType(declaredNullability: Nullability.nullable)
         ):
-      case (
-          NeverType(nullability: Nullability.nullable),
-          DartType(declaredNullability: Nullability.legacy)
-        ):
-      case (
-          NeverType(nullability: Nullability.legacy),
-          DartType(declaredNullability: Nullability.nullable)
-        ):
-      case (
-          NeverType(nullability: Nullability.legacy),
-          DartType(declaredNullability: Nullability.legacy)
-        ):
       case (_, DartType(declaredNullability: Nullability.nullable))
           when coreTypes.isNull(type1):
-      case (_, DartType(declaredNullability: Nullability.legacy))
-          when coreTypes.isNull(type1):
         return type1;
       case (NullType(), _):
       case (NeverType(nullability: Nullability.nullable), _):
-      case (NeverType(nullability: Nullability.legacy), _):
       case (_, _) when coreTypes.isNull(type1):
         return const NeverType.nonNullable();
       case (DartType(declaredNullability: Nullability.nullable), NullType()):
-      case (DartType(declaredNullability: Nullability.legacy), NullType()):
       case (
           DartType(declaredNullability: Nullability.nullable),
           NeverType(nullability: Nullability.nullable)
         ):
-      case (
-          DartType(declaredNullability: Nullability.legacy),
-          NeverType(nullability: Nullability.nullable)
-        ):
-      case (
-          DartType(declaredNullability: Nullability.nullable),
-          NeverType(nullability: Nullability.legacy)
-        ):
-      case (
-          DartType(declaredNullability: Nullability.legacy),
-          NeverType(nullability: Nullability.legacy)
-        ):
       case (DartType(declaredNullability: Nullability.nullable), _)
           when coreTypes.isNull(type2):
-      case (DartType(declaredNullability: Nullability.legacy), _)
-          when coreTypes.isNull(type2):
         return type2;
       case (_, NullType()):
       case (_, NeverType(nullability: Nullability.nullable)):
-      case (_, NeverType(nullability: Nullability.legacy)):
       case (_, _) when coreTypes.isNull(type2):
         return const NeverType.nonNullable();
 
@@ -533,12 +407,6 @@
               isType2WithoutNullabilityMarker:
         return _getStandardLowerBound(type1WithoutNullabilityMarker, type2);
       case (_, _)
-          when isLegacyTypeConstructorApplication(type1) ||
-              isLegacyTypeConstructorApplication(type2):
-        return _getStandardLowerBound(
-                type1WithoutNullabilityMarker, type2WithoutNullabilityMarker)
-            .withDeclaredNullability(Nullability.legacy);
-      case (_, _)
           when isNullableTypeConstructorApplication(type1) &&
               isNullableTypeConstructorApplication(type2):
         return _getStandardLowerBound(
@@ -747,28 +615,14 @@
           NeverType(nullability: Nullability.nullable),
           NeverType(nullability: Nullability.nullable)
         ):
-      case (
-          NeverType(nullability: Nullability.nullable),
-          NeverType(nullability: Nullability.legacy)
-        ):
-      case (
-          NeverType(nullability: Nullability.legacy),
-          NeverType(nullability: Nullability.nullable)
-        ):
-      case (
-          NeverType(nullability: Nullability.legacy),
-          NeverType(nullability: Nullability.legacy)
-        ):
       case (_, _) when coreTypes.isNull(type1) && coreTypes.isNull(type2):
         return morebottom(type1, type2) ? type2 : type1;
       case (NullType(), _):
       case (NeverType(nullability: Nullability.nullable), _):
-      case (NeverType(nullability: Nullability.legacy), _):
       case (_, _) when coreTypes.isNull(type1):
         return type2.withDeclaredNullability(Nullability.nullable);
       case (_, NullType()):
       case (_, NeverType(nullability: Nullability.nullable)):
-      case (_, NeverType(nullability: Nullability.legacy)):
       case (_, _) when coreTypes.isNull(type2):
         return type1.withDeclaredNullability(Nullability.nullable);
 
@@ -810,12 +664,6 @@
                 computeTypeWithoutNullabilityMarker(type1),
                 computeTypeWithoutNullabilityMarker(type2))
             .withDeclaredNullability(Nullability.nullable);
-      case (_, _) when isLegacyTypeConstructorApplication(type1):
-      case (_, _) when isLegacyTypeConstructorApplication(type2):
-        return _getStandardUpperBound(
-                computeTypeWithoutNullabilityMarker(type1),
-                computeTypeWithoutNullabilityMarker(type2))
-            .withDeclaredNullability(Nullability.legacy);
 
       case (TypeParameterType typeParameterType1, _):
         return _getTypeVariableStandardUpperBound(type1, type2,
diff --git a/pkg/kernel/lib/src/text_util.dart b/pkg/kernel/lib/src/text_util.dart
index 22b6c5c..7f53370 100644
--- a/pkg/kernel/lib/src/text_util.dart
+++ b/pkg/kernel/lib/src/text_util.dart
@@ -6,8 +6,6 @@
 
 String nullabilityToString(Nullability nullability) {
   switch (nullability) {
-    case Nullability.legacy:
-      return '*';
     case Nullability.nullable:
       return '?';
     case Nullability.undetermined:
diff --git a/pkg/kernel/lib/src/unaliasing.dart b/pkg/kernel/lib/src/unaliasing.dart
index 745ba3f..76c6853 100644
--- a/pkg/kernel/lib/src/unaliasing.dart
+++ b/pkg/kernel/lib/src/unaliasing.dart
@@ -5,7 +5,6 @@
 import 'package:kernel/type_algebra.dart';
 
 import '../ast.dart';
-import 'legacy_erasure.dart';
 import 'replacement_visitor.dart';
 
 /// Replaces all occurrences of [TypedefType] in [type] with the corresponding
@@ -13,8 +12,8 @@
 ///
 /// If [legacyEraseAliases] is `true`, the unaliased types will be legacy
 /// erased. This used when the [TypedefType] was used in a legacy library.
-DartType unalias(DartType type, {required bool legacyEraseAliases}) {
-  return rawUnalias(type, legacyEraseAliases: legacyEraseAliases) ?? type;
+DartType unalias(DartType type) {
+  return rawUnalias(type) ?? type;
 }
 
 /// Replaces all occurrences of [TypedefType] in [types] with the corresponding
@@ -22,11 +21,9 @@
 ///
 /// If [legacyEraseAliases] is `true`, the unaliased types will be legacy
 /// erased. This used when the [TypedefType] was used in a legacy library.
-List<DartType>? unaliasTypes(List<DartType>? types,
-    {required bool legacyEraseAliases}) {
+List<DartType>? unaliasTypes(List<DartType>? types) {
   if (types == null) return null;
-  return rawUnaliasTypes(types, legacyEraseAliases: legacyEraseAliases) ??
-      types;
+  return rawUnaliasTypes(types) ?? types;
 }
 
 /// Replaces all occurrences of [TypedefType] in [type] with the corresponding
@@ -34,12 +31,8 @@
 ///
 /// If [legacyEraseAliases] is `true`, the unaliased types will be legacy
 /// erased. This used when the [TypedefType] was used in a legacy library.
-DartType? rawUnalias(DartType type, {required bool legacyEraseAliases}) {
-  return type.accept1(
-      legacyEraseAliases
-          ? const _Unalias(legacyEraseAliases: true)
-          : const _Unalias(legacyEraseAliases: false),
-      Variance.covariant);
+DartType? rawUnalias(DartType type) {
+  return type.accept1(const _Unalias(), Variance.covariant);
 }
 
 /// Replaces all occurrences of [TypedefType] in [types] with the corresponding
@@ -47,13 +40,11 @@
 ///
 /// If [legacyEraseAliases] is `true`, the unaliased types will be legacy
 /// erased. This used when the [TypedefType] was used in a legacy library.
-List<DartType>? rawUnaliasTypes(List<DartType> types,
-    {required bool legacyEraseAliases}) {
+List<DartType>? rawUnaliasTypes(List<DartType> types) {
   List<DartType>? newTypes;
   for (int i = 0; i < types.length; i++) {
     DartType typeArgument = types[i];
-    DartType? newTypeArgument =
-        rawUnalias(typeArgument, legacyEraseAliases: legacyEraseAliases);
+    DartType? newTypeArgument = rawUnalias(typeArgument);
     if (newTypeArgument != null) {
       newTypes ??= types.toList(growable: false);
       newTypes[i] = newTypeArgument;
@@ -68,9 +59,7 @@
 /// If [legacyEraseAliases] is `true`, the unaliased types will be legacy
 /// erased. This used when the [TypedefType] was used in a legacy library.
 class _Unalias extends ReplacementVisitor {
-  final bool legacyEraseAliases;
-
-  const _Unalias({required this.legacyEraseAliases});
+  const _Unalias();
 
   @override
   DartType visitTypedefType(TypedefType node, Variance variance) {
@@ -94,18 +83,8 @@
     } else {
       result = node.unalias;
     }
-    if (node.nullability == Nullability.legacy ||
-        node.typedefNode.type!.nullability == Nullability.legacy) {
-      // The typedef is defined or used in an opt-out library so the nullability
-      // is based on the use site alone.
-      result = result.withDeclaredNullability(node.declaredNullability);
-    } else {
-      result = result.withDeclaredNullability(uniteNullabilities(
-          node.declaredNullability, result.declaredNullability));
-    }
-    if (legacyEraseAliases) {
-      result = legacyErasure(result);
-    }
+    result = result.withDeclaredNullability(uniteNullabilities(
+        node.declaredNullability, result.declaredNullability));
     return result;
   }
 }
diff --git a/pkg/kernel/lib/testing/type_parser.dart b/pkg/kernel/lib/testing/type_parser.dart
index c39c80d..36d2b29 100644
--- a/pkg/kernel/lib/testing/type_parser.dart
+++ b/pkg/kernel/lib/testing/type_parser.dart
@@ -12,9 +12,6 @@
   // Used when the type is declared with the '?' suffix.
   nullable,
 
-  // Used when the type is declared with the '*' suffix.
-  legacy,
-
   // Used when the type isn't known to be nullable or non-nullable.
   //
   // For example, the type `A` is such a type, given the declaration:
@@ -34,8 +31,6 @@
   switch (parsedNullability) {
     case ParsedNullability.nullable:
       return Nullability.nullable;
-    case ParsedNullability.legacy:
-      return Nullability.legacy;
     case ParsedNullability.undetermined:
       return Nullability.undetermined;
     case ParsedNullability.omitted:
@@ -47,8 +42,6 @@
   switch (parsedNullability) {
     case ParsedNullability.nullable:
       return '?';
-    case ParsedNullability.legacy:
-      return '*';
     case ParsedNullability.undetermined:
       return '%';
     case ParsedNullability.omitted:
@@ -463,8 +456,6 @@
       result = ParsedNullability.nullable;
     } else if (optionalAdvance("%")) {
       result = ParsedNullability.undetermined;
-    } else if (optionalAdvance("*")) {
-      result = ParsedNullability.legacy;
     }
     return result;
   }
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index b500a1e..ce719c7 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -2577,12 +2577,6 @@
 
   void writeNullability(Nullability nullability, {bool inComment = false}) {
     switch (nullability) {
-      case Nullability.legacy:
-        writeSymbol('*');
-        if (!inComment) {
-          state = WORD; // Disallow a word immediately after the '*'.
-        }
-        break;
       case Nullability.nullable:
         writeSymbol('?');
         if (!inComment) {
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 0d62966..eb4fc96 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -939,17 +939,16 @@
 /// nullability of `T?` and `int`.  The function computes the nullability for
 /// the replacement as per the following table:
 ///
-/// |  inner \ outer  |  !  |  ?  |  *  |  %  |
-/// |-----------------|-----|-----|-----|-----|
-/// |     !           |  !  |  ?  |  *  |  !  |
-/// |     ?           | N/A |  ?  |  ?  |  ?  |
-/// |     *           |  *  |  ?  |  *  |  *  |
-/// |     %           | N/A |  ?  |  *  |  %  |
+/// |  inner \ outer  |  !  |  ?  |  %  |
+/// |-----------------|-----|-----|-----|
+/// |     !           |  !  |  ?  |  !  |
+/// |     ?           | N/A |  ?  |  ?  |
+/// |     %           | N/A |  ?  |  %  |
 ///
 /// Here `!` denotes `Nullability.nonNullable`, `?` denotes
-/// `Nullability.nullable`, `*` denotes `Nullability.legacy`, and `%` denotes
-/// `Nullability.undetermined`.  The table elements marked with N/A denote the
-/// cases that should yield a type error before the substitution is performed.
+/// `Nullability.nullable`, and `%` denotes `Nullability.undetermined`.  The
+/// table elements marked with N/A denote the cases that should yield a type
+/// error before the substitution is performed.
 ///
 /// a is nonNullable:
 /// DartDocTest(
@@ -964,11 +963,6 @@
 /// )
 /// DartDocTest(
 ///   combineNullabilitiesForSubstitution(
-///     inner: Nullability.nonNullable, outer: Nullability.legacy),
-///   Nullability.legacy
-/// )
-/// DartDocTest(
-///   combineNullabilitiesForSubstitution(
 ///     inner: Nullability.nonNullable, outer: Nullability.undetermined),
 ///   Nullability.nonNullable
 /// )
@@ -981,37 +975,10 @@
 /// )
 /// DartDocTest(
 ///   combineNullabilitiesForSubstitution(
-///     inner: Nullability.nullable, outer: Nullability.legacy),
-///   Nullability.nullable
-/// )
-/// DartDocTest(
-///   combineNullabilitiesForSubstitution(
 ///     inner: Nullability.nullable, outer: Nullability.undetermined),
 ///   Nullability.nullable
 /// )
 ///
-/// a is legacy:
-/// DartDocTest(
-///   combineNullabilitiesForSubstitution(
-///     inner: Nullability.legacy, outer: Nullability.nonNullable),
-///   Nullability.legacy
-/// )
-/// DartDocTest(
-///   combineNullabilitiesForSubstitution(
-///     inner: Nullability.legacy, outer: Nullability.nullable),
-///   Nullability.nullable
-/// )
-/// DartDocTest(
-///   combineNullabilitiesForSubstitution(
-///     inner: Nullability.legacy, outer: Nullability.legacy),
-///   Nullability.legacy
-/// )
-/// DartDocTest(
-///   combineNullabilitiesForSubstitution(
-///     inner: Nullability.legacy, outer: Nullability.undetermined),
-///   Nullability.legacy
-/// )
-///
 /// a is undetermined:
 /// DartDocTest(
 ///   combineNullabilitiesForSubstitution(
@@ -1020,11 +987,6 @@
 /// )
 /// DartDocTest(
 ///   combineNullabilitiesForSubstitution(
-///     inner: Nullability.undetermined, outer: Nullability.legacy),
-///   Nullability.legacy
-/// )
-/// DartDocTest(
-///   combineNullabilitiesForSubstitution(
 ///     inner: Nullability.undetermined, outer: Nullability.undetermined),
 ///   Nullability.undetermined
 /// )
@@ -1034,22 +996,17 @@
   // with whatever is easier to implement.  In this implementation, we extend
   // the table function as follows:
   //
-  // |  inner  \  outer  |  !  |  ?  |  *  |  %  |
+  // |  inner  \  outer  |  !  |  ?  |  %  |
   // |-----------|-----|-----|-----|-----|
-  // |     !     |  !  |  ?  |  *  |  !  |
-  // |     ?     |  ?  |  ?  |  ?  |  ?  |
-  // |     *     |  *  |  ?  |  *  |  *  |
-  // |     %     |  %  |  ?  |  *  |  %  |
+  // |     !     |  !  |  ?  |  !  |
+  // |     ?     |  ?  |  ?  |  ?  |
+  // |     %     |  %  |  ?  |  %  |
   //
 
   if (inner == Nullability.nullable || outer == Nullability.nullable) {
     return Nullability.nullable;
   }
 
-  if (inner == Nullability.legacy || outer == Nullability.legacy) {
-    return Nullability.legacy;
-  }
-
   return inner;
 }
 
@@ -1749,9 +1706,6 @@
   if (a == Nullability.nullable || b == Nullability.nullable) {
     return Nullability.nullable;
   }
-  if (a == Nullability.legacy || b == Nullability.legacy) {
-    return Nullability.legacy;
-  }
   if (a == Nullability.undetermined || b == Nullability.undetermined) {
     return Nullability.undetermined;
   }
@@ -1765,9 +1719,6 @@
   if (a == Nullability.undetermined || b == Nullability.undetermined) {
     return Nullability.undetermined;
   }
-  if (a == Nullability.legacy || b == Nullability.legacy) {
-    return Nullability.legacy;
-  }
   return Nullability.nullable;
 }
 
@@ -2188,21 +2139,18 @@
   @override
   bool visitFunctionType(FunctionType node) {
     assert(node.declaredNullability != Nullability.undetermined);
-    return node.declaredNullability == Nullability.nullable ||
-        node.declaredNullability == Nullability.legacy;
+    return node.declaredNullability == Nullability.nullable;
   }
 
   @override
   bool visitRecordType(RecordType node) {
     assert(node.declaredNullability != Nullability.undetermined);
-    return node.declaredNullability == Nullability.nullable ||
-        node.declaredNullability == Nullability.legacy;
+    return node.declaredNullability == Nullability.nullable;
   }
 
   @override
   bool visitFutureOrType(FutureOrType node) {
-    if (node.declaredNullability == Nullability.nullable ||
-        node.declaredNullability == Nullability.legacy) {
+    if (node.declaredNullability == Nullability.nullable) {
       return true;
     }
     return false;
@@ -2211,14 +2159,12 @@
   @override
   bool visitInterfaceType(InterfaceType node) {
     assert(node.declaredNullability != Nullability.undetermined);
-    return node.declaredNullability == Nullability.nullable ||
-        node.declaredNullability == Nullability.legacy;
+    return node.declaredNullability == Nullability.nullable;
   }
 
   @override
   bool visitExtensionType(ExtensionType node) {
-    return node.declaredNullability == Nullability.nullable ||
-        node.declaredNullability == Nullability.legacy;
+    return node.declaredNullability == Nullability.nullable;
   }
 
   @override
@@ -2227,8 +2173,7 @@
   @override
   bool visitNeverType(NeverType node) {
     assert(node.declaredNullability != Nullability.undetermined);
-    return node.declaredNullability == Nullability.nullable ||
-        node.declaredNullability == Nullability.legacy;
+    return node.declaredNullability == Nullability.nullable;
   }
 
   @override
@@ -2250,8 +2195,7 @@
   @override
   bool visitTypedefType(TypedefType node) {
     assert(node.declaredNullability != Nullability.undetermined);
-    return node.declaredNullability == Nullability.nullable ||
-        node.declaredNullability == Nullability.legacy;
+    return node.declaredNullability == Nullability.nullable;
   }
 
   @override
@@ -2277,31 +2221,6 @@
       type is! InvalidType;
 }
 
-/// Returns true if [type] is an application of the legacy type constructor.
-///
-/// A type is considered an application of the legacy type constructor if it was
-/// declared within a legacy library and is not one of exempt types, such as
-/// dynamic or void.
-bool isLegacyTypeConstructorApplication(DartType type) {
-  if (type is TypeParameterType) {
-    // The legacy nullability is considered an application of the legacy
-    // nullability constructor if it doesn't match the default nullability
-    // of the type-parameter type for the library.
-    return type.declaredNullability == Nullability.legacy &&
-        !isTypeParameterTypeWithoutNullabilityMarker(type);
-  } else if (type is StructuralParameterType) {
-    // The legacy nullability is considered an application of the legacy
-    // nullability constructor if it doesn't match the default nullability
-    // of the type-parameter type for the library.
-    return type.declaredNullability == Nullability.legacy &&
-        !isStructuralParameterTypeWithoutNullabilityMarker(type);
-  } else if (type is InvalidType) {
-    return false;
-  } else {
-    return type.declaredNullability == Nullability.legacy;
-  }
-}
-
 /// Recalculates and updates nullabilities of the bounds in [typeParameters].
 ///
 /// The procedure is intended to be used on type parameters that are in the
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index f3bbd3e..712cc9e 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -1673,8 +1673,7 @@
         node is VoidType ||
         node is InterfaceType &&
             isObjectClass(node.classNode) &&
-            (node.nullability == Nullability.nullable ||
-                node.nullability == Nullability.legacy) ||
+            node.nullability == Nullability.nullable ||
         node is FutureOrType && isTopType(node.typeArgument);
   }
 
@@ -1685,11 +1684,6 @@
 
   @override
   void defaultDartType(DartType node) {
-    if (!inConstant && node.nullability == Nullability.legacy) {
-      problem(localContext,
-          "Unexpected appearance of the legacy type $node outside a constant.",
-          origin: remoteContext);
-    }
     if (!AllowedTypes.isAllowed(node, inConstant: inConstant)) {
       final TreeNode? localContext = this.localContext;
       final TreeNode? remoteContext = this.remoteContext;
diff --git a/pkg/kernel/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
index cffafb3..f9b8236 100644
--- a/pkg/kernel/test/class_hierarchy_test.dart
+++ b/pkg/kernel/test/class_hierarchy_test.dart
@@ -341,8 +341,8 @@
             name, coreTypes.objectNullableRawType, const DynamicType()))
         .toList();
     var typeParameterTypes = typeParameters
-        .map(
-            (parameter) => new TypeParameterType(parameter, Nullability.legacy))
+        .map((parameter) =>
+            new TypeParameterType(parameter, Nullability.undetermined))
         .toList();
     var supertype =
         extends_ != null ? extends_(typeParameterTypes) : objectSuper;
@@ -1344,11 +1344,11 @@
 class B<T? = dynamic> extends self::A<self::B::T%, core::bool> {}
 ''');
 
-    var b_int = new InterfaceType(b, Nullability.legacy, [int]);
+    var b_int = new InterfaceType(b, Nullability.nonNullable, [int]);
     expect(hierarchy.getInterfaceTypeAsInstanceOfClass(b_int, a),
-        new InterfaceType(a, Nullability.legacy, [int, bool]));
+        new InterfaceType(a, Nullability.nonNullable, [int, bool]));
     expect(hierarchy.getInterfaceTypeAsInstanceOfClass(b_int, objectClass),
-        new InterfaceType(objectClass, Nullability.legacy));
+        new InterfaceType(objectClass, Nullability.nonNullable));
   }
 
   void _assertOverridePairs(Class class_, List<String> expected) {
diff --git a/pkg/kernel/test/dart_type_equivalence_test.dart b/pkg/kernel/test/dart_type_equivalence_test.dart
index 369b3dd..95c2cae 100644
--- a/pkg/kernel/test/dart_type_equivalence_test.dart
+++ b/pkg/kernel/test/dart_type_equivalence_test.dart
@@ -45,30 +45,26 @@
   // Top types.
   areEqual("dynamic", "dynamic");
   notEqual("dynamic", "Object?");
-  notEqual("dynamic", "Object*");
+  notEqual("dynamic", "Object");
   notEqual("dynamic", "void");
   areEqual("Object?", "Object?");
-  notEqual("Object?", "Object*");
+  notEqual("Object?", "Object");
   notEqual("Object?", "void");
-  areEqual("Object*", "Object*");
-  notEqual("Object*", "void");
+  areEqual("Object", "Object");
+  notEqual("Object", "void");
   areEqual("void", "void");
   notEqual("FutureOr<dynamic>", "void");
-  notEqual("FutureOr<FutureOr<Object?>>", "Object*");
-  notEqual("FutureOr<FutureOr<FutureOr<Object*>?>>?", "dynamic");
+  notEqual("FutureOr<FutureOr<Object?>>", "Object");
+  notEqual("FutureOr<FutureOr<FutureOr<Object>?>>?", "dynamic");
   notEqual("FutureOr<Object?>", "FutureOr<Object?>?");
   notEqual("FutureOr<FutureOr<Object?>>", "FutureOr<FutureOr<Object?>?>?");
   notEqual("FutureOr<FutureOr<Object?>>", "FutureOr<FutureOr<dynamic>?>?");
 
   areEqual("dynamic", "Object?", equateTopTypes: true);
-  areEqual("dynamic", "Object*", equateTopTypes: true);
   areEqual("dynamic", "void", equateTopTypes: true);
-  areEqual("Object?", "Object*", equateTopTypes: true);
   areEqual("Object?", "void", equateTopTypes: true);
-  areEqual("Object*", "void", equateTopTypes: true);
   areEqual("FutureOr<dynamic>", "void", equateTopTypes: true);
-  areEqual("FutureOr<FutureOr<Object?>>", "Object*", equateTopTypes: true);
-  areEqual("FutureOr<FutureOr<FutureOr<Object*>?>>?", "dynamic",
+  areEqual("FutureOr<FutureOr<FutureOr<Object>?>>?", "dynamic",
       equateTopTypes: true);
   areEqual("FutureOr<Object?>", "FutureOr<Object?>?", equateTopTypes: true);
   areEqual("FutureOr<FutureOr<Object?>>", "FutureOr<FutureOr<Object?>?>?",
@@ -76,7 +72,6 @@
   areEqual("FutureOr<FutureOr<Object?>>", "FutureOr<FutureOr<dynamic>?>?",
       equateTopTypes: true);
 
-  areEqual("Object?", "Object*", ignoreAllNullabilities: true);
   areEqual("FutureOr<Object?>", "FutureOr<Object?>?",
       ignoreAllNullabilities: true);
   areEqual("FutureOr<FutureOr<Object?>>", "FutureOr<FutureOr<Object?>?>?",
diff --git a/pkg/kernel/test/flatten_test.dart b/pkg/kernel/test/flatten_test.dart
index 9950653..2ea414d 100644
--- a/pkg/kernel/test/flatten_test.dart
+++ b/pkg/kernel/test/flatten_test.dart
@@ -16,45 +16,30 @@
   const Test('dynamic', 'dynamic'),
   const Test('bool', 'bool'),
   const Test('bool?', 'bool?'),
-  const Test('bool*', 'bool*'),
   const Test('List<bool>', 'List<bool>'),
   const Test('List<bool>?', 'List<bool>?'),
-  const Test('List<bool>*', 'List<bool>*'),
   const Test('FutureOr<bool>', 'bool'),
   const Test('FutureOr<bool>?', 'bool?'),
-  const Test('FutureOr<bool>*', 'bool*'),
-  const Test('FutureOr<bool?>*', 'bool?'),
   const Test('FutureOr<bool?>?', 'bool?'),
-  const Test('FutureOr<bool*>?', 'bool?'),
   const Test('FutureOr<Null>', 'Null'),
   const Test('FutureOr<Null>?', 'Null'),
-  const Test('FutureOr<Null>*', 'Null'),
   const Test('Future<bool>', 'bool'),
   const Test('Future<bool>?', 'bool?'),
-  const Test('Future<bool>*', 'bool*'),
   const Test('Future<bool?>', 'bool?'),
-  const Test('Future<bool*>', 'bool*'),
-  const Test('() ->* bool*', '() ->* bool*'),
-  const Test('() -> bool*', '() -> bool*'),
-  const Test('() ->? bool*', '() ->? bool*'),
-  const Test('() ->* bool', '() ->* bool'),
+  const Test('() ->? bool?', '() ->? bool?'),
+  const Test('() -> bool?', '() -> bool?'),
   const Test('() ->? bool', '() ->? bool'),
   const Test('() -> bool', '() -> bool'),
   const Test('T', 'T', 'T'),
   const Test('T?', 'T?', 'T'),
-  const Test('T*', 'T*', 'T'),
   const Test('T', 'T', 'T extends bool'),
   const Test('T?', 'T?', 'T extends bool'),
-  const Test('T*', 'T*', 'T extends bool'),
   const Test('T', 'bool', 'T extends FutureOr<bool>'),
   const Test('T?', 'bool?', 'T extends FutureOr<bool>'),
-  const Test('T*', 'bool*', 'T extends FutureOr<bool>'),
   const Test('T', 'bool', 'T extends Future<bool>'),
   const Test('T?', 'bool?', 'T extends Future<bool>'),
-  const Test('T*', 'bool*', 'T extends Future<bool>'),
   const Test('T & bool', 'T', 'T'),
   const Test('T & bool?', 'T', 'T'),
-  const Test('T & bool*', 'T', 'T'),
 };
 
 class Test {
diff --git a/pkg/kernel/test/future_value_type_test.dart b/pkg/kernel/test/future_value_type_test.dart
index 61c75d9..da7a5f8 100644
--- a/pkg/kernel/test/future_value_type_test.dart
+++ b/pkg/kernel/test/future_value_type_test.dart
@@ -16,7 +16,6 @@
   'dynamic': 'dynamic',
   'bool': 'Object?',
   'bool?': 'Object?',
-  'bool*': 'Object?',
   'List<bool>': 'Object?',
   '() -> void': 'Object?',
   '<T>(T) -> void': 'Object?',
@@ -25,46 +24,32 @@
   'X_extends_FutureOrInt': 'Object?',
   'Future<dynamic>': 'dynamic',
   'Future<dynamic>?': 'dynamic',
-  'Future<dynamic>*': 'dynamic',
   'Future<Object>': 'Object',
   'Future<Object>?': 'Object',
-  'Future<Object>*': 'Object',
   'Future<int?>': 'int?',
   'Future<int?>?': 'int?',
-  'Future<int?>*': 'int?',
   'Future<Future<int>?>': 'Future<int>?',
   'Future<Future<int>?>?': 'Future<int>?',
-  'Future<Future<int>?>*': 'Future<int>?',
   'Future<FutureOr<int>?>': 'FutureOr<int>?',
   'Future<FutureOr<int>?>?': 'FutureOr<int>?',
-  'Future<FutureOr<int>?>*': 'FutureOr<int>?',
   'Future<Null>': 'Null',
   'Future<Null>?': 'Null',
-  'Future<Null>*': 'Null',
   'Future<void>': 'void',
   'Future<void>?': 'void',
-  'Future<void>*': 'void',
   'FutureOr<dynamic>': 'dynamic',
   'FutureOr<dynamic>?': 'dynamic',
-  'FutureOr<dynamic>*': 'dynamic',
   'FutureOr<Object>': 'Object',
   'FutureOr<Object>?': 'Object',
-  'FutureOr<Object>*': 'Object',
   'FutureOr<int?>': 'int?',
   'FutureOr<int?>?': 'int?',
-  'FutureOr<int?>*': 'int?',
   'FutureOr<Future<int>?>': 'Future<int>?',
   'FutureOr<Future<int>?>?': 'Future<int>?',
-  'FutureOr<Future<int>?>*': 'Future<int>?',
   'FutureOr<FutureOr<int>?>': 'FutureOr<int>?',
   'FutureOr<FutureOr<int>?>?': 'FutureOr<int>?',
-  'FutureOr<FutureOr<int>?>*': 'FutureOr<int>?',
   'FutureOr<Null>': 'Null',
   'FutureOr<Null>?': 'Null',
-  'FutureOr<Null>*': 'Null',
   'FutureOr<void>': 'void',
   'FutureOr<void>?': 'void',
-  'FutureOr<void>*': 'void',
 };
 
 void main() {
diff --git a/pkg/kernel/test/legacy_erasure_test.dart b/pkg/kernel/test/legacy_erasure_test.dart
deleted file mode 100644
index 3831067..0000000
--- a/pkg/kernel/test/legacy_erasure_test.dart
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "package:expect/expect.dart" show Expect;
-
-import 'package:kernel/ast.dart';
-import 'package:kernel/src/legacy_erasure.dart';
-import 'package:kernel/testing/type_parser_environment.dart';
-
-const Map<String, String> data = {
-  'Null': 'Null',
-  'Never': 'Null',
-  'Never?': 'Null',
-  'void': 'void',
-  'dynamic': 'dynamic',
-  'bool': 'bool*',
-  'bool?': 'bool*',
-  'bool*': 'bool*',
-  'List<bool>': 'List<bool*>*',
-  'List<bool?>': 'List<bool*>*',
-  'List<bool*>': 'List<bool*>*',
-  'List<bool>?': 'List<bool*>*',
-  'List<bool?>?': 'List<bool*>*',
-  'List<bool*>?': 'List<bool*>*',
-  'List<bool>*': 'List<bool*>*',
-  'List<bool?>*': 'List<bool*>*',
-  'List<bool*>*': 'List<bool*>*',
-  '() ->* bool*': '() ->* bool*',
-  '() ->? bool*': '() ->* bool*',
-  '() -> bool*': '() ->* bool*',
-  '() ->* bool?': '() ->* bool*',
-  '() ->? bool?': '() ->* bool*',
-  '() -> bool?': '() ->* bool*',
-  '() ->* bool': '() ->* bool*',
-  '() ->? bool': '() ->* bool*',
-  '() -> bool': '() ->* bool*',
-  '(int*) -> void': '(int*) ->* void',
-  '(int?) -> void': '(int*) ->* void',
-  '(int) -> void': '(int*) ->* void',
-  '([int*]) -> void': '([int*]) ->* void',
-  '([int?]) -> void': '([int*]) ->* void',
-  '([int]) -> void': '([int*]) ->* void',
-  '({int* a}) -> void': '({int* a}) ->* void',
-  '({int? a}) -> void': '({int* a}) ->* void',
-  '({int a}) -> void': '({int* a}) ->* void',
-  '({required int* a}) -> void': '({int* a}) ->* void',
-  '({required int? a}) -> void': '({int* a}) ->* void',
-  '({required int a}) -> void': '({int* a}) ->* void',
-  '<T>(T) -> void': '<T extends Object*>(T) ->* void',
-  '<T>(T?) -> void': '<T extends Object*>(T*) ->* void',
-  '<T extends bool>(T) -> void': '<T extends bool*>(T) ->* void',
-  '<T extends List<T>>(T) -> void': '<T extends List<T*>*>(T) ->* void',
-};
-
-void main() {
-  Env env = new Env('');
-  data.forEach((String input, String output) {
-    DartType inputType = env.parseType(input);
-    DartType expectedOutputType = env.parseType(output);
-    DartType actualOutputType = legacyErasure(inputType);
-    print('legacyErasure($inputType) = $actualOutputType: $expectedOutputType');
-    Expect.equals(
-        expectedOutputType,
-        actualOutputType,
-        "Unexpected legacy erasure of $inputType ('$input'):\n"
-        "Expected: ${expectedOutputType} ('$output')\n"
-        "Actual: ${actualOutputType}");
-  });
-}
diff --git a/pkg/kernel/test/nnbd_top_merge_test.dart b/pkg/kernel/test/nnbd_top_merge_test.dart
index c0e204b..aae0375 100644
--- a/pkg/kernel/test/nnbd_top_merge_test.dart
+++ b/pkg/kernel/test/nnbd_top_merge_test.dart
@@ -20,10 +20,8 @@
   'Object? vs dynamic': 'Object?',
   'Object vs dynamic': null,
   'Never? vs Null': null,
-  'Never* vs Null': 'Null',
   'Never vs Null': null,
   'int? vs int?': 'int?',
-  'int? vs int*': 'int?',
   'int vs int': 'int',
   'int? vs int': null,
   'List<Object?> vs List<Object?>': 'List<Object?>',
@@ -39,35 +37,22 @@
   'List<Never?> vs List<Null>': null,
   'List<Never> vs List<Null>': null,
   'List<int?> vs List<int?>': 'List<int?>',
-  'List<int?> vs List<int*>': 'List<int?>',
   'List<int> vs List<int>': 'List<int>',
   'List<int?> vs List<int>': null,
   '() ->? void vs () ->? void': '() ->? void',
-  '() ->? void vs () ->* void': '() ->? void',
-  '() ->* void vs () ->* void': '() ->* void',
-  '() ->* void vs () -> void': '() -> void',
   '() -> void vs () -> void': '() -> void',
   '() ->? void vs () -> void': null,
   '(int?) -> void vs (int?) -> void': '(int?) -> void',
-  '(int*) -> void vs (int) -> void': '(int) -> void',
   '(int) -> void vs (int) -> void': '(int) -> void',
   '(int?) -> void vs (int) -> void': null,
   '([int?]) -> void vs ([int?]) -> void': '([int?]) -> void',
-  '([int*]) -> void vs ([int]) -> void': '([int]) -> void',
   '([int]) -> void vs ([int]) -> void': '([int]) -> void',
   '([int?]) -> void vs ([int]) -> void': null,
   '({int? a}) -> void vs ({int? a}) -> void': '({int? a}) -> void',
-  '({int* a}) -> void vs ({int a}) -> void': '({int a}) -> void',
   '({int a}) -> void vs ({int a}) -> void': '({int a}) -> void',
   '({int? a}) -> void vs ({int a}) -> void': null,
   '({required int? a}) -> void vs ({required int? a}) -> void':
       '({required int? a}) -> void',
-  '({required int? a}) -> void vs ({required int* a}) -> void':
-      '({required int? a}) -> void',
-  '({required int* a}) -> void vs ({required int* a}) -> void':
-      '({required int* a}) -> void',
-  '({required int* a}) -> void vs ({required int a}) -> void':
-      '({required int a}) -> void',
   '({required int? a}) -> void vs ({required int a}) -> void': null,
   '({int a, bool b}) -> void vs ({int a, bool b}) -> void':
       '({int a, bool b}) -> void',
diff --git a/pkg/kernel/test/non_null_test.dart b/pkg/kernel/test/non_null_test.dart
index 54b865a..0c028c6 100644
--- a/pkg/kernel/test/non_null_test.dart
+++ b/pkg/kernel/test/non_null_test.dart
@@ -14,30 +14,18 @@
   'Null': 'Never',
   'Never': 'Never',
   'Never?': 'Never',
-  'Never*': 'Never',
   'Object': 'Object',
   'Object?': 'Object',
-  'Object*': 'Object',
   'List<Object>': 'List<Object>',
   'List<Object>?': 'List<Object>',
-  'List<Object>*': 'List<Object>',
   'List<Object?>': 'List<Object?>',
   'List<Object?>?': 'List<Object?>',
-  'List<Object?>*': 'List<Object?>',
-  'List<Object*>': 'List<Object*>',
-  'List<Object*>?': 'List<Object*>',
-  'List<Object*>*': 'List<Object*>',
   'FutureOr<Null>': 'FutureOr<Null>',
   'FutureOr<dynamic>': 'FutureOr<dynamic>',
   'FutureOr<Object>': 'FutureOr<Object>',
   'FutureOr<Object>?': 'FutureOr<Object>',
-  'FutureOr<Object>*': 'FutureOr<Object>',
   'FutureOr<Object?>': 'FutureOr<Object?>',
   'FutureOr<Object?>?': 'FutureOr<Object?>',
-  'FutureOr<Object?>*': 'FutureOr<Object?>',
-  'FutureOr<Object*>': 'FutureOr<Object*>',
-  'FutureOr<Object*>?': 'FutureOr<Object*>',
-  'FutureOr<Object*>*': 'FutureOr<Object*>',
   'FutureOr<FutureOr<Object?>>': 'FutureOr<FutureOr<Object?>>',
   '(List<Object>, {required List<Object> a, List<Object> b}) -> List<Object>':
       '(List<Object>, {required List<Object> a, List<Object> b})'
@@ -45,22 +33,16 @@
   '(List<Object>, {required List<Object> a, List<Object> b}) ->? List<Object>':
       '(List<Object>, {required List<Object> a, List<Object> b})'
           ' -> List<Object>',
-  '(List<Object>, {required List<Object> a, List<Object> b}) ->* List<Object>':
-      '(List<Object>, {required List<Object> a, List<Object> b})'
-          ' -> List<Object>',
   '(List<Object>?, {required List<Object?> a, List<Object?>? b})'
           ' ->? List<Object?>':
       '(List<Object>?, {required List<Object?> a, List<Object?>? b})'
           ' -> List<Object?>',
   'X': 'X & Object',
   'X?': 'X & Object',
-  'X*': 'X & Object',
   'X_extends_Object': 'X_extends_Object',
   'X_extends_Object?': 'X_extends_Object',
-  'X_extends_Object*': 'X_extends_Object',
   'X_extends_dynamic': 'X_extends_dynamic',
   'X_extends_dynamic?': 'X_extends_dynamic',
-  'X_extends_dynamic*': 'X_extends_dynamic',
   'X & Object?': 'X & Object',
   'X & dynamic': 'X & dynamic',
   'X & Object': 'X & Object',
@@ -71,7 +53,6 @@
   'Y?': 'Y & X & Object',
   'Y_extends_dynamic': 'Y_extends_dynamic',
   'Y_extends_dynamic?': 'Y_extends_dynamic',
-  'Y_extends_dynamic*': 'Y_extends_dynamic',
   'Y_extends_dynamic & X': 'Y_extends_dynamic & X & Object',
   'Y_extends_dynamic & X_extends_dynamic?':
       'Y_extends_dynamic & X_extends_dynamic',
diff --git a/pkg/kernel/test/norm_test.dart b/pkg/kernel/test/norm_test.dart
index 8d27e77..27d1e90 100644
--- a/pkg/kernel/test/norm_test.dart
+++ b/pkg/kernel/test/norm_test.dart
@@ -12,7 +12,6 @@
   checkNormToSame('Null');
   checkNormToSame('Never');
   check('Never?', 'Null');
-  checkNormToSame('Never*');
   checkNormToSame('void');
   checkNormToSame('dynamic');
   checkNormToSame('Object?');
@@ -20,23 +19,14 @@
   check('FutureOr<void>', 'void');
   check('FutureOr<Object>', 'Object');
   check('FutureOr<Object?>', 'Object?');
-  check('FutureOr<Object*>', 'Object*');
   check('FutureOr<Never>', 'Future<Never>');
   check('FutureOr<Never?>', 'Future<Null>?');
 
-  // TODO(cstefantsova): Use the following test case instead when FutureOr can
-  // distinguish between the declared nullability and the nullability as a
-  // property.
-  //
-  //check('FutureOr<Never*>', 'Future<Never*>');
-  check('FutureOr<Never*>', 'Future<Never*>*');
-
   check('FutureOr<Null>', 'Future<Null>?');
   check('FutureOr<FutureOr<dynamic>>', 'dynamic');
   check('FutureOr<FutureOr<void>>', 'void');
   check('FutureOr<FutureOr<Object>>', 'Object');
   check('FutureOr<FutureOr<Object?>>', 'Object?');
-  check('FutureOr<FutureOr<Object*>>', 'Object*');
   check('FutureOr<FutureOr<Never>>', 'FutureOr<Future<Never>>');
 
   // TODO(cstefantsova): Use the following test case instead when FutureOr can
@@ -50,40 +40,22 @@
   // distinguish between the declared nullability and the nullability as a
   // property.
   //
-  //check('FutureOr<FutureOr<Never*>>', 'FutureOr<Future<Never*>>');
-  check('FutureOr<FutureOr<Never*>>', 'FutureOr<Future<Never*>*>*');
-
-  // TODO(cstefantsova): Use the following test case instead when FutureOr can
-  // distinguish between the declared nullability and the nullability as a
-  // property.
-  //
   //check('FutureOr<FutureOr<Null>>', 'FutureOr<Future<Null>?>');
   check('FutureOr<FutureOr<Null>>', 'FutureOr<Future<Null>?>?');
 
   checkNormToSame('bool');
   checkNormToSame('bool?');
-  checkNormToSame('bool*');
 
   checkNormToSame('List<bool>');
   checkNormToSame('List<bool?>');
-  checkNormToSame('List<bool*>');
   checkNormToSame('List<bool>?');
   checkNormToSame('List<bool?>?');
-  checkNormToSame('List<bool*>?');
-  checkNormToSame('List<bool>*');
-  checkNormToSame('List<bool?>*');
-  checkNormToSame('List<bool*>*');
   check('List<FutureOr<Object?>>', 'List<Object?>');
   check('List<T>', 'List<Never>', 'T extends Never');
   check('List<T?>', 'List<Null>', 'T extends Never');
 
-  checkNormToSame('() ->* bool*');
-  checkNormToSame('() ->? bool*');
-  checkNormToSame('() -> bool*');
-  checkNormToSame('() ->* bool?');
   checkNormToSame('() ->? bool?');
   checkNormToSame('() -> bool?');
-  checkNormToSame('() ->* bool');
   checkNormToSame('() ->? bool');
   checkNormToSame('() -> bool');
   check('() ->? List<FutureOr<Object?>>', '() ->? List<Object?>');
@@ -91,16 +63,12 @@
   check('() ->? List<T?>', '() ->? List<Null>',
       'T extends S, S extends U, U extends Never');
 
-  checkNormToSame('(int*) -> void');
   checkNormToSame('(int?) -> void');
   checkNormToSame('(int) -> void');
-  checkNormToSame('([int*]) -> void');
   checkNormToSame('([int?]) -> void');
   checkNormToSame('([int]) -> void');
-  checkNormToSame('({int* a}) -> void');
   checkNormToSame('({int? a}) -> void');
   checkNormToSame('({int a}) -> void');
-  checkNormToSame('({required int* a}) -> void');
   checkNormToSame('({required int? a}) -> void');
   checkNormToSame('({required int a}) -> void');
   check('(List<FutureOr<Object?>>) -> void', '(List<Object?>) -> void');
diff --git a/pkg/kernel/test/type_parser.dart b/pkg/kernel/test/type_parser.dart
index fb01d12..616a87d 100644
--- a/pkg/kernel/test/type_parser.dart
+++ b/pkg/kernel/test/type_parser.dart
@@ -32,7 +32,6 @@
   static const int Colon = 12;
   static const int Ampersand = 13;
   static const int QuestionMark = 14;
-  static const int Asterisk = 15;
   static const int Invalid = 100;
 }
 
@@ -98,8 +97,6 @@
     switch (character) {
       case 38:
         return Token.Ampersand;
-      case 42:
-        return Token.Asterisk;
       case 44:
         return Token.Comma;
       case 60:
@@ -144,9 +141,6 @@
       case Token.QuestionMark:
         scanToken();
         return Nullability.nullable;
-      case Token.Asterisk:
-        scanToken();
-        return Nullability.legacy;
       default:
         return defaultNullability;
     }
diff --git a/pkg/kernel/test/type_parser_test.dart b/pkg/kernel/test/type_parser_test.dart
index 8597dca..3ea6de5 100644
--- a/pkg/kernel/test/type_parser_test.dart
+++ b/pkg/kernel/test/type_parser_test.dart
@@ -12,7 +12,6 @@
 
 void main() {
   testParse("""
-() ->* void
 () ->? void
 () -> void
 (int) -> dynamic
@@ -45,13 +44,10 @@
 S & T & U
 class C;
 <E>(E) -> int & <E>(E) -> void
-C*
 C?
 C
-A<C>*
 A<C>?
 A<C>
-A<C*>
 A<C?>
 A<C>
 <T extends bool>(T) -> void
diff --git a/pkg/kernel/test/type_substitute_bounds_test.dart b/pkg/kernel/test/type_substitute_bounds_test.dart
index 116bddd..1fe6e42 100644
--- a/pkg/kernel/test/type_substitute_bounds_test.dart
+++ b/pkg/kernel/test/type_substitute_bounds_test.dart
@@ -31,7 +31,6 @@
       '(<F>(String) => int) => int'),
   testCase('<E>((T) => int) => int', {'T': bound('_', 'String')},
       '<E>((String) => int) => int'),
-  testCase('(T?) =>* String', {'T': bound('int', 'int')}, '(int?) =>* String'),
 ];
 
 class TestCase {
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 84c83f5..416892d 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -18,7 +18,7 @@
 // package:kernel/binary.md.
 
 static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
-static const uint32_t kSupportedKernelFormatVersion = 124;
+static const uint32_t kSupportedKernelFormatVersion = 125;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
@@ -216,7 +216,6 @@
   kUndetermined = 0,
   kNullable = 1,
   kNonNullable = 2,
-  kLegacy = 3,
 };
 
 // Keep in sync with package:kernel/lib/ast.dart
@@ -443,8 +442,6 @@
       case KernelNullability::kNonNullable:
       case KernelNullability::kUndetermined:
         return Nullability::kNonNullable;
-      case KernelNullability::kLegacy:
-        FATAL("Legacy nullability is not supported.");
     }
     UNREACHABLE();
   }