Include generic type arguments in deferred load computation.

Closes #33046

Change-Id: I1273b631e3f5b5aca8d4042b0afd972709a00068
Reviewed-on: https://dart-review.googlesource.com/53805
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index c7db088..1e56455 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -23,7 +23,7 @@
     show AstElement, ClassElement, Element, MethodElement, LocalFunctionElement;
 import 'elements/entities.dart';
 import 'kernel/kelements.dart' show KLocalFunction;
-import 'universe/use.dart' show StaticUse, StaticUseKind, TypeUse, TypeUseKind;
+import 'universe/use.dart';
 import 'universe/world_impact.dart'
     show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
 import 'util/uri_extras.dart' as uri_extras;
@@ -320,6 +320,18 @@
             case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
               _collectTypeDependencies(staticUse.type, elements);
               break;
+            case StaticUseKind.INVOKE:
+            case StaticUseKind.CLOSURE_CALL:
+            case StaticUseKind.DIRECT_INVOKE:
+              // TODO(johnniwinther): Use rti need data to skip unneeded type
+              // arguments.
+              List<DartType> typeArguments = staticUse.typeArguments;
+              if (typeArguments != null) {
+                for (DartType typeArgument in typeArguments) {
+                  _collectTypeDependencies(typeArgument, elements);
+                }
+              }
+              break;
             default:
           }
         }, visitTypeUse: (TypeUse typeUse) {
@@ -358,6 +370,15 @@
               }
               break;
           }
+        }, visitDynamicUse: (DynamicUse dynamicUse) {
+          // TODO(johnniwinther): Use rti need data to skip unneeded type
+          // arguments.
+          List<DartType> typeArguments = dynamicUse.typeArguments;
+          if (typeArguments != null) {
+            for (DartType typeArgument in typeArguments) {
+              _collectTypeDependencies(typeArgument, elements);
+            }
+          }
         }),
         DeferredLoadTask.IMPACT_USE);
   }
diff --git a/tests/compiler/dart2js/deferred_loading/data/type_argument_dependency.dart b/tests/compiler/dart2js/deferred_loading/data/type_argument_dependency.dart
new file mode 100644
index 0000000..80026e3
--- /dev/null
+++ b/tests/compiler/dart2js/deferred_loading/data/type_argument_dependency.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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 '../libs/type_argument_dependency_lib1.dart';
+import '../libs/type_argument_dependency_lib2.dart' deferred as c;
+
+/*element: main:OutputUnit(main, {})*/
+main() async {
+  await c.loadLibrary();
+  c.createA();
+  doCast(<dynamic>[1, 2]);
+}
diff --git a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
index d69452a..37b9fed 100644
--- a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
+++ b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
@@ -34,10 +34,13 @@
     Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
     await checkTests(
         dataDir, computeAstOutputUnitData, computeKernelOutputUnitData,
+        computeClassDataFromAst: computeAstClassOutputUnitData,
+        computeClassDataFromKernel: computeKernelClassOutputUnitData,
         libDirectory: new Directory.fromUri(Platform.script.resolve('libs')),
         skipForKernel: skipForKernel,
         options: compilerOptions,
-        args: args, setUpFunction: () {
+        args: args,
+        testOmit: true, setUpFunction: () {
       importPrefixes.clear();
     });
   });
@@ -107,6 +110,17 @@
   }
 }
 
+void computeAstClassOutputUnitData(
+    Compiler compiler, ClassEntity _cls, Map<Id, ActualData> actualMap,
+    {bool verbose: false}) {
+  ClassElement cls = _cls;
+  OutputUnitData data = compiler.backend.outputUnitData;
+  String value = outputUnitString(data.outputUnitForEntity(cls));
+
+  _registerValue(new ClassId(cls.name), value, cls, cls.sourcePosition,
+      actualMap, compiler.reporter);
+}
+
 /// OutputData for [member] as a kernel based element.
 ///
 /// At this point the compiler has already been run, so it is holding the
@@ -157,6 +171,25 @@
   }
 }
 
+void computeKernelClassOutputUnitData(
+    Compiler compiler, ClassEntity cls, Map<Id, ActualData> actualMap,
+    {bool verbose: false}) {
+  OutputUnitData data = compiler.backend.outputUnitData;
+  String value = outputUnitString(data.outputUnitForEntity(cls));
+
+  KernelBackendStrategy backendStrategy = compiler.backendStrategy;
+  KernelToElementMapForBuilding elementMap = backendStrategy.elementMap;
+  ClassDefinition definition = elementMap.getClassDefinition(cls);
+
+  _registerValue(
+      new ClassId(cls.name),
+      value,
+      cls,
+      computeSourceSpanFromTreeNode(definition.node),
+      actualMap,
+      compiler.reporter);
+}
+
 /// Set [actualMap] to hold a key of [id] with the computed data [value]
 /// corresponding to [object] at location [sourceSpan]. We also perform error
 /// checking to ensure that the same [id] isn't added twice.
diff --git a/tests/compiler/dart2js/deferred_loading/libs/deferred_class_library.dart b/tests/compiler/dart2js/deferred_loading/libs/deferred_class_library.dart
index 95f54b4..3e359eb 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/deferred_class_library.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/deferred_class_library.dart
@@ -6,6 +6,7 @@
 
 library deferred_class_library;
 
+/*class: MyClass:OutputUnit(1, {lib})*/
 class MyClass {
   /*element: MyClass.:OutputUnit(1, {lib})*/
   const MyClass();
diff --git a/tests/compiler/dart2js/deferred_loading/libs/deferred_constant1_lib3.dart b/tests/compiler/dart2js/deferred_loading/libs/deferred_constant1_lib3.dart
index 1cb567c9..3935220 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/deferred_constant1_lib3.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/deferred_constant1_lib3.dart
@@ -4,6 +4,7 @@
 
 library deferred_constants1_lib3;
 
+/*class: C:OutputUnit(main, {})*/
 class C {
   /*element: C.value:OutputUnit(main, {})*/
   final value;
diff --git a/tests/compiler/dart2js/deferred_loading/libs/deferred_constant2_lib.dart b/tests/compiler/dart2js/deferred_loading/libs/deferred_constant2_lib.dart
index dc59b97..33b5017 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/deferred_constant2_lib.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/deferred_constant2_lib.dart
@@ -4,6 +4,7 @@
 
 library deferred_constants2_lib;
 
+/*class: Constant:OutputUnit(1, {lib})*/
 class Constant {
   /*element: Constant.value:OutputUnit(1, {lib})*/
   final value;
diff --git a/tests/compiler/dart2js/deferred_loading/libs/deferred_overlapping_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/deferred_overlapping_lib1.dart
index e1c3a03..7587f4e 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/deferred_overlapping_lib1.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/deferred_overlapping_lib1.dart
@@ -4,5 +4,6 @@
 
 import "deferred_overlapping_lib3.dart";
 
+/*class: C1:OutputUnit(1, {lib1})*/
 /*element: C1.:OutputUnit(1, {lib1})*/
 class C1 extends C3 {}
diff --git a/tests/compiler/dart2js/deferred_loading/libs/deferred_overlapping_lib2.dart b/tests/compiler/dart2js/deferred_loading/libs/deferred_overlapping_lib2.dart
index 4d7c620..3e49d22 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/deferred_overlapping_lib2.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/deferred_overlapping_lib2.dart
@@ -4,5 +4,6 @@
 
 import "deferred_overlapping_lib3.dart";
 
+/*class: C2:OutputUnit(3, {lib2})*/
 /*element: C2.:OutputUnit(3, {lib2})*/
 class C2 extends C3 {}
diff --git a/tests/compiler/dart2js/deferred_loading/libs/deferred_overlapping_lib3.dart b/tests/compiler/dart2js/deferred_loading/libs/deferred_overlapping_lib3.dart
index 6804b23..5447ff9 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/deferred_overlapping_lib3.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/deferred_overlapping_lib3.dart
@@ -2,5 +2,6 @@
 // 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.
 
+/*class: C3:OutputUnit(2, {lib1, lib2})*/
 /*element: C3.:OutputUnit(2, {lib1, lib2})*/
 class C3 {}
diff --git a/tests/compiler/dart2js/deferred_loading/libs/deferred_typed_map_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/deferred_typed_map_lib1.dart
index 4529ffb..36d7d4a 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/deferred_typed_map_lib1.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/deferred_typed_map_lib1.dart
@@ -2,6 +2,7 @@
 // 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.
 
+/*class: M:OutputUnit(1, {lib})*/
 class M {}
 
 typedef dynamic FF({M b});
@@ -9,8 +10,7 @@
 /*element: table:OutputUnit(1, {lib})*/
 const table =
 /*ast.null*/
-/*kernel.OutputUnit(1, {lib})*/
-/*strong.OutputUnit(1, {lib})*/
+/*!ast.OutputUnit(1, {lib})*/
     const <int, FF>{1: f1, 2: f2};
 
 /*element: f1:OutputUnit(1, {lib})*/
diff --git a/tests/compiler/dart2js/deferred_loading/libs/deferred_typedef_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/deferred_typedef_lib1.dart
index 9344b77..9d6d26a 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/deferred_typedef_lib1.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/deferred_typedef_lib1.dart
@@ -4,6 +4,7 @@
 
 library deferred_typedef_lib1;
 
+/*class: C:OutputUnit(1, {lib1})*/
 class C {
   /*element: C.a:OutputUnit(1, {lib1})*/
   final a;
diff --git a/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart
index 1fefeae..80c37a0 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart
@@ -17,6 +17,7 @@
 /*element: C2b:OutputUnit(1, {lib1})*/
 const C2b = /*OutputUnit(1, {lib1})*/ const C(1010);
 
+/*class: D:OutputUnit(main, {})*/
 class D {
   /*element: D.C3:OutputUnit(1, {lib1})*/
   static const C3 = "string2";
diff --git a/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_main.dart b/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_main.dart
index a68724a..494a35d 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_main.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_main.dart
@@ -8,6 +8,7 @@
 /*element: c:OutputUnit(main, {})*/
 const c = "string3";
 
+/*class: C:OutputUnit(main, {})*/
 class C {
   /*element: C.p:OutputUnit(main, {})*/
   final p;
diff --git a/tests/compiler/dart2js/deferred_loading/libs/shared_constant_c.dart b/tests/compiler/dart2js/deferred_loading/libs/shared_constant_c.dart
index 370c0e1..b6ce057 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/shared_constant_c.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/shared_constant_c.dart
@@ -2,6 +2,7 @@
 // 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.
 
+/*class: C:OutputUnit(1, {s1, s2})*/
 class C {
   /*element: C.:OutputUnit(1, {s1, s2})*/
   const C();
diff --git a/tests/compiler/dart2js/deferred_loading/libs/type_argument_dependency_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/type_argument_dependency_lib1.dart
new file mode 100644
index 0000000..37095d3
--- /dev/null
+++ b/tests/compiler/dart2js/deferred_loading/libs/type_argument_dependency_lib1.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, 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 'type_argument_dependency_lib2.dart';
+
+/*element: doCast:OutputUnit(main, {})*/
+doCast(List<dynamic> l) => l.cast<B>().map((x) => 1);
diff --git a/tests/compiler/dart2js/deferred_loading/libs/type_argument_dependency_lib2.dart b/tests/compiler/dart2js/deferred_loading/libs/type_argument_dependency_lib2.dart
new file mode 100644
index 0000000..bf70190
--- /dev/null
+++ b/tests/compiler/dart2js/deferred_loading/libs/type_argument_dependency_lib2.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, 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.
+
+/*ast.class: A:OutputUnit(1, {c})*/
+/*kernel.class: A:OutputUnit(1, {c})*/
+/*strong.class: A:OutputUnit(main, {})*/
+/*omit.class: A:OutputUnit(main, {})*/
+class A {
+  /*element: A.:OutputUnit(1, {c})*/
+  A();
+}
+
+/*class: B:OutputUnit(main, {})*/
+class B extends A {}
+
+/*element: createA:OutputUnit(1, {c})*/
+createA() => new A();