Instantiate to bounds when resolving type names.

R=brianwilkerson@google.com

Change-Id: I55ea6339b5b949f986f7e6becc60c0328496489e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99188
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index b5623fb..b8a1a61 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -245,7 +245,7 @@
       library.resolveTypes(nodesToBuildType);
     }
     computeSimplyBounded(bundleContext, builders.values);
-    TypeBuilder(linkingBundleContext).build(nodesToBuildType);
+    TypeBuilder(typeSystem).build(nodesToBuildType);
   }
 }
 
diff --git a/pkg/analyzer/lib/src/summary2/type_builder.dart b/pkg/analyzer/lib/src/summary2/type_builder.dart
index 7093935..ccad03b 100644
--- a/pkg/analyzer/lib/src/summary2/type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/type_builder.dart
@@ -9,9 +9,8 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
-import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/summary2/lazy_ast.dart';
-import 'package:analyzer/src/summary2/linking_bundle_context.dart';
 
 /// Type annotations and declarations to build types for.
 ///
@@ -44,9 +43,9 @@
 
 /// Build types in a [NodesToBuildType].
 class TypeBuilder {
-  final LinkingBundleContext bundleContext;
+  final Dart2TypeSystem typeSystem;
 
-  TypeBuilder(this.bundleContext);
+  TypeBuilder(this.typeSystem);
 
   DynamicTypeImpl get _dynamicType {
     return DynamicTypeImpl.instance;
@@ -122,102 +121,56 @@
       if (element.isEnum) {
         node.type = InterfaceTypeImpl.explicit(element, const []);
       } else {
-        // TODO(scheglov) Use instantiate to bounds.
+        var rawType = element.type;
+
         var typeParametersLength = element.typeParameters.length;
-        if (typeArguments == null ||
-            typeArguments.length != typeParametersLength) {
-          typeArguments = List<DartType>.filled(
-            typeParametersLength,
-            DynamicTypeImpl.instance,
-          );
+        if (typeParametersLength == 0) {
+          node.type = rawType;
+          return;
         }
+
+        if (typeArguments == null) {
+          node.type = typeSystem.instantiateToBounds(rawType);
+          return;
+        }
+
+        if (typeArguments.length != typeParametersLength) {
+          typeArguments = _listOfDynamic(typeParametersLength);
+        }
+
         node.type = InterfaceTypeImpl.explicit(element, typeArguments);
       }
     } else if (element is GenericTypeAliasElement) {
-      // TODO(scheglov) Use instantiate to bounds.
-      var typeParametersLength = element.typeParameters.length;
-      if (typeArguments == null ||
-          typeArguments.length != typeParametersLength) {
-        typeArguments = List<DartType>.filled(
-          typeParametersLength,
-          DynamicTypeImpl.instance,
+      var rawType = element.function.type;
+
+      var typeParameters = element.typeParameters;
+      var typeParametersLength = typeParameters.length;
+      if (typeParametersLength == 0) {
+        node.type = rawType;
+        return;
+      }
+
+      if (typeArguments == null) {
+        typeArguments = typeSystem.instantiateTypeFormalsToBounds(
+          typeParameters,
         );
+      } else if (typeArguments.length != typeParametersLength) {
+        typeArguments = _listOfDynamic(typeParametersLength);
       }
 
       var substitution = Substitution.fromPairs(
-        element.typeParameters,
+        typeParameters,
         typeArguments,
       );
-
-      // TODO(scheglov) Not sure if I like this.
-      var type = substitution.substituteType(element.function.type);
-      node.type = type;
+      node.type = substitution.substituteType(rawType);
     } else if (element is TypeParameterElement) {
       node.type = TypeParameterTypeImpl(element);
     } else {
-//      throw UnimplementedError('${element.runtimeType}');
-      // TODO(scheglov) implement
-      node.type = DynamicTypeImpl.instance;
+      // We might get all kinds of elements, including not type at all.
+      // For example a PrefixElement, or a getter, etc.
+      // In all these cases the type is dynamic.
+      node.type = _dynamicType;
     }
-
-//    var referenceIndex = typeNameElementIndex(node.typeName_name);
-//    var reference = bundleContext.referenceOfIndex(referenceIndex);
-//
-//    List<LinkedNodeTypeBuilder> typeArguments;
-//    var typeArgumentList = node.typeName_typeArguments;
-//    if (typeArgumentList != null) {
-//      typeArguments = typeArgumentList.typeArgumentList_arguments
-//          .map((node) => _getType(node))
-//          .toList();
-//    }
-//
-//    if (reference.isClass) {
-//      // TODO(scheglov) Use instantiate to bounds.
-//      var typeParametersLength = _typeParametersLength(reference);
-//      if (typeArguments == null ||
-//          typeArguments.length != typeParametersLength) {
-//        typeArguments = List<LinkedNodeTypeBuilder>.filled(
-//          typeParametersLength,
-//          _dynamicType,
-//        );
-//      }
-//      node.typeName_type = LinkedNodeTypeBuilder(
-//        kind: LinkedNodeTypeKind.interface,
-//        interfaceClass: referenceIndex,
-//        interfaceTypeArguments: typeArguments,
-//      );
-//    } else if (reference.isDynamic) {
-//      node.typeName_type = LinkedNodeTypeBuilder(
-//        kind: LinkedNodeTypeKind.dynamic_,
-//      );
-//    } else if (reference.isTypeAlias) {
-//      // TODO(scheglov) Use instantiate to bounds.
-//      var typeParametersLength = _typeParametersLength(reference);
-//      if (typeArguments == null ||
-//          typeArguments.length != typeParametersLength) {
-//        typeArguments = List<LinkedNodeTypeBuilder>.filled(
-//          typeParametersLength,
-//          _dynamicType,
-//        );
-//      }
-//      node.typeName_type = LinkedNodeTypeBuilder(
-//        kind: LinkedNodeTypeKind.genericTypeAlias,
-//        genericTypeAliasReference: referenceIndex,
-//        genericTypeAliasTypeArguments: typeArguments,
-//      );
-//    } else if (reference.isEnum) {
-//      node.typeName_type = LinkedNodeTypeBuilder(
-//        kind: LinkedNodeTypeKind.interface,
-//        interfaceClass: referenceIndex,
-//      );
-//    } else if (reference.isTypeParameter) {
-//      node.typeName_type = LinkedNodeTypeBuilder(
-//        kind: LinkedNodeTypeKind.typeParameter,
-//        typeParameterParameter: referenceIndex,
-//      );
-//    } else {
-//      node.typeName_type = _dynamicType;
-//    }
   }
 
   void _fieldFormalParameter(FieldFormalParameter node) {
@@ -243,32 +196,9 @@
     LazyAst.setType(node, type);
   }
 
-//  LinkedNodeTypeBuilder _getFormalParameterType(LinkedNode node) {
-//    var kind = node.kind;
-//    if (kind == LinkedNodeKind.defaultFormalParameter) {
-//      return _getFormalParameterType(node.defaultFormalParameter_parameter);
-//    }
-//    if (kind == LinkedNodeKind.functionTypedFormalParameter) {
-//      return node.functionTypedFormalParameter_type2;
-//    }
-//    if (kind == LinkedNodeKind.simpleFormalParameter) {
-//      return _getType(node.simpleFormalParameter_type);
-//    }
-//    throw UnimplementedError('$kind');
-//  }
-
-//  LinkedNodeTypeBuilder _getType(LinkedNodeBuilder node) {
-//    if (node == null) return _dynamicType;
-//
-//    var kind = node.kind;
-//    if (kind == LinkedNodeKind.genericFunctionType) {
-//      return node.genericFunctionType_type;
-//    } else if (kind == LinkedNodeKind.typeName) {
-//      return node.typeName_type;
-//    } else {
-//      throw UnimplementedError('$kind');
-//    }
-//  }
+  List<DartType> _listOfDynamic(int typeParametersLength) {
+    return List<DartType>.filled(typeParametersLength, _dynamicType);
+  }
 
   void _setTypesForDeclaration(AstNode node) {
     if (node is FieldFormalParameter) {
@@ -298,52 +228,5 @@
     } else {
       throw UnimplementedError('${node.runtimeType}');
     }
-//    var kind = node.kind;
-//    if (kind == LinkedNodeKind.fieldFormalParameter) {
-//      _fieldFormalParameter(node);
-//    } else if (kind == LinkedNodeKind.functionDeclaration) {
-//      node.functionDeclaration_returnType2 = _getType(
-//        node.functionDeclaration_returnType,
-//      );
-//    } else if (kind == LinkedNodeKind.functionTypeAlias) {
-//      node.functionTypeAlias_returnType2 = _getType(
-//        node.functionTypeAlias_returnType,
-//      );
-//    } else if (kind == LinkedNodeKind.functionTypedFormalParameter) {
-//      _functionTypedFormalParameter(node);
-//    } else if (kind == LinkedNodeKind.genericFunctionType) {
-//      node.genericFunctionType_returnType2 = _getType(
-//        node.genericFunctionType_returnType,
-//      );
-//    } else if (kind == LinkedNodeKind.methodDeclaration) {
-//      node.methodDeclaration_returnType2 = _getType(
-//        node.methodDeclaration_returnType,
-//      );
-//    } else if (kind == LinkedNodeKind.simpleFormalParameter) {
-//      node.simpleFormalParameter_type2 = _getType(
-//        node.simpleFormalParameter_type,
-//      );
-//    } else if (kind == LinkedNodeKind.variableDeclarationList) {
-//      var typeNode = node.variableDeclarationList_type;
-//      for (var variable in node.variableDeclarationList_variables) {
-//        variable.variableDeclaration_type2 = _getType(typeNode);
-//      }
-//    } else {
-//      throw UnimplementedError('$kind');
-//    }
-  }
-
-//  int _typeParametersLength(Reference reference) {
-//    var node = bundleContext.elementFactory.nodeOfReference(reference);
-//    return LinkedUnitContext.getTypeParameters(node)?.length ?? 0;
-//  }
-
-  static int typeNameElementIndex(LinkedNode name) {
-    if (name.kind == LinkedNodeKind.simpleIdentifier) {
-      return name.simpleIdentifier_element;
-    } else {
-      var identifier = name.prefixedIdentifier_identifier;
-      return identifier.simpleIdentifier_element;
-    }
   }
 }
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index 2eb6848..99b8730 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -196,12 +196,6 @@
 
   @override
   @failingTest
-  test_class_notSimplyBounded_complex_by_cycle() async {
-    await super.test_class_notSimplyBounded_complex_by_cycle();
-  }
-
-  @override
-  @failingTest
   test_class_notSimplyBounded_function_typed_bound_complex_via_parameter_type() async {
     await super
         .test_class_notSimplyBounded_function_typed_bound_complex_via_parameter_type();
@@ -209,12 +203,6 @@
 
   @override
   @failingTest
-  test_class_notSimplyBounded_refers_to_circular_typedef() async {
-    await super.test_class_notSimplyBounded_refers_to_circular_typedef();
-  }
-
-  @override
-  @failingTest
   test_class_type_parameters_bound() async {
     await super.test_class_type_parameters_bound();
   }
@@ -444,42 +432,12 @@
 
   @override
   @failingTest
-  test_instantiateToBounds_boundRefersToEarlierTypeArgument() async {
-    await super.test_instantiateToBounds_boundRefersToEarlierTypeArgument();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_boundRefersToItself() async {
-    await super.test_instantiateToBounds_boundRefersToItself();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_boundRefersToLaterTypeArgument() async {
-    await super.test_instantiateToBounds_boundRefersToLaterTypeArgument();
-  }
-
-  @override
-  @failingTest
   test_instantiateToBounds_functionTypeAlias_reexported() async {
     await super.test_instantiateToBounds_functionTypeAlias_reexported();
   }
 
   @override
   @failingTest
-  test_instantiateToBounds_functionTypeAlias_simple() async {
-    await super.test_instantiateToBounds_functionTypeAlias_simple();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_simple() async {
-    await super.test_instantiateToBounds_simple();
-  }
-
-  @override
-  @failingTest
   test_invalidUri_part_emptyUri() async {
     await super.test_invalidUri_part_emptyUri();
   }
@@ -578,13 +536,6 @@
 
   @override
   @failingTest
-  test_typedef_notSimplyBounded_dependency_via_param_type_new_style_name_included() async {
-    await super
-        .test_typedef_notSimplyBounded_dependency_via_param_type_new_style_name_included();
-  }
-
-  @override
-  @failingTest
   test_typedef_notSimplyBounded_dependency_via_param_type_new_style_name_omitted() async {
     await super
         .test_typedef_notSimplyBounded_dependency_via_param_type_new_style_name_omitted();
@@ -592,27 +543,6 @@
 
   @override
   @failingTest
-  test_typedef_notSimplyBounded_dependency_via_param_type_old_style() async {
-    await super
-        .test_typedef_notSimplyBounded_dependency_via_param_type_old_style();
-  }
-
-  @override
-  @failingTest
-  test_typedef_notSimplyBounded_dependency_via_return_type_new_style() async {
-    await super
-        .test_typedef_notSimplyBounded_dependency_via_return_type_new_style();
-  }
-
-  @override
-  @failingTest
-  test_typedef_notSimplyBounded_dependency_via_return_type_old_style() async {
-    await super
-        .test_typedef_notSimplyBounded_dependency_via_return_type_old_style();
-  }
-
-  @override
-  @failingTest
   test_typedef_type_parameters_bound() async {
     await super.test_typedef_type_parameters_bound();
   }
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 0bc59334..315fd79 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -1247,11 +1247,19 @@
 class C<T extends F> {}
 typedef F(C value);
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+notSimplyBounded typedef F = dynamic Function(C<(C<dynamic>) → dynamic> value);
+notSimplyBounded class C<T extends (C<dynamic>) → dynamic> {
+}
+''');
+    } else {
+      checkElementText(library, r'''
 notSimplyBounded typedef F = dynamic Function(C<dynamic> value);
 notSimplyBounded class C<T extends (C<dynamic>) → dynamic> {
 }
 ''');
+    }
   }
 
   test_class_notSimplyBounded_circularity_with_type_params() async {
@@ -1359,12 +1367,21 @@
 typedef F(G value);
 typedef G(F value);
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+notSimplyBounded typedef F = dynamic Function(((dynamic) → dynamic) → dynamic value);
+notSimplyBounded typedef G = dynamic Function(((dynamic) → dynamic) → dynamic value);
+notSimplyBounded class C<T extends ((dynamic) → dynamic) → dynamic> {
+}
+''');
+    } else {
+      checkElementText(library, r'''
 notSimplyBounded typedef F = dynamic Function(((...) → dynamic) → dynamic value);
 notSimplyBounded typedef G = dynamic Function(((...) → dynamic) → dynamic value);
 notSimplyBounded class C<T extends ((...) → dynamic) → dynamic> {
 }
 ''');
+    }
   }
 
   test_class_notSimplyBounded_self() async {
@@ -9244,11 +9261,19 @@
 typedef F = void Function(C c);
 class C<T extends C<T>> {}
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+notSimplyBounded typedef F = void Function(C<dynamic> c);
+notSimplyBounded class C<T extends C<T>> {
+}
+''');
+    } else {
+      checkElementText(library, r'''
 notSimplyBounded typedef F = void Function(C<C<dynamic>> c);
 notSimplyBounded class C<T extends C<T>> {
 }
 ''');
+    }
   }
 
   test_typedef_notSimplyBounded_dependency_via_param_type_new_style_name_omitted() async {
@@ -9258,11 +9283,19 @@
 typedef F = void Function(C);
 class C<T extends C<T>> {}
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+notSimplyBounded typedef F = void Function(C<dynamic> );
+notSimplyBounded class C<T extends C<T>> {
+}
+''');
+    } else {
+      checkElementText(library, r'''
 notSimplyBounded typedef F = void Function(C<C<dynamic>> );
 notSimplyBounded class C<T extends C<T>> {
 }
 ''');
+    }
   }
 
   test_typedef_notSimplyBounded_dependency_via_param_type_old_style() async {
@@ -9272,11 +9305,19 @@
 typedef void F(C c);
 class C<T extends C<T>> {}
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+notSimplyBounded typedef F = void Function(C<dynamic> c);
+notSimplyBounded class C<T extends C<T>> {
+}
+''');
+    } else {
+      checkElementText(library, r'''
 notSimplyBounded typedef F = void Function(C<C<dynamic>> c);
 notSimplyBounded class C<T extends C<T>> {
 }
 ''');
+    }
   }
 
   test_typedef_notSimplyBounded_dependency_via_return_type_new_style() async {
@@ -9286,11 +9327,19 @@
 typedef F = C Function();
 class C<T extends C<T>> {}
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+notSimplyBounded typedef F = C<dynamic> Function();
+notSimplyBounded class C<T extends C<T>> {
+}
+''');
+    } else {
+      checkElementText(library, r'''
 notSimplyBounded typedef F = C<C<dynamic>> Function();
 notSimplyBounded class C<T extends C<T>> {
 }
 ''');
+    }
   }
 
   test_typedef_notSimplyBounded_dependency_via_return_type_old_style() async {
@@ -9300,11 +9349,19 @@
 typedef C F();
 class C<T extends C<T>> {}
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+notSimplyBounded typedef F = C<dynamic> Function();
+notSimplyBounded class C<T extends C<T>> {
+}
+''');
+    } else {
+      checkElementText(library, r'''
 notSimplyBounded typedef F = C<C<dynamic>> Function();
 notSimplyBounded class C<T extends C<T>> {
 }
 ''');
+    }
   }
 
   test_typedef_parameter_parameters() async {