Skip to content

Commit 173c1ae

Browse files
committed
Improve upper bound finalization in VM and fix #25122.
Add regression test. [email protected] Review URL: https://codereview.chromium.org/1513493002 .
1 parent c985c59 commit 173c1ae

File tree

5 files changed

+37
-7
lines changed

5 files changed

+37
-7
lines changed

runtime/lib/mirrors.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,11 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_members, 2) {
12061206
DEFINE_NATIVE_ENTRY(ClassMirror_type_variables, 1) {
12071207
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
12081208
const Class& klass = Class::Handle(ref.GetClassReferent());
1209+
const Error& error = Error::Handle(zone, klass.EnsureIsFinalized(thread));
1210+
if (!error.IsNull()) {
1211+
Exceptions::PropagateError(error);
1212+
UNREACHABLE();
1213+
}
12091214
return CreateTypeVariableList(klass);
12101215
}
12111216

runtime/vm/class_finalizer.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,7 +1269,8 @@ void ClassFinalizer::FinalizeUpperBounds(const Class& cls) {
12691269
for (intptr_t i = 0; i < num_type_params; i++) {
12701270
type_param ^= type_params.TypeAt(i);
12711271
bound = type_param.bound();
1272-
if (bound.IsFinalized() || bound.IsBeingFinalized()) {
1272+
// Bound may be finalized, but not canonical yet.
1273+
if (bound.IsCanonical() || bound.IsBeingFinalized()) {
12731274
// A bound involved in F-bounded quantification may form a cycle.
12741275
continue;
12751276
}
@@ -2231,7 +2232,10 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
22312232
FinalizeTypeParameters(cls); // May change super type.
22322233
super_class = cls.SuperClass();
22332234
ASSERT(super_class.IsNull() || super_class.is_type_finalized());
2234-
ResolveUpperBounds(cls);
2235+
// Only resolving rather than finalizing the upper bounds here would result in
2236+
// instantiated type parameters of the super type to temporarily have
2237+
// unfinalized bounds. It is more efficient to finalize them early.
2238+
FinalizeUpperBounds(cls);
22352239
// Finalize super type.
22362240
AbstractType& super_type = AbstractType::Handle(cls.super_type());
22372241
if (!super_type.IsNull()) {
@@ -2344,6 +2348,7 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
23442348
void ClassFinalizer::FinalizeClass(const Class& cls) {
23452349
Thread* thread = Thread::Current();
23462350
HANDLESCOPE(thread);
2351+
ASSERT(cls.is_type_finalized());
23472352
if (cls.is_finalized()) {
23482353
return;
23492354
}

runtime/vm/object.cc

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3787,11 +3787,11 @@ bool Class::TypeTestNonRecursive(const Class& cls,
37873787
}
37883788
// Check for reflexivity.
37893789
if (thsi.raw() == other.raw()) {
3790-
const intptr_t num_type_args = thsi.NumTypeArguments();
3791-
if (num_type_args == 0) {
3790+
const intptr_t num_type_params = thsi.NumTypeParameters();
3791+
if (num_type_params == 0) {
37923792
return true;
37933793
}
3794-
const intptr_t num_type_params = thsi.NumTypeParameters();
3794+
const intptr_t num_type_args = thsi.NumTypeArguments();
37953795
const intptr_t from_index = num_type_args - num_type_params;
37963796
// Since we do not truncate the type argument vector of a subclass (see
37973797
// below), we only check a subvector of the proper length.
@@ -15630,8 +15630,8 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
1563015630
const AbstractType& other,
1563115631
Error* bound_error,
1563215632
Heap::Space space) const {
15633-
ASSERT(IsResolved());
15634-
ASSERT(other.IsResolved());
15633+
ASSERT(IsFinalized());
15634+
ASSERT(other.IsFinalized());
1563515635
if (IsMalformed() || other.IsMalformed()) {
1563615636
// Malformed types involved in subtype tests should be handled specially
1563715637
// by the caller. Malformed types should only be encountered here in a
@@ -15685,6 +15685,15 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
1568515685
}
1568615686
}
1568715687
const AbstractType& bound = AbstractType::Handle(type_param.bound());
15688+
// We may be checking bounds at finalization time and can encounter
15689+
// a still unfinalized bound.
15690+
if (!bound.IsFinalized() && !bound.IsBeingFinalized()) {
15691+
ClassFinalizer::FinalizeType(
15692+
Class::Handle(type_param.parameterized_class()),
15693+
bound,
15694+
ClassFinalizer::kCanonicalize);
15695+
type_param.set_bound(bound);
15696+
}
1568815697
if (bound.IsMoreSpecificThan(other, bound_error)) {
1568915698
return true;
1569015699
}

tests/language/language_dart2js.status

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ mixin_super_2_test: CompileTimeError # Issue 23773
5353
mixin_super_bound2_test: CompileTimeError # Issue 23773
5454
mixin_super_use_test: CompileTimeError # Issue 23773
5555
mixin_superclass_test: CompileTimeError # Issue 23773
56+
regress_25122_test: Crash # Issue 25181
5657

5758
ref_before_declaration_test/00: MissingCompileTimeError
5859
ref_before_declaration_test/01: MissingCompileTimeError
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
main() {}
6+
7+
class AbstractListMember<E, M extends AbstractListMember<E, M>> {}
8+
9+
class RepoListMember<M extends RepoListMember<M>>
10+
extends AbstractListMember<String, M> {}

0 commit comments

Comments
 (0)