diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index 5fcbd6a6533..365503e7656 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -324,11 +324,9 @@ bool HierarchyInfo::CanUseSubtypeRangeCheckFor(const AbstractType& type) { // arguments. // // This is e.g. true for "String" but also for "List". (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 a29f44a9f7d..c970791ebdf 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -3068,12 +3068,17 @@ bool Class::IsInFullSnapshot() const { } 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 @@ void Type::PrintName(NameVisibility name_visibility, 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 e1414d42d5c..724e58a630e 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -1198,7 +1198,7 @@ class Class : public Object { 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 @@ class TypeParameters : public Object { 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.