Use TypeEnvironment.getTypeAsInstanceOf instead of ClassHierarchy

Change-Id: I1682baeb336b8be3cb6c5874715ef8ba730561e0
Reviewed-on: https://dart-review.googlesource.com/c/88803
Commit-Queue: Peter von der Ahé <ahe@google.com>
Commit-Queue: Kevin Millikin <kmillikin@google.com>
Auto-Submit: Peter von der Ahé <ahe@google.com>
Reviewed-by: Kevin Millikin <kmillikin@google.com>
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 47129b6..877ff1f 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -148,7 +148,7 @@
     }
     if (type is ir.InterfaceType) {
       ir.InterfaceType upcastType =
-          typeEnvironment.hierarchy.getTypeAsInstanceOf(type, superclass);
+          typeEnvironment.getTypeAsInstanceOf(type, superclass);
       if (upcastType != null) return upcastType;
     } else if (type is ir.BottomType) {
       return superclass.bottomType;
@@ -604,8 +604,8 @@
       if (declaringClass.typeParameters.isEmpty) {
         resultType = node.interfaceTarget.getterType;
       } else {
-        ir.DartType receiver = typeEnvironment.hierarchy
-            .getTypeAsInstanceOf(typeEnvironment.thisType, declaringClass);
+        ir.DartType receiver = typeEnvironment.getTypeAsInstanceOf(
+            typeEnvironment.thisType, declaringClass);
         resultType = ir.Substitution.fromInterfaceType(receiver)
             .substituteType(node.interfaceTarget.getterType);
       }
@@ -637,8 +637,8 @@
       returnType = const ir.DynamicType();
     } else {
       ir.Class superclass = node.interfaceTarget.enclosingClass;
-      ir.InterfaceType receiverType = typeEnvironment.hierarchy
-          .getTypeAsInstanceOf(typeEnvironment.thisType, superclass);
+      ir.InterfaceType receiverType = typeEnvironment.getTypeAsInstanceOf(
+          typeEnvironment.thisType, superclass);
       returnType = ir.Substitution.fromInterfaceType(receiverType)
           .substituteType(node.interfaceTarget.function.returnType);
       returnType = ir.Substitution.fromPairs(
diff --git a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
index b0f3d1e..b61d006 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
@@ -1244,8 +1244,8 @@
   /// Determines the appropriate substitution to translate type parameters
   /// mentioned in the given [candidate] to type parameters on [class_].
   Substitution _substitutionFor(Procedure candidate, Class class_) {
-    return Substitution.fromInterfaceType(_typeEnvironment.hierarchy
-        .getTypeAsInstanceOf(class_.thisType, candidate.enclosingClass));
+    return Substitution.fromInterfaceType(_typeEnvironment.getTypeAsInstanceOf(
+        class_.thisType, candidate.enclosingClass));
   }
 
   /// Executes [callback] once for each uniquely named member of [candidates].
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
index 23402c5..91df6f16 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
@@ -181,7 +181,7 @@
     // above is irrelevant; we just need to find the matched superclass,
     // substitute, and then iterate through type variables.
     var matchingSupertypeOfSubtype =
-        environment.hierarchy.getTypeAsInstanceOf(subtype, supertype.classNode);
+        environment.getTypeAsInstanceOf(subtype, supertype.classNode);
     if (matchingSupertypeOfSubtype == null) return false;
     for (int i = 0; i < supertype.classNode.typeParameters.length; i++) {
       if (!_isSubtypeMatch(matchingSupertypeOfSubtype.typeArguments[i],
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 4f16b8a..0cf92d1 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -2190,7 +2190,7 @@
       type = (type as TypeParameterType).parameter.bound;
     }
     if (type is InterfaceType) {
-      var upcastType = types.hierarchy.getTypeAsInstanceOf(type, superclass);
+      var upcastType = types.getTypeAsInstanceOf(type, superclass);
       if (upcastType != null) return upcastType;
     } else if (type is BottomType) {
       return superclass.bottomType;
@@ -2558,8 +2558,7 @@
     if (declaringClass.typeParameters.isEmpty) {
       return interfaceTarget.getterType;
     }
-    var receiver =
-        types.hierarchy.getTypeAsInstanceOf(types.thisType, declaringClass);
+    var receiver = types.getTypeAsInstanceOf(types.thisType, declaringClass);
     return Substitution.fromInterfaceType(receiver)
         .substituteType(interfaceTarget.getterType);
   }
@@ -2881,8 +2880,7 @@
   DartType getStaticType(TypeEnvironment types) {
     if (interfaceTarget == null) return const DynamicType();
     Class superclass = interfaceTarget.enclosingClass;
-    var receiverType =
-        types.hierarchy.getTypeAsInstanceOf(types.thisType, superclass);
+    var receiverType = types.getTypeAsInstanceOf(types.thisType, superclass);
     var returnType = Substitution.fromInterfaceType(receiverType)
         .substituteType(interfaceTarget.function.returnType);
     return Substitution.fromPairs(
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index fe0a51b..09c9406 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -82,8 +82,7 @@
       // we aren't concerned with it.  If a class implements multiple
       // instantiations of Future, getTypeAsInstanceOf is responsible for
       // picking the least one in the sense required by the spec.
-      InterfaceType future =
-          hierarchy.getTypeAsInstanceOf(type, coreTypes.futureClass);
+      InterfaceType future = getTypeAsInstanceOf(type, coreTypes.futureClass);
       if (future != null) {
         return future.typeArguments[0];
       }
@@ -143,6 +142,11 @@
     if (type1 == doubleType || type2 == doubleType) return doubleType;
     return numType;
   }
+
+  @override
+  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) {
+    return hierarchy.getTypeAsInstanceOf(type, superclass);
+  }
 }
 
 /// The part of [TypeEnvironment] that deals with subtype tests.
@@ -152,11 +156,12 @@
   InterfaceType get objectType;
   InterfaceType get nullType;
   InterfaceType get rawFunctionType;
-  ClassHierarchy get hierarchy;
   Class get futureOrClass;
   InterfaceType futureType(DartType type);
   bool get legacyMode;
 
+  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass);
+
   /// Determines if the given type is at the bottom of the type hierarchy.  May
   /// be overridden in subclasses.
   bool isBottom(DartType type) =>
@@ -206,8 +211,7 @@
     }
 
     if (subtype is InterfaceType && supertype is InterfaceType) {
-      var upcastType =
-          hierarchy.getTypeAsInstanceOf(subtype, supertype.classNode);
+      var upcastType = getTypeAsInstanceOf(subtype, supertype.classNode);
       if (upcastType == null) return false;
       for (int i = 0; i < upcastType.typeArguments.length; ++i) {
         // Termination: the 'supertype' parameter decreases in size.
diff --git a/pkg/kernel/test/type_subtype_test.dart b/pkg/kernel/test/type_subtype_test.dart
index d97c690..753e525 100644
--- a/pkg/kernel/test/type_subtype_test.dart
+++ b/pkg/kernel/test/type_subtype_test.dart
@@ -200,11 +200,16 @@
   Class futureClass;
   Class futureOrClass;
   LazyTypeEnvironment environment;
-  bool legacyMode = true;
+  bool legacyMode = false;
 
   InterfaceType futureType(DartType type) =>
       new InterfaceType(futureClass, [type]);
 
+  @override
+  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) {
+    return hierarchy.getTypeAsInstanceOf(type, superclass);
+  }
+
   MockSubtypeTester(
       this.hierarchy,
       this.objectType,