[vm] Make Class::RareType() the instantiated to bounds type.
Previously, Class::RareType() returned a Type where the type arguments
were null (e.g., all dynamic). However, this is an invalid type for
classes that have at least one type parameter with a bound that is not a
top type, and could mean that comparisons (such as subtyping) against
the "rare" type could return incorrect answers.
Instead, use TypeParameters::defaults() to get the canonicalized
instantiated to bounds type argument vector and use that instead.
TEST=ci
Cq-Include-Trybots: luci.dart.try:vm-reload-linux-debug-x64-try,vm-reload-rollback-linux-debug-x64-try,vm-linux-debug-x64-try,vm-linux-release-x64-try
Change-Id: Iea591e93102f53713265b481476f9670cfb81c93
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/312261
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 5fcbd6a..365503e 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -324,11 +324,9 @@
// arguments.
//
// This is e.g. true for "String" but also for "List<dynamic>". (A type for
- // which the type arguments vector is filled with "dynamic" is known as a rare
- // type)
+ // which the type arguments vector is instantiated to bounds is known as a
+ // rare type.)
if (type_class.IsGeneric()) {
- // TODO(kustermann): We might want to consider extending this when the type
- // arguments are not "dynamic" but instantiated-to-bounds.
const Type& rare_type = Type::Handle(zone, type_class.RareType());
if (!rare_type.IsSubtypeOf(type, Heap::kNew)) {
ASSERT(Type::Cast(type).arguments() != TypeArguments::null());
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index a29f44a..c970791 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3068,12 +3068,17 @@
}
TypePtr Class::RareType() const {
- if (!IsGeneric() && !IsClosureClass()) {
+ if (!IsGeneric()) {
return DeclarationType();
}
ASSERT(is_declaration_loaded());
- Type& type = Type::Handle(Type::New(*this, Object::null_type_arguments(),
- Nullability::kNonNullable));
+ Thread* const thread = Thread::Current();
+ Zone* const zone = thread->zone();
+ const auto& inst_to_bounds =
+ TypeArguments::Handle(zone, InstantiateToBounds(thread));
+ ASSERT(inst_to_bounds.ptr() != Object::empty_type_arguments().ptr());
+ auto& type = Type::Handle(
+ zone, Type::New(*this, inst_to_bounds, Nullability::kNonNullable));
type ^= ClassFinalizer::FinalizeType(type);
return type.ptr();
}
@@ -22768,12 +22773,14 @@
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
const Class& cls = Class::Handle(zone, type_class());
+ const TypeParameters& params =
+ TypeParameters::Handle(zone, cls.type_parameters());
printer->AddString(cls.NameCString(name_visibility));
const TypeArguments& args = TypeArguments::Handle(zone, arguments());
intptr_t num_type_params = 0;
if (cls.is_declaration_loaded()) {
num_type_params = cls.NumTypeParameters(thread);
- } else if (!args.IsNull()) {
+ } else if (!args.IsNull() || args.ptr() != params.defaults()) {
num_type_params = args.Length();
}
if (num_type_params == 0) {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index e1414d4..724e58a 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1198,7 +1198,7 @@
int32_t SourceFingerprint() const;
- // Return the Type with type arguments filled in with dynamic.
+ // Return the Type with type arguments instantiated to bounds.
TypePtr RareType() const;
// Return the non-nullable Type whose arguments are the type parameters
@@ -8315,6 +8315,7 @@
friend class FunctionType;
friend class Object;
friend class Precompiler;
+ friend class Type; // To determine whether to print type arguments.
};
// A TypeArguments is an array of AbstractType.