Skip to content

Commit 0b64f54

Browse files
creliercommit-bot@chromium.org
authored andcommitted
[VM/nnbd] Normalize 'X extends Never' to 'Never'.
In order to normalize 'X extends Never' to 'Never' (and 'X? extends Never' to 'Null'), the VM has to instantiate the bounds of function type parameters. Instantiating these bounds lazily is not easily feasible, as the instantiators are not kept around after instantiating types. Note that the normalization tests do not yet pass due to test issues and CFE issues, see #42143 Change-Id: I9ed6fcb9d7a11a4adbe514757ad9ac6ff7818981 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/147281 Commit-Queue: Régis Crelier <[email protected]> Reviewed-by: Alexander Markov <[email protected]>
1 parent d25c369 commit 0b64f54

File tree

1 file changed

+59
-27
lines changed

1 file changed

+59
-27
lines changed

runtime/vm/object.cc

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20121,12 +20121,27 @@ TypeParameterPtr TypeParameter::ToNullability(Nullability value,
2012120121
bool TypeParameter::IsInstantiated(Genericity genericity,
2012220122
intptr_t num_free_fun_type_params,
2012320123
TrailPtr trail) const {
20124+
// Bounds of class type parameters are ignored in the VM.
2012420125
if (IsClassTypeParameter()) {
2012520126
return genericity == kFunctions;
2012620127
}
2012720128
ASSERT(IsFunctionTypeParameter());
2012820129
ASSERT(IsFinalized());
20129-
return (genericity == kCurrentClass) || (index() >= num_free_fun_type_params);
20130+
if ((genericity != kCurrentClass) && (index() < num_free_fun_type_params)) {
20131+
return false;
20132+
}
20133+
// Although the type parameter is instantiated, its bound may not be.
20134+
const AbstractType& upper_bound = AbstractType::Handle(bound());
20135+
if (upper_bound.IsTypeParameter() ||
20136+
upper_bound.arguments() != TypeArguments::null()) {
20137+
// Use trail to break cycles created by bound referring to type parameter.
20138+
if (!TestAndAddToTrail(&trail) &&
20139+
!upper_bound.IsInstantiated(genericity, num_free_fun_type_params,
20140+
trail)) {
20141+
return false;
20142+
}
20143+
}
20144+
return true;
2013020145
}
2013120146

2013220147
bool TypeParameter::IsEquivalent(const Instance& other,
@@ -20264,40 +20279,57 @@ AbstractTypePtr TypeParameter::InstantiateFrom(
2026420279
Heap::Space space,
2026520280
TrailPtr trail) const {
2026620281
ASSERT(IsFinalized());
20282+
AbstractType& result = AbstractType::Handle();
2026720283
if (IsFunctionTypeParameter()) {
2026820284
if (index() >= num_free_fun_type_params) {
20269-
// Return uninstantiated type parameter unchanged.
20270-
return raw();
20285+
// Do not instantiate the function type parameter, but possibly its bound.
20286+
result = raw();
20287+
AbstractType& upper_bound = AbstractType::Handle(bound());
20288+
if (!upper_bound.IsInstantiated(kAny, num_free_fun_type_params,
20289+
nullptr)) {
20290+
// Use trail to break cycles created by bound referring to type param.
20291+
if (OnlyBuddyInTrail(trail) == Object::null()) {
20292+
AddOnlyBuddyToTrail(&trail, *this);
20293+
upper_bound = upper_bound.InstantiateFrom(
20294+
instantiator_type_arguments, function_type_arguments,
20295+
num_free_fun_type_params, space, trail);
20296+
if (upper_bound.raw() == Type::NeverType()) {
20297+
// Normalize 'X extends Never' to 'Never'.
20298+
result = Type::NeverType();
20299+
} else if (upper_bound.raw() != bound()) {
20300+
result ^= Object::Clone(result, space);
20301+
TypeParameter::Cast(result).set_bound(upper_bound);
20302+
}
20303+
}
20304+
}
20305+
} else if (function_type_arguments.IsNull()) {
20306+
return Type::DynamicType();
20307+
} else {
20308+
result = function_type_arguments.TypeAt(index());
20309+
ASSERT(!result.IsTypeParameter());
2027120310
}
20272-
if (function_type_arguments.IsNull()) {
20311+
} else {
20312+
ASSERT(IsClassTypeParameter());
20313+
if (instantiator_type_arguments.IsNull()) {
2027320314
return Type::DynamicType();
2027420315
}
20275-
AbstractType& result =
20276-
AbstractType::Handle(function_type_arguments.TypeAt(index()));
20277-
result = result.SetInstantiatedNullability(*this, space);
20278-
return result.NormalizeFutureOrType(space);
20279-
}
20280-
ASSERT(IsClassTypeParameter());
20281-
if (instantiator_type_arguments.IsNull()) {
20282-
return Type::DynamicType();
20283-
}
20284-
if (instantiator_type_arguments.Length() <= index()) {
20285-
// InstantiateFrom can be invoked from a compilation pipeline with
20286-
// mismatching type arguments vector. This can only happen for
20287-
// a dynamically unreachable code - which compiler can't remove
20288-
// statically for some reason.
20289-
// To prevent crashes we return AbstractType::null(), understood by caller
20290-
// (see AssertAssignableInstr::Canonicalize).
20291-
return AbstractType::null();
20316+
if (instantiator_type_arguments.Length() <= index()) {
20317+
// InstantiateFrom can be invoked from a compilation pipeline with
20318+
// mismatching type arguments vector. This can only happen for
20319+
// a dynamically unreachable code - which compiler can't remove
20320+
// statically for some reason.
20321+
// To prevent crashes we return AbstractType::null(), understood by caller
20322+
// (see AssertAssignableInstr::Canonicalize).
20323+
return AbstractType::null();
20324+
}
20325+
result = instantiator_type_arguments.TypeAt(index());
20326+
// Instantiating a class type parameter cannot result in a
20327+
// function type parameter.
20328+
// Bounds of class type parameters are ignored in the VM.
2029220329
}
20293-
AbstractType& result =
20294-
AbstractType::Handle(instantiator_type_arguments.TypeAt(index()));
2029520330
result = result.SetInstantiatedNullability(*this, space);
20331+
// Canonicalization is not part of instantiation.
2029620332
return result.NormalizeFutureOrType(space);
20297-
// There is no need to canonicalize the instantiated type parameter, since all
20298-
// type arguments are canonicalized at type finalization time. It would be too
20299-
// early to canonicalize the returned type argument here, since instantiation
20300-
// not only happens at run time, but also during type finalization.
2030120333
}
2030220334

2030320335
AbstractTypePtr TypeParameter::Canonicalize(TrailPtr trail) const {

0 commit comments

Comments
 (0)