Build types for not simply bounded elements using dynamic type arguments.

R=brianwilkerson@google.com

Change-Id: Ia3c2d5193212a8cf58caad2323185e1ac9e31c9c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99716
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index 8ba88df..b0bdfcd 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -554,6 +554,7 @@
     node.implementsClause?.accept(this);
     node.withClause?.accept(this);
     node.members.accept(this);
+    nodesToBuildType.add(node);
 
     scope = outerScope;
     reference = outerReference;
diff --git a/pkg/analyzer/lib/src/summary2/type_builder.dart b/pkg/analyzer/lib/src/summary2/type_builder.dart
index 8db0314..2182e4e 100644
--- a/pkg/analyzer/lib/src/summary2/type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/type_builder.dart
@@ -49,6 +49,11 @@
     }
   }
 
+  void _buildElement(Element element) {
+    var node = (element as ElementImpl).linkedNode;
+    _build(node);
+  }
+
   FunctionType _buildFunctionType(
     TypeParameterList typeParameterList,
     TypeAnnotation returnTypeNode,
@@ -82,7 +87,9 @@
   }
 
   void _declaration(AstNode node) {
-    if (node is FieldFormalParameter) {
+    if (node is ClassDeclaration) {
+      _typeParameterList(node.typeParameters);
+    } else if (node is FieldFormalParameter) {
       _fieldFormalParameter(node);
     } else if (node is FunctionDeclaration) {
       var defaultReturnType = node.isSetter ? _voidType : _dynamicType;
@@ -183,19 +190,28 @@
     }
   }
 
+  List<DartType> _typeArgumentList(TypeArgumentList node) {
+    if (node == null) return null;
+
+    var argumentNodes = node.arguments;
+    var argumentTypes = List<DartType>(argumentNodes.length);
+    for (var i = 0; i < argumentNodes.length; ++i) {
+      var argumentNode = argumentNodes[i];
+      _build(argumentNode);
+      argumentTypes[i] = argumentNode.type;
+    }
+    return argumentTypes;
+  }
+
   void _typeName(TypeName node) {
     var element = node.name.staticElement;
-
-    List<DartType> typeArguments;
-    var typeArgumentList = node.typeArguments;
-    if (typeArgumentList != null) {
-      typeArguments = typeArgumentList.arguments.map((a) => a.type).toList();
-    }
-
     if (element is ClassElement) {
       if (element.isEnum) {
         node.type = InterfaceTypeImpl.explicit(element, const []);
       } else {
+        _buildElement(element);
+        var typeArguments = _typeArgumentList(node.typeArguments);
+
         var rawType = element.type;
 
         var typeParametersLength = element.typeParameters.length;
@@ -205,7 +221,12 @@
         }
 
         if (typeArguments == null) {
-          node.type = typeSystem.instantiateToBounds(rawType);
+          if (element.isSimplyBounded) {
+            node.type = typeSystem.instantiateToBounds(rawType);
+          } else {
+            typeArguments = _listOfDynamic(typeParametersLength);
+            node.type = InterfaceTypeImpl.explicit(element, typeArguments);
+          }
           return;
         }
 
@@ -216,7 +237,8 @@
         node.type = InterfaceTypeImpl.explicit(element, typeArguments);
       }
     } else if (element is GenericTypeAliasElement) {
-      _build((element as ElementImpl).linkedNode);
+      _buildElement(element);
+      var typeArguments = _typeArgumentList(node.typeArguments);
 
       var rawType = element.function.type;
 
@@ -228,9 +250,13 @@
       }
 
       if (typeArguments == null) {
-        typeArguments = typeSystem.instantiateTypeFormalsToBounds(
-          typeParameters,
-        );
+        if (element.isSimplyBounded) {
+          typeArguments = typeSystem.instantiateTypeFormalsToBounds(
+            typeParameters,
+          );
+        } else {
+          typeArguments = _listOfDynamic(typeParametersLength);
+        }
       } else if (typeArguments.length != typeParametersLength) {
         typeArguments = _listOfDynamic(typeParametersLength);
       }
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 47de718..666393d 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -1270,12 +1270,21 @@
 class C<T extends D> {}
 class D<T extends C> {}
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+notSimplyBounded class C<T extends D<dynamic>> {
+}
+notSimplyBounded class D<T extends C<dynamic>> {
+}
+''');
+    } else {
+      checkElementText(library, r'''
 notSimplyBounded class C<T extends D<dynamic>> {
 }
 notSimplyBounded class D<T extends C<D<dynamic>>> {
 }
 ''');
+    }
   }
 
   test_class_notSimplyBounded_complex_by_reference_to_cycle() async {
@@ -6872,11 +6881,19 @@
 class C<S extends num, T extends C<S, T>> {}
 C c;
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+notSimplyBounded class C<S extends num, T extends C<S, T>> {
+}
+C<dynamic, dynamic> c;
+''');
+    } else {
+      checkElementText(library, r'''
 notSimplyBounded class C<S extends num, T extends C<S, T>> {
 }
 C<num, C<num, dynamic>> c;
 ''');
+    }
   }
 
   test_instantiateToBounds_boundRefersToItself() async {
@@ -6888,7 +6905,18 @@
   var c3 = new C();
 }
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+notSimplyBounded class C<T extends C<T>> {
+}
+class B {
+  C<C<dynamic>> c3;
+}
+C<dynamic> c;
+C<C<dynamic>> c2;
+''');
+    } else {
+      checkElementText(library, r'''
 notSimplyBounded class C<T extends C<T>> {
 }
 class B {
@@ -6897,6 +6925,7 @@
 C<C<dynamic>> c;
 C<C<dynamic>> c2;
 ''');
+    }
   }
 
   test_instantiateToBounds_boundRefersToLaterTypeArgument() async {
@@ -6904,11 +6933,19 @@
 class C<T extends C<T, U>, U extends num> {}
 C c;
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+notSimplyBounded class C<T extends C<T, U>, U extends num> {
+}
+C<dynamic, dynamic> c;
+''');
+    } else {
+      checkElementText(library, r'''
 notSimplyBounded class C<T extends C<T, U>, U extends num> {
 }
 C<C<dynamic, num>, num> c;
 ''');
+    }
   }
 
   test_instantiateToBounds_functionTypeAlias_reexported() async {
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 4a036db..7f58c00 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -29,6 +29,8 @@
    */
   bool get mayCheckTypesOfLocals;
 
+  bool get useSummary2;
+
   /**
    * Add a new file with the given [name] and [content].
    */
@@ -3549,13 +3551,23 @@
 class B<T extends /*error:NOT_INSTANTIATED_BOUND*/A> {}
 B v = null;
 ''');
-    checkElementText(unit.library, r'''
+    if (useSummary2) {
+      checkElementText(unit.library, r'''
+notSimplyBounded class A<T1 extends int, T2 extends T1> {
+}
+notSimplyBounded class B<T extends A<dynamic, dynamic>> {
+}
+B<dynamic> v;
+''');
+    } else {
+      checkElementText(unit.library, r'''
 notSimplyBounded class A<T1 extends int, T2 extends T1> {
 }
 notSimplyBounded class B<T extends A<int, int>> {
 }
 B<A<int, int>> v;
 ''');
+    }
   }
 
   test_instantiateToBounds_typeName_error2() async {
@@ -3564,13 +3576,23 @@
 class B<T extends /*error:NOT_INSTANTIATED_BOUND*/A> {}
 B v = null;
 ''');
-    checkElementText(unit.library, r'''
+    if (useSummary2) {
+      checkElementText(unit.library, r'''
+notSimplyBounded class A<T1 extends T2, T2 extends int> {
+}
+notSimplyBounded class B<T extends A<dynamic, dynamic>> {
+}
+B<dynamic> v;
+''');
+    } else {
+      checkElementText(unit.library, r'''
 notSimplyBounded class A<T1 extends T2, T2 extends int> {
 }
 notSimplyBounded class B<T extends A<int, int>> {
 }
 B<A<int, int>> v;
 ''');
+    }
   }
 
   test_instantiateToBounds_typeName_error3() async {
@@ -3579,13 +3601,23 @@
 class B<T extends /*error:NOT_INSTANTIATED_BOUND*/A> {}
 B v = null;
 ''');
-    checkElementText(unit.library, r'''
+    if (useSummary2) {
+      checkElementText(unit.library, r'''
+notSimplyBounded class A<T1 extends int, T2 extends List<T1>> {
+}
+notSimplyBounded class B<T extends A<dynamic, dynamic>> {
+}
+B<dynamic> v;
+''');
+    } else {
+      checkElementText(unit.library, r'''
 notSimplyBounded class A<T1 extends int, T2 extends List<T1>> {
 }
 notSimplyBounded class B<T extends A<int, List<int>>> {
 }
 B<A<int, List<int>>> v;
 ''');
+    }
   }
 
   test_instantiateToBounds_typeName_OK_hasBound_definedAfter() async {
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index 03726eb..e8be4ba 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -242,9 +242,11 @@
   AnalysisContext _context = null;
   AnalysisDriver _driver = null;
 
+  Map<String, List<Folder>> packageMap;
+
   List<String> get enabledExperiments => [];
 
-  Map<String, List<Folder>> packageMap;
+  bool get useSummary2 => _driver.useSummary2;
 
   /// Adds a file to check. The file should contain:
   ///