mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
Include liveness of type argument in supertypes in RTI needed checks computation
Change-Id: Ifdde3e8694f8d39ccf10cac0d5dc2cb3cb9225bd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/98560 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
parent
9a2b222cba
commit
78fca5b2fa
3 changed files with 77 additions and 0 deletions
|
@ -2073,6 +2073,7 @@ class RuntimeTypesImpl extends _RuntimeTypesBase
|
|||
classUse.instance = true;
|
||||
});
|
||||
|
||||
Set<ClassEntity> visitedSuperClasses = {};
|
||||
codegenWorldBuilder.instantiatedTypes.forEach((InterfaceType type) {
|
||||
liveTypeVisitor.visitType(type, TypeVisitorState.direct);
|
||||
ClassUse classUse =
|
||||
|
@ -2082,6 +2083,31 @@ class RuntimeTypesImpl extends _RuntimeTypesBase
|
|||
if (callType != null) {
|
||||
liveTypeVisitor.visitType(callType, TypeVisitorState.direct);
|
||||
}
|
||||
|
||||
// Superclass might make classes live as type arguments. For instance
|
||||
//
|
||||
// class A {}
|
||||
// class B<T> {}
|
||||
// class C extends B<A> {}
|
||||
// main() => new C();
|
||||
//
|
||||
// Here `A` is live as a type argument through the liveness of `C`.
|
||||
ClassEntity superclass = _elementEnvironment.getSuperClass(type.element);
|
||||
while (superclass != null) {
|
||||
if (!_elementEnvironment.isGenericClass(superclass) &&
|
||||
visitedSuperClasses.contains(superclass)) {
|
||||
// If [superclass] is not generic then a second visit cannot add more
|
||||
// information that the first. In the example above, visiting `C`
|
||||
// twice can only result in a second registration of `A` as live
|
||||
// type argument.
|
||||
break;
|
||||
}
|
||||
visitedSuperClasses.add(superclass);
|
||||
InterfaceType supertype =
|
||||
_closedWorld.dartTypes.asInstanceOf(type, superclass);
|
||||
liveTypeVisitor.visitType(supertype, TypeVisitorState.direct);
|
||||
superclass = _elementEnvironment.getSuperClass(superclass);
|
||||
}
|
||||
});
|
||||
|
||||
for (FunctionEntity element
|
||||
|
|
29
tests/compiler/dart2js/rti/emission/fixed_type_argument.dart
Normal file
29
tests/compiler/dart2js/rti/emission/fixed_type_argument.dart
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2019, 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.
|
||||
|
||||
/*strong.class: A:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
|
||||
/*omit.class: A:checkedTypeArgument,checks=[],typeArgument*/
|
||||
class A {}
|
||||
|
||||
/*strong.class: B:checkedInstance,checks=[$isA],typeArgument*/
|
||||
/*omit.class: B:checks=[$isA],typeArgument*/
|
||||
class B implements A {}
|
||||
|
||||
/*class: C:checks=[],indirectInstance*/
|
||||
class C<T> {
|
||||
@pragma('dart2js:noInline')
|
||||
method(void Function(T) f) {}
|
||||
}
|
||||
|
||||
/*strong.class: D:checks=[$asC],instance*/
|
||||
/*omit.class: D:checks=[],instance*/
|
||||
class D extends C<B> {}
|
||||
|
||||
main() {
|
||||
C<A> c = new D();
|
||||
c.method(
|
||||
/*strong.checks=[$signature],instance*/
|
||||
/*omit.checks=[],instance*/
|
||||
(A a) {});
|
||||
}
|
22
tests/compiler/dart2js_extra/fixed_type_argument_test.dart
Normal file
22
tests/compiler/dart2js_extra/fixed_type_argument_test.dart
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) 2019, 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.
|
||||
|
||||
// Test that we emit the relation between B and A even when B is only live
|
||||
// as a type argument through the superclass of D.
|
||||
|
||||
class A {}
|
||||
|
||||
class B implements A {}
|
||||
|
||||
class C<T> {
|
||||
@pragma('dart2js:noInline')
|
||||
method(void Function(T) f) {}
|
||||
}
|
||||
|
||||
class D extends C<B> {}
|
||||
|
||||
main() {
|
||||
C<A> c = new D();
|
||||
c.method((A a) {});
|
||||
}
|
Loading…
Reference in a new issue