Fix for a new infinite cycle in InterfaceTypeImpl.substitute2().

I introduced it in https://github.com/dart-lang/sdk/commit/74d6957b4fa7c2c74004cf2a8dc15ac743841d90

R=brianwilkerson@google.com
BUG=

Review-Url: https://codereview.chromium.org/2773523002 .
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index af51d63..6f31ee6 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisEngine;
 import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/generated/utilities_collection.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
 /**
@@ -714,7 +715,8 @@
               normalParameterTypes, object.normalParameterTypes) &&
           TypeImpl.equalArrays(
               optionalParameterTypes, object.optionalParameterTypes) &&
-          _equals(namedParameterTypes, object.namedParameterTypes);
+          _equals(namedParameterTypes, object.namedParameterTypes) &&
+          TypeImpl.equalArrays(typeArguments, object.typeArguments);
     }
     return false;
   }
@@ -2003,8 +2005,12 @@
     if (argumentTypes.length == 0 || typeArguments.length == 0) {
       return this.pruned(prune);
     }
+
     List<DartType> newTypeArguments = TypeImpl.substitute(
         typeArguments, argumentTypes, parameterTypes, prune);
+    if (listsEqual(newTypeArguments, typeArguments)) {
+      return this;
+    }
 
     if (isDartAsyncFuture && newTypeArguments.isNotEmpty) {
       //
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index a466fec..4cfa5d1 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -1331,6 +1331,16 @@
     expect(result.unit.element.types.map((e) => e.name), ['A']);
   }
 
+  test_getResult_recursiveFlatten() async {
+    String content = r'''
+import 'dart:async';
+class C<T> implements Future<C<T>> {}
+''';
+    addTestFile(content);
+    // Should not throw exceptions.
+    await driver.getResult(testFile);
+  }
+
   test_getResult_sameFile_twoUris() async {
     var a = _p('/test/lib/a.dart');
     var b = _p('/test/lib/b.dart');