mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:09:48 +00:00
Reland "[VM/runtime] Refactor the representation of type parameters in the VM."
This is a reland of 8a21ab195a
Original change's description:
> [VM/runtime] Refactor the representation of type parameters in the VM.
>
> This introduces a new VM internal class 'TypeParameters' representing the declaration of a list of type parameters, either in a class or function.
> The reference to (or use of) a type parameter is still represented by the existing 'TypeParameter' class.
>
> Fixes https://github.com/dart-lang/sdk/issues/43901
> Fixes https://github.com/dart-lang/sdk/issues/45763
>
> TEST=existing ones and a regression test
>
> Change-Id: I1fde808bf753cc1cb829f2c4383c1836651cee80
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/189942
> Commit-Queue: Régis Crelier <regis@google.com>
> Reviewed-by: Alexander Markov <alexmarkov@google.com>
This fixes https://github.com/dart-lang/sdk/issues/45911
TEST=existing ones and a regression test
Change-Id: I709d38b1df3d73fe3c9796d5aca3cbbdcf77fd38
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/198380
Commit-Queue: Régis Crelier <regis@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
df3bb63a13
commit
1f55b7ca10
|
@ -191,7 +191,7 @@ static InstancePtr CreateTypeVariableMirror(const TypeParameter& param,
|
|||
const Instance& owner_mirror) {
|
||||
const Array& args = Array::Handle(Array::New(3));
|
||||
args.SetAt(0, param);
|
||||
args.SetAt(1, String::Handle(param.name()));
|
||||
args.SetAt(1, String::Handle(param.UserVisibleName()));
|
||||
args.SetAt(2, owner_mirror);
|
||||
return CreateMirror(Symbols::_TypeVariableMirror(), args);
|
||||
}
|
||||
|
@ -199,18 +199,17 @@ static InstancePtr CreateTypeVariableMirror(const TypeParameter& param,
|
|||
// We create a list in native code and let Dart code create the type mirror
|
||||
// object and the ordered map.
|
||||
static InstancePtr CreateTypeVariableList(const Class& cls) {
|
||||
const TypeArguments& args = TypeArguments::Handle(cls.type_parameters());
|
||||
if (args.IsNull()) {
|
||||
const intptr_t num_type_params = cls.NumTypeParameters();
|
||||
if (num_type_params == 0) {
|
||||
return Object::empty_array().ptr();
|
||||
}
|
||||
const Array& result = Array::Handle(Array::New(args.Length() * 2));
|
||||
const Array& result = Array::Handle(Array::New(num_type_params * 2));
|
||||
TypeParameter& type = TypeParameter::Handle();
|
||||
String& name = String::Handle();
|
||||
for (intptr_t i = 0; i < args.Length(); i++) {
|
||||
type ^= args.TypeAt(i);
|
||||
ASSERT(type.IsTypeParameter());
|
||||
for (intptr_t i = 0; i < num_type_params; i++) {
|
||||
type = cls.TypeParameterAt(i, Nullability::kLegacy);
|
||||
ASSERT(type.IsFinalized());
|
||||
name = type.name();
|
||||
name = type.UserVisibleName();
|
||||
result.SetAt(2 * i, name);
|
||||
result.SetAt(2 * i + 1, type);
|
||||
}
|
||||
|
|
|
@ -449,18 +449,19 @@ DEFINE_NATIVE_ENTRY(Internal_boundsCheckForPartialInstantiation, 0, 2) {
|
|||
const Closure& closure =
|
||||
Closure::CheckedHandle(zone, arguments->NativeArgAt(0));
|
||||
const Function& target = Function::Handle(zone, closure.function());
|
||||
const TypeArguments& bounds =
|
||||
TypeArguments::Handle(zone, target.type_parameters());
|
||||
|
||||
// Either the bounds are all-dynamic or the function is not generic.
|
||||
if (bounds.IsNull()) return Object::null();
|
||||
const TypeParameters& type_params =
|
||||
TypeParameters::Handle(zone, target.type_parameters());
|
||||
if (type_params.IsNull() || type_params.AllDynamicBounds()) {
|
||||
// The function is not generic or the bounds are all dynamic.
|
||||
return Object::null();
|
||||
}
|
||||
|
||||
const TypeArguments& type_args_to_check =
|
||||
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(1));
|
||||
|
||||
// This should be guaranteed by the front-end.
|
||||
ASSERT(type_args_to_check.IsNull() ||
|
||||
bounds.Length() <= type_args_to_check.Length());
|
||||
type_params.Length() <= type_args_to_check.Length());
|
||||
|
||||
// The bounds on the closure may need instantiation.
|
||||
const TypeArguments& instantiator_type_args =
|
||||
|
@ -470,10 +471,8 @@ DEFINE_NATIVE_ENTRY(Internal_boundsCheckForPartialInstantiation, 0, 2) {
|
|||
|
||||
AbstractType& supertype = AbstractType::Handle(zone);
|
||||
AbstractType& subtype = AbstractType::Handle(zone);
|
||||
TypeParameter& parameter = TypeParameter::Handle(zone);
|
||||
for (intptr_t i = 0; i < bounds.Length(); ++i) {
|
||||
parameter ^= bounds.TypeAt(i);
|
||||
supertype = parameter.bound();
|
||||
for (intptr_t i = 0; i < type_params.Length(); ++i) {
|
||||
supertype = type_params.BoundAt(i);
|
||||
subtype = type_args_to_check.IsNull() ? Object::dynamic_type().ptr()
|
||||
: type_args_to_check.TypeAt(i);
|
||||
|
||||
|
@ -492,7 +491,7 @@ DEFINE_NATIVE_ENTRY(Internal_boundsCheckForPartialInstantiation, 0, 2) {
|
|||
ASSERT(caller_frame != NULL);
|
||||
location = caller_frame->GetTokenPos();
|
||||
}
|
||||
String& parameter_name = String::Handle(zone, parameter.Name());
|
||||
const auto& parameter_name = String::Handle(zone, type_params.NameAt(i));
|
||||
Exceptions::CreateAndThrowTypeError(location, subtype, supertype,
|
||||
parameter_name);
|
||||
UNREACHABLE();
|
||||
|
|
|
@ -40,11 +40,6 @@ bool MetadataMapTraits::IsMatch(const Object& a, const Object& b) {
|
|||
const Object& owner_b = Object::Handle(Field::Cast(b).Owner());
|
||||
return IsMatch(owner_a, owner_b);
|
||||
} else if (a.IsTypeParameter() && b.IsTypeParameter()) {
|
||||
const String& name_a = String::Handle(TypeParameter::Cast(a).name());
|
||||
const String& name_b = String::Handle(TypeParameter::Cast(b).name());
|
||||
if (!name_a.Equals(name_b)) {
|
||||
return false;
|
||||
}
|
||||
if (TypeParameter::Cast(a).index() != TypeParameter::Cast(b).index() ||
|
||||
TypeParameter::Cast(a).base() != TypeParameter::Cast(b).base()) {
|
||||
return false;
|
||||
|
|
|
@ -294,31 +294,41 @@ void ClassFinalizer::VerifyBootstrapClasses() {
|
|||
}
|
||||
IsolateGroup::Current()->heap()->Verify();
|
||||
}
|
||||
|
||||
void ClassFinalizer::FinalizeTypeParameters(const Class& cls,
|
||||
FinalizationKind finalization) {
|
||||
if (FLAG_trace_type_finalization) {
|
||||
THR_Print("%s type parameters of '%s'\n",
|
||||
String::Handle(cls.Name()).ToCString(),
|
||||
finalization == kFinalize ? "Finalizing" : "Canonicalizing");
|
||||
}
|
||||
const TypeArguments& type_params =
|
||||
TypeArguments::Handle(cls.type_parameters());
|
||||
if (!type_params.IsNull()) {
|
||||
const intptr_t num_type_params = type_params.Length();
|
||||
TypeParameter& type_param = TypeParameter::Handle();
|
||||
for (intptr_t i = 0; i < num_type_params; i++) {
|
||||
type_param ^= type_params.TypeAt(i);
|
||||
if (!type_param.IsBeingFinalized()) {
|
||||
type_param ^= FinalizeType(type_param, finalization);
|
||||
type_params.SetTypeAt(i, type_param);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
void ClassFinalizer::FinalizeTypeParameters(Zone* zone,
|
||||
const Class& cls,
|
||||
const FunctionType& signature,
|
||||
FinalizationKind finalization,
|
||||
PendingTypes* pending_types) {
|
||||
if (FLAG_trace_type_finalization) {
|
||||
THR_Print(
|
||||
"%s type parameters of %s '%s'\n",
|
||||
finalization == kFinalize ? "Finalizing" : "Canonicalizing",
|
||||
!cls.IsNull() ? "class" : "signature",
|
||||
String::Handle(zone, !cls.IsNull() ? cls.Name() : signature.Name())
|
||||
.ToCString());
|
||||
}
|
||||
const TypeParameters& type_params =
|
||||
TypeParameters::Handle(zone, !cls.IsNull() ? cls.type_parameters()
|
||||
: signature.type_parameters());
|
||||
if (!type_params.IsNull()) {
|
||||
TypeArguments& type_args = TypeArguments::Handle(zone);
|
||||
|
||||
type_args = type_params.bounds();
|
||||
type_args =
|
||||
FinalizeTypeArguments(zone, type_args, finalization, pending_types);
|
||||
type_params.set_bounds(type_args);
|
||||
|
||||
type_args = type_params.defaults();
|
||||
type_args =
|
||||
FinalizeTypeArguments(zone, type_args, finalization, pending_types);
|
||||
type_params.set_defaults(type_args);
|
||||
|
||||
type_params.OptimizeFlags();
|
||||
}
|
||||
}
|
||||
|
||||
// This function reports a compilation error if the recursive 'type' T being
|
||||
// finalized is a non-contractive type, i.e. if the induced type set S of P is
|
||||
// not finite, where P is the instantiation of T with its own type parameters.
|
||||
|
@ -407,9 +417,9 @@ void ClassFinalizer::CheckRecursiveType(const AbstractType& type,
|
|||
// Expand the type arguments of the given type and finalize its full type
|
||||
// argument vector. Return the number of type arguments (0 for a raw type).
|
||||
intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
|
||||
Zone* zone,
|
||||
const AbstractType& type,
|
||||
PendingTypes* pending_types) {
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
// The type class does not need to be finalized in order to finalize the type.
|
||||
// Also, the type parameters of the type class must be finalized.
|
||||
Class& type_class = Class::Handle(zone, type.type_class());
|
||||
|
@ -483,8 +493,8 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
|
|||
}
|
||||
if (offset > 0) {
|
||||
TrailPtr trail = new Trail(zone, 4);
|
||||
FinalizeTypeArguments(type_class, full_arguments, offset, pending_types,
|
||||
trail);
|
||||
FillAndFinalizeTypeArguments(zone, type_class, full_arguments, offset,
|
||||
pending_types, trail);
|
||||
}
|
||||
if (full_arguments.IsRaw(0, num_type_arguments)) {
|
||||
// The parameterized_type is raw. Set its argument vector to null, which
|
||||
|
@ -535,7 +545,9 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
|
|||
// same time. Canonicalization happens when pending types are processed.
|
||||
// The trail is required to correctly instantiate a recursive type argument
|
||||
// of the super type.
|
||||
void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
|
||||
void ClassFinalizer::FillAndFinalizeTypeArguments(
|
||||
Zone* zone,
|
||||
const Class& cls,
|
||||
const TypeArguments& arguments,
|
||||
intptr_t num_uninitialized_arguments,
|
||||
PendingTypes* pending_types,
|
||||
|
@ -545,12 +557,12 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
|
|||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
UNREACHABLE();
|
||||
#else
|
||||
FinalizeTypeParameters(cls, kFinalize);
|
||||
FinalizeTypeParameters(zone, cls, Object::null_function_type(), kFinalize);
|
||||
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
||||
}
|
||||
AbstractType& super_type = AbstractType::Handle(cls.super_type());
|
||||
AbstractType& super_type = AbstractType::Handle(zone, cls.super_type());
|
||||
if (!super_type.IsNull()) {
|
||||
const Class& super_class = Class::Handle(super_type.type_class());
|
||||
const Class& super_class = Class::Handle(zone, super_type.type_class());
|
||||
const intptr_t num_super_type_params = super_class.NumTypeParameters();
|
||||
const intptr_t num_super_type_args = super_class.NumTypeArguments();
|
||||
if (!super_type.IsFinalized() && !super_type.IsBeingFinalized()) {
|
||||
|
@ -558,11 +570,12 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
|
|||
cls.set_super_type(super_type);
|
||||
}
|
||||
TypeArguments& super_type_args =
|
||||
TypeArguments::Handle(super_type.arguments());
|
||||
TypeArguments::Handle(zone, super_type.arguments());
|
||||
// Offset of super type's type parameters in cls' type argument vector.
|
||||
const intptr_t super_offset = num_super_type_args - num_super_type_params;
|
||||
// If the super type is raw (i.e. super_type_args is null), set to dynamic.
|
||||
AbstractType& super_type_arg = AbstractType::Handle(Type::DynamicType());
|
||||
AbstractType& super_type_arg =
|
||||
AbstractType::Handle(zone, Type::DynamicType());
|
||||
for (intptr_t i = super_offset; i < num_uninitialized_arguments; i++) {
|
||||
if (!super_type_args.IsNull()) {
|
||||
super_type_arg = super_type_args.TypeAt(i);
|
||||
|
@ -581,8 +594,9 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
|
|||
ASSERT(super_type_arg.IsFunctionType());
|
||||
}
|
||||
if (FLAG_trace_type_finalization) {
|
||||
THR_Print("Creating TypeRef '%s': '%s'\n",
|
||||
String::Handle(super_type_arg.Name()).ToCString(),
|
||||
THR_Print(
|
||||
"Creating TypeRef '%s': '%s'\n",
|
||||
String::Handle(zone, super_type_arg.Name()).ToCString(),
|
||||
super_type_arg.ToCString());
|
||||
}
|
||||
super_type_arg = TypeRef::New(super_type_arg);
|
||||
|
@ -601,12 +615,12 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
|
|||
// Instantiate super_type_arg with the current argument vector.
|
||||
if (!super_type_arg.IsInstantiated()) {
|
||||
if (FLAG_trace_type_finalization && super_type_arg.IsTypeRef()) {
|
||||
AbstractType& ref_type =
|
||||
AbstractType::Handle(TypeRef::Cast(super_type_arg).type());
|
||||
AbstractType& ref_type = AbstractType::Handle(
|
||||
zone, TypeRef::Cast(super_type_arg).type());
|
||||
THR_Print(
|
||||
"Instantiating TypeRef '%s': '%s'\n"
|
||||
" instantiator: '%s'\n",
|
||||
String::Handle(super_type_arg.Name()).ToCString(),
|
||||
String::Handle(zone, super_type_arg.Name()).ToCString(),
|
||||
ref_type.ToCString(), arguments.ToCString());
|
||||
}
|
||||
// In the typical case of an F-bounded type, the instantiation of the
|
||||
|
@ -628,7 +642,7 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
|
|||
// The super_type_arg was instantiated from a type being finalized.
|
||||
// We need to finish finalizing its type arguments, unless it is a
|
||||
// type parameter, in which case there is nothing more to do.
|
||||
AbstractType& unfinalized_type = AbstractType::Handle();
|
||||
AbstractType& unfinalized_type = AbstractType::Handle(zone);
|
||||
if (super_type_arg.IsTypeRef()) {
|
||||
unfinalized_type = TypeRef::Cast(super_type_arg).type();
|
||||
} else {
|
||||
|
@ -636,8 +650,9 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
|
|||
unfinalized_type = super_type_arg.ptr();
|
||||
}
|
||||
if (FLAG_trace_type_finalization) {
|
||||
THR_Print("Instantiated unfinalized '%s': '%s'\n",
|
||||
String::Handle(unfinalized_type.Name()).ToCString(),
|
||||
THR_Print(
|
||||
"Instantiated unfinalized '%s': '%s'\n",
|
||||
String::Handle(zone, unfinalized_type.Name()).ToCString(),
|
||||
unfinalized_type.ToCString());
|
||||
}
|
||||
if (unfinalized_type.IsType()) {
|
||||
|
@ -645,9 +660,9 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
|
|||
pending_types->Add(unfinalized_type);
|
||||
}
|
||||
const Class& super_cls =
|
||||
Class::Handle(unfinalized_type.type_class());
|
||||
Class::Handle(zone, unfinalized_type.type_class());
|
||||
const TypeArguments& super_args =
|
||||
TypeArguments::Handle(unfinalized_type.arguments());
|
||||
TypeArguments::Handle(zone, unfinalized_type.arguments());
|
||||
// Mark as finalized before finalizing to avoid cycles.
|
||||
unfinalized_type.SetIsFinalized();
|
||||
// Although the instantiator is different between cls and super_cls,
|
||||
|
@ -655,13 +670,14 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
|
|||
// divergence. Finalizing the type arguments of super_cls may indeed
|
||||
// recursively require instantiating the same type_refs already
|
||||
// present in the trail (see issue #29949).
|
||||
FinalizeTypeArguments(
|
||||
super_cls, super_args,
|
||||
FillAndFinalizeTypeArguments(
|
||||
zone, super_cls, super_args,
|
||||
super_cls.NumTypeArguments() - super_cls.NumTypeParameters(),
|
||||
pending_types, trail);
|
||||
if (FLAG_trace_type_finalization) {
|
||||
THR_Print("Finalized instantiated '%s': '%s'\n",
|
||||
String::Handle(unfinalized_type.Name()).ToCString(),
|
||||
THR_Print(
|
||||
"Finalized instantiated '%s': '%s'\n",
|
||||
String::Handle(zone, unfinalized_type.Name()).ToCString(),
|
||||
unfinalized_type.ToCString());
|
||||
}
|
||||
}
|
||||
|
@ -669,11 +685,38 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
|
|||
}
|
||||
arguments.SetTypeAt(i, super_type_arg);
|
||||
}
|
||||
FinalizeTypeArguments(super_class, arguments, super_offset, pending_types,
|
||||
trail);
|
||||
FillAndFinalizeTypeArguments(zone, super_class, arguments, super_offset,
|
||||
pending_types, trail);
|
||||
}
|
||||
}
|
||||
|
||||
TypeArgumentsPtr ClassFinalizer::FinalizeTypeArguments(
|
||||
Zone* zone,
|
||||
const TypeArguments& type_args,
|
||||
FinalizationKind finalization,
|
||||
PendingTypes* pending_types) {
|
||||
if (type_args.IsNull()) return TypeArguments::null();
|
||||
ASSERT(type_args.ptr() != Object::empty_type_arguments().ptr());
|
||||
const intptr_t len = type_args.Length();
|
||||
AbstractType& type = AbstractType::Handle(zone);
|
||||
AbstractType& finalized_type = AbstractType::Handle(zone);
|
||||
for (intptr_t i = 0; i < len; i++) {
|
||||
type = type_args.TypeAt(i);
|
||||
if (type.IsBeingFinalized()) {
|
||||
ASSERT(finalization < kCanonicalize);
|
||||
continue;
|
||||
}
|
||||
finalized_type = FinalizeType(type, kFinalize, pending_types);
|
||||
if (type.ptr() != finalized_type.ptr()) {
|
||||
type_args.SetTypeAt(i, finalized_type);
|
||||
}
|
||||
}
|
||||
if (finalization >= kCanonicalize) {
|
||||
return type_args.Canonicalize(Thread::Current(), nullptr);
|
||||
}
|
||||
return type_args.ptr();
|
||||
}
|
||||
|
||||
AbstractTypePtr ClassFinalizer::FinalizeType(const AbstractType& type,
|
||||
FinalizationKind finalization,
|
||||
PendingTypes* pending_types) {
|
||||
|
@ -701,8 +744,8 @@ AbstractTypePtr ClassFinalizer::FinalizeType(const AbstractType& type,
|
|||
return type.ptr();
|
||||
}
|
||||
|
||||
// Recursive types must be processed in FinalizeTypeArguments() and cannot be
|
||||
// encountered here.
|
||||
// Recursive types must be processed in FillAndFinalizeTypeArguments() and
|
||||
// cannot be encountered here.
|
||||
ASSERT(!type.IsBeingFinalized());
|
||||
|
||||
// Mark the type as being finalized in order to detect self reference.
|
||||
|
@ -737,17 +780,20 @@ AbstractTypePtr ClassFinalizer::FinalizeType(const AbstractType& type,
|
|||
type_parameter.set_parameterized_class_id(kClassCid);
|
||||
}
|
||||
|
||||
AbstractType& t = AbstractType::Handle(zone);
|
||||
t = type_parameter.bound();
|
||||
if (!t.IsBeingFinalized()) {
|
||||
t = FinalizeType(t, kFinalize);
|
||||
type_parameter.set_bound(t);
|
||||
AbstractType& upper_bound = AbstractType::Handle(zone);
|
||||
upper_bound = type_parameter.bound();
|
||||
if (upper_bound.IsBeingFinalized()) {
|
||||
if (upper_bound.IsTypeRef()) {
|
||||
// Nothing to do.
|
||||
} else {
|
||||
upper_bound = TypeRef::New(upper_bound);
|
||||
type_parameter.set_bound(upper_bound);
|
||||
upper_bound = FinalizeType(upper_bound, kFinalize);
|
||||
}
|
||||
} else {
|
||||
upper_bound = FinalizeType(upper_bound, kFinalize);
|
||||
type_parameter.set_bound(upper_bound);
|
||||
}
|
||||
t = type_parameter.default_argument();
|
||||
// The default argument cannot create a cycle with the type parameter.
|
||||
t = FinalizeType(t, kFinalize);
|
||||
type_parameter.set_default_argument(t);
|
||||
|
||||
type_parameter.SetIsFinalized();
|
||||
|
||||
if (FLAG_trace_type_finalization) {
|
||||
|
@ -781,7 +827,7 @@ AbstractTypePtr ClassFinalizer::FinalizeType(const AbstractType& type,
|
|||
pending_types->Add(type);
|
||||
|
||||
const intptr_t num_expanded_type_arguments =
|
||||
ExpandAndFinalizeTypeArguments(type, pending_types);
|
||||
ExpandAndFinalizeTypeArguments(zone, type, pending_types);
|
||||
|
||||
// Self referencing types may get finalized indirectly.
|
||||
if (!type.IsFinalized()) {
|
||||
|
@ -819,23 +865,12 @@ AbstractTypePtr ClassFinalizer::FinalizeSignature(Zone* zone,
|
|||
const FunctionType& signature,
|
||||
FinalizationKind finalization,
|
||||
PendingTypes* pending_types) {
|
||||
// Finalize signature type parameter upper bounds and default args.
|
||||
FinalizeTypeParameters(zone, Object::null_class(), signature, finalization,
|
||||
pending_types);
|
||||
|
||||
AbstractType& type = AbstractType::Handle(zone);
|
||||
AbstractType& finalized_type = AbstractType::Handle(zone);
|
||||
// Finalize signature type parameters, their upper bounds and default args.
|
||||
const intptr_t num_type_params = signature.NumTypeParameters();
|
||||
if (num_type_params > 0) {
|
||||
TypeParameter& type_param = TypeParameter::Handle(zone);
|
||||
const TypeArguments& type_params =
|
||||
TypeArguments::Handle(zone, signature.type_parameters());
|
||||
for (intptr_t i = 0; i < num_type_params; i++) {
|
||||
type_param ^= type_params.TypeAt(i);
|
||||
finalized_type ^= FinalizeType(type_param, kFinalize, pending_types);
|
||||
if (type_param.ptr() != finalized_type.ptr()) {
|
||||
type_params.SetTypeAt(i, TypeParameter::Cast(finalized_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize result type.
|
||||
type = signature.result_type();
|
||||
finalized_type = FinalizeType(type, kFinalize, pending_types);
|
||||
|
@ -984,6 +1019,7 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
|
|||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
UNREACHABLE();
|
||||
#else
|
||||
Zone* zone = thread->zone();
|
||||
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
|
||||
if (cls.is_type_finalized()) {
|
||||
return;
|
||||
|
@ -993,24 +1029,24 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
|
|||
THR_Print("Finalize types in %s\n", cls.ToCString());
|
||||
}
|
||||
// Finalize super class.
|
||||
Class& super_class = Class::Handle(cls.SuperClass());
|
||||
Class& super_class = Class::Handle(zone, cls.SuperClass());
|
||||
if (!super_class.IsNull()) {
|
||||
FinalizeTypesInClass(super_class);
|
||||
}
|
||||
// Finalize type parameters before finalizing the super type.
|
||||
FinalizeTypeParameters(cls, kFinalize);
|
||||
FinalizeTypeParameters(zone, cls, Object::null_function_type(),
|
||||
kCanonicalize);
|
||||
ASSERT(super_class.ptr() == cls.SuperClass()); // Not modified.
|
||||
ASSERT(super_class.IsNull() || super_class.is_type_finalized());
|
||||
FinalizeTypeParameters(cls, kCanonicalize);
|
||||
// Finalize super type.
|
||||
AbstractType& super_type = AbstractType::Handle(cls.super_type());
|
||||
AbstractType& super_type = AbstractType::Handle(zone, cls.super_type());
|
||||
if (!super_type.IsNull()) {
|
||||
super_type = FinalizeType(super_type);
|
||||
cls.set_super_type(super_type);
|
||||
}
|
||||
// Finalize interface types (but not necessarily interface classes).
|
||||
Array& interface_types = Array::Handle(cls.interfaces());
|
||||
AbstractType& interface_type = AbstractType::Handle();
|
||||
Array& interface_types = Array::Handle(zone, cls.interfaces());
|
||||
AbstractType& interface_type = AbstractType::Handle(zone);
|
||||
for (intptr_t i = 0; i < interface_types.Length(); i++) {
|
||||
interface_type ^= interface_types.At(i);
|
||||
interface_type = FinalizeType(interface_type);
|
||||
|
@ -1343,8 +1379,7 @@ void ClassFinalizer::VerifyImplicitFieldOffsets() {
|
|||
error = cls.EnsureIsFinalized(thread);
|
||||
ASSERT(error.IsNull());
|
||||
ASSERT(cls.NumTypeParameters() == 1);
|
||||
type_param ^= TypeParameter::RawCast(
|
||||
TypeArguments::Handle(cls.type_parameters()).TypeAt(0));
|
||||
type_param = cls.TypeParameterAt(0);
|
||||
ASSERT(Pointer::kNativeTypeArgPos == type_param.index());
|
||||
#endif
|
||||
}
|
||||
|
@ -1660,7 +1695,8 @@ void ClassFinalizer::RehashTypes() {
|
|||
for (intptr_t i = 0; i < typeparams.Length(); i++) {
|
||||
typeparam ^= typeparams.At(i);
|
||||
bool present = typeparams_table.Insert(typeparam);
|
||||
ASSERT(!present);
|
||||
// Two recursive types with different topology (and hashes) may be equal.
|
||||
ASSERT(!present || typeparam.IsRecursive());
|
||||
}
|
||||
object_store->set_canonical_type_parameters(typeparams_table.Release());
|
||||
|
||||
|
|
|
@ -79,6 +79,13 @@ class ClassFinalizer : public AllStatic {
|
|||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
private:
|
||||
// Finalize given type argument vector.
|
||||
static TypeArgumentsPtr FinalizeTypeArguments(
|
||||
Zone* zone,
|
||||
const TypeArguments& type_args,
|
||||
FinalizationKind finalization = kCanonicalize,
|
||||
PendingTypes* pending_types = NULL);
|
||||
|
||||
// Finalize the types in the signature and the signature itself.
|
||||
static AbstractTypePtr FinalizeSignature(
|
||||
Zone* zone,
|
||||
|
@ -88,14 +95,20 @@ class ClassFinalizer : public AllStatic {
|
|||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
static void AllocateEnumValues(const Class& enum_cls);
|
||||
static void FinalizeTypeParameters(
|
||||
const Class& cls,
|
||||
FinalizationKind finalization = kCanonicalize);
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
static intptr_t ExpandAndFinalizeTypeArguments(const AbstractType& type,
|
||||
static void FinalizeTypeParameters(
|
||||
Zone* zone,
|
||||
const Class& cls,
|
||||
const FunctionType& signature,
|
||||
FinalizationKind finalization = kCanonicalize,
|
||||
PendingTypes* pending_types = NULL);
|
||||
|
||||
static intptr_t ExpandAndFinalizeTypeArguments(Zone* zone,
|
||||
const AbstractType& type,
|
||||
PendingTypes* pending_types);
|
||||
static void FinalizeTypeArguments(const Class& cls,
|
||||
static void FillAndFinalizeTypeArguments(Zone* zone,
|
||||
const Class& cls,
|
||||
const TypeArguments& arguments,
|
||||
intptr_t num_uninitialized_arguments,
|
||||
PendingTypes* pending_types,
|
||||
|
|
|
@ -21,6 +21,7 @@ typedef uint16_t ClassIdTagType;
|
|||
V(Class) \
|
||||
V(PatchClass) \
|
||||
V(Function) \
|
||||
V(TypeParameters) \
|
||||
V(ClosureData) \
|
||||
V(FfiTrampolineData) \
|
||||
V(Field) \
|
||||
|
|
|
@ -533,8 +533,14 @@ class CanonicalSetSerializationCluster : public SerializationCluster {
|
|||
element ^= ptr;
|
||||
intptr_t entry = -1;
|
||||
const bool present = table.FindKeyOrDeletedOrUnused(element, &entry);
|
||||
ASSERT(!present);
|
||||
if (!present) {
|
||||
table.InsertKey(entry, element);
|
||||
} else {
|
||||
// Two recursive types with different topology (and hashes)
|
||||
// may be equal.
|
||||
ASSERT(element.IsRecursive());
|
||||
objects_[num_occupied++] = ptr;
|
||||
}
|
||||
} else {
|
||||
objects_[num_occupied++] = ptr;
|
||||
}
|
||||
|
@ -685,6 +691,74 @@ class CanonicalSetDeserializationCluster : public DeserializationCluster {
|
|||
}
|
||||
};
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
class TypeParametersSerializationCluster : public SerializationCluster {
|
||||
public:
|
||||
TypeParametersSerializationCluster()
|
||||
: SerializationCluster("TypeParameters",
|
||||
kTypeParametersCid,
|
||||
compiler::target::TypeParameters::InstanceSize()) {
|
||||
}
|
||||
~TypeParametersSerializationCluster() {}
|
||||
|
||||
void Trace(Serializer* s, ObjectPtr object) {
|
||||
TypeParametersPtr type_params = TypeParameters::RawCast(object);
|
||||
objects_.Add(type_params);
|
||||
PushFromTo(type_params);
|
||||
}
|
||||
|
||||
void WriteAlloc(Serializer* s) {
|
||||
const intptr_t count = objects_.length();
|
||||
s->WriteUnsigned(count);
|
||||
for (intptr_t i = 0; i < count; i++) {
|
||||
TypeParametersPtr type_params = objects_[i];
|
||||
s->AssignRef(type_params);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteFill(Serializer* s) {
|
||||
const intptr_t count = objects_.length();
|
||||
for (intptr_t i = 0; i < count; i++) {
|
||||
TypeParametersPtr type_params = objects_[i];
|
||||
AutoTraceObject(type_params);
|
||||
WriteFromTo(type_params);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
GrowableArray<TypeParametersPtr> objects_;
|
||||
};
|
||||
#endif // !DART_PRECOMPILED_RUNTIME
|
||||
|
||||
class TypeParametersDeserializationCluster : public DeserializationCluster {
|
||||
public:
|
||||
TypeParametersDeserializationCluster()
|
||||
: DeserializationCluster("TypeParameters") {}
|
||||
~TypeParametersDeserializationCluster() {}
|
||||
|
||||
void ReadAlloc(Deserializer* d) {
|
||||
start_index_ = d->next_index();
|
||||
PageSpace* old_space = d->heap()->old_space();
|
||||
const intptr_t count = d->ReadUnsigned();
|
||||
for (intptr_t i = 0; i < count; i++) {
|
||||
d->AssignRef(
|
||||
AllocateUninitialized(old_space, TypeParameters::InstanceSize()));
|
||||
}
|
||||
stop_index_ = d->next_index();
|
||||
}
|
||||
|
||||
void ReadFill(Deserializer* d, bool primary) {
|
||||
ASSERT(!is_canonical()); // Never canonical.
|
||||
for (intptr_t id = start_index_; id < stop_index_; id++) {
|
||||
TypeParametersPtr type_params =
|
||||
static_cast<TypeParametersPtr>(d->Ref(id));
|
||||
Deserializer::InitializeHeader(type_params, kTypeParametersCid,
|
||||
TypeParameters::InstanceSize());
|
||||
ReadFromTo(type_params);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
class TypeArgumentsSerializationCluster
|
||||
: public CanonicalSetSerializationCluster<CanonicalTypeArgumentsSet,
|
||||
|
@ -1088,7 +1162,6 @@ class ClosureDataSerializationCluster : public SerializationCluster {
|
|||
}
|
||||
s->Push(data->untag()->parent_function());
|
||||
s->Push(data->untag()->closure());
|
||||
s->Push(data->untag()->default_type_arguments());
|
||||
}
|
||||
|
||||
void WriteAlloc(Serializer* s) {
|
||||
|
@ -1110,7 +1183,6 @@ class ClosureDataSerializationCluster : public SerializationCluster {
|
|||
}
|
||||
WriteCompressedField(data, parent_function);
|
||||
WriteCompressedField(data, closure);
|
||||
WriteCompressedField(data, default_type_arguments);
|
||||
s->WriteUnsigned(
|
||||
static_cast<intptr_t>(data->untag()->default_type_arguments_kind_));
|
||||
}
|
||||
|
@ -1151,8 +1223,6 @@ class ClosureDataDeserializationCluster : public DeserializationCluster {
|
|||
}
|
||||
data->untag()->parent_function_ = static_cast<FunctionPtr>(d->ReadRef());
|
||||
data->untag()->closure_ = static_cast<InstancePtr>(d->ReadRef());
|
||||
data->untag()->default_type_arguments_ =
|
||||
static_cast<TypeArgumentsPtr>(d->ReadRef());
|
||||
data->untag()->default_type_arguments_kind_ =
|
||||
static_cast<ClosureData::DefaultTypeArgumentsKind>(d->ReadUnsigned());
|
||||
}
|
||||
|
@ -4218,8 +4288,8 @@ class TypeParameterSerializationCluster
|
|||
AutoTraceObject(type);
|
||||
WriteFromTo(type);
|
||||
s->Write<int32_t>(type->untag()->parameterized_class_id_);
|
||||
s->Write<uint16_t>(type->untag()->base_);
|
||||
s->Write<uint16_t>(type->untag()->index_);
|
||||
s->Write<uint8_t>(type->untag()->base_);
|
||||
s->Write<uint8_t>(type->untag()->index_);
|
||||
ASSERT(type->untag()->flags_ < (1 << UntaggedTypeParameter::kFlagsBitSize));
|
||||
ASSERT(type->untag()->nullability_ < (1 << kNullabilityBitSize));
|
||||
static_assert(UntaggedTypeParameter::kFlagsBitSize + kNullabilityBitSize <=
|
||||
|
@ -4264,8 +4334,8 @@ class TypeParameterDeserializationCluster
|
|||
primary && is_canonical());
|
||||
ReadFromTo(type);
|
||||
type->untag()->parameterized_class_id_ = d->Read<int32_t>();
|
||||
type->untag()->base_ = d->Read<uint16_t>();
|
||||
type->untag()->index_ = d->Read<uint16_t>();
|
||||
type->untag()->base_ = d->Read<uint8_t>();
|
||||
type->untag()->index_ = d->Read<uint8_t>();
|
||||
const uint8_t combined = d->Read<uint8_t>();
|
||||
type->untag()->flags_ = combined >> kNullabilityBitSize;
|
||||
type->untag()->nullability_ = combined & kNullabilityBitMask;
|
||||
|
@ -6536,6 +6606,8 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid,
|
|||
switch (cid) {
|
||||
case kClassCid:
|
||||
return new (Z) ClassSerializationCluster(num_cids_ + num_tlc_cids_);
|
||||
case kTypeParametersCid:
|
||||
return new (Z) TypeParametersSerializationCluster();
|
||||
case kTypeArgumentsCid:
|
||||
return new (Z) TypeArgumentsSerializationCluster(
|
||||
is_canonical, cluster_represents_canonical_set);
|
||||
|
@ -7388,6 +7460,8 @@ DeserializationCluster* Deserializer::ReadCluster() {
|
|||
case kClassCid:
|
||||
ASSERT(!is_canonical);
|
||||
return new (Z) ClassDeserializationCluster();
|
||||
case kTypeParametersCid:
|
||||
return new (Z) TypeParametersDeserializationCluster();
|
||||
case kTypeArgumentsCid:
|
||||
return new (Z)
|
||||
TypeArgumentsDeserializationCluster(is_canonical, !is_non_root_unit_);
|
||||
|
|
|
@ -962,7 +962,7 @@ void Precompiler::AddTypesOf(const Class& cls) {
|
|||
AddType(type);
|
||||
}
|
||||
|
||||
AddTypeArguments(TypeArguments::Handle(Z, cls.type_parameters()));
|
||||
AddTypeParameters(TypeParameters::Handle(Z, cls.type_parameters()));
|
||||
|
||||
type = cls.super_type();
|
||||
AddType(type);
|
||||
|
@ -991,15 +991,6 @@ void Precompiler::AddTypesOf(const Function& function) {
|
|||
const FunctionType& signature = FunctionType::Handle(Z, function.signature());
|
||||
AddType(signature);
|
||||
|
||||
// At this point, ensure any cached default type arguments are canonicalized.
|
||||
function.UpdateCachedDefaultTypeArguments(thread());
|
||||
if (function.CachesDefaultTypeArguments()) {
|
||||
const auto& defaults = TypeArguments::Handle(
|
||||
Z, function.default_type_arguments(/*kind_out=*/nullptr));
|
||||
ASSERT(defaults.IsCanonical());
|
||||
AddTypeArguments(defaults);
|
||||
}
|
||||
|
||||
// A class may have all functions inlined except a local function.
|
||||
const Class& owner = Class::Handle(Z, function.Owner());
|
||||
AddTypesOf(owner);
|
||||
|
@ -1054,10 +1045,8 @@ void Precompiler::AddType(const AbstractType& abstype) {
|
|||
if (typeparams_to_retain_.HasKey(¶m)) return;
|
||||
typeparams_to_retain_.Insert(&TypeParameter::ZoneHandle(Z, param.ptr()));
|
||||
|
||||
auto& type = AbstractType::Handle(Z, param.bound());
|
||||
AddType(type);
|
||||
type = param.default_argument();
|
||||
AddType(type);
|
||||
auto& bound = AbstractType::Handle(Z, param.bound());
|
||||
AddType(bound);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1067,7 +1056,7 @@ void Precompiler::AddType(const AbstractType& abstype) {
|
|||
FunctionType::ZoneHandle(Z, FunctionType::Cast(abstype).ptr());
|
||||
functiontypes_to_retain_.Insert(&signature);
|
||||
|
||||
AddTypeArguments(TypeArguments::Handle(Z, signature.type_parameters()));
|
||||
AddTypeParameters(TypeParameters::Handle(Z, signature.type_parameters()));
|
||||
|
||||
AbstractType& type = AbstractType::Handle(Z);
|
||||
type = signature.result_type();
|
||||
|
@ -1095,6 +1084,16 @@ void Precompiler::AddType(const AbstractType& abstype) {
|
|||
}
|
||||
}
|
||||
|
||||
void Precompiler::AddTypeParameters(const TypeParameters& params) {
|
||||
if (params.IsNull()) return;
|
||||
|
||||
TypeArguments& args = TypeArguments::Handle();
|
||||
args = params.bounds();
|
||||
AddTypeArguments(args);
|
||||
args = params.defaults();
|
||||
AddTypeArguments(args);
|
||||
}
|
||||
|
||||
void Precompiler::AddTypeArguments(const TypeArguments& args) {
|
||||
if (args.IsNull()) return;
|
||||
|
||||
|
|
|
@ -298,6 +298,7 @@ class Precompiler : public ValueObject {
|
|||
void AddType(const AbstractType& type);
|
||||
void AddTypesOf(const Class& cls);
|
||||
void AddTypesOf(const Function& function);
|
||||
void AddTypeParameters(const TypeParameters& params);
|
||||
void AddTypeArguments(const TypeArguments& args);
|
||||
void AddCalleesOf(const Function& function, intptr_t gop_offset);
|
||||
void AddCalleesOfHelper(const Object& entry,
|
||||
|
|
|
@ -2694,7 +2694,6 @@ bool LoadFieldInstr::IsImmutableLengthLoad() const {
|
|||
case Slot::Kind::kClosure_function_type_arguments:
|
||||
case Slot::Kind::kClosure_instantiator_type_arguments:
|
||||
case Slot::Kind::kClosure_hash:
|
||||
case Slot::Kind::kClosureData_default_type_arguments:
|
||||
case Slot::Kind::kCapturedVariable:
|
||||
case Slot::Kind::kDartField:
|
||||
case Slot::Kind::kFunction_data:
|
||||
|
@ -2705,8 +2704,11 @@ bool LoadFieldInstr::IsImmutableLengthLoad() const {
|
|||
case Slot::Kind::kPointerBase_data_field:
|
||||
case Slot::Kind::kType_arguments:
|
||||
case Slot::Kind::kTypeArgumentsIndex:
|
||||
case Slot::Kind::kTypeParameters_names:
|
||||
case Slot::Kind::kTypeParameters_flags:
|
||||
case Slot::Kind::kTypeParameters_bounds:
|
||||
case Slot::Kind::kTypeParameters_defaults:
|
||||
case Slot::Kind::kTypeParameter_bound:
|
||||
case Slot::Kind::kTypeParameter_name:
|
||||
case Slot::Kind::kUnhandledException_exception:
|
||||
case Slot::Kind::kUnhandledException_stacktrace:
|
||||
case Slot::Kind::kWeakProperty_key:
|
||||
|
|
|
@ -52,18 +52,14 @@ ClassPtr GetClass(const Library& lib, const char* name) {
|
|||
return cls.ptr();
|
||||
}
|
||||
|
||||
TypeParameterPtr GetClassTypeParameter(const Class& klass, const char* name) {
|
||||
const auto& param = TypeParameter::Handle(
|
||||
klass.LookupTypeParameter(String::Handle(String::New(name))));
|
||||
TypeParameterPtr GetClassTypeParameter(const Class& klass, intptr_t index) {
|
||||
const auto& param = TypeParameter::Handle(klass.TypeParameterAt(index));
|
||||
EXPECT(!param.IsNull());
|
||||
return param.ptr();
|
||||
}
|
||||
|
||||
TypeParameterPtr GetFunctionTypeParameter(const Function& fun,
|
||||
const char* name) {
|
||||
intptr_t fun_level = 0;
|
||||
const auto& param = TypeParameter::Handle(
|
||||
fun.LookupTypeParameter(String::Handle(String::New(name)), &fun_level));
|
||||
TypeParameterPtr GetFunctionTypeParameter(const Function& fun, intptr_t index) {
|
||||
const auto& param = TypeParameter::Handle(fun.TypeParameterAt(index));
|
||||
EXPECT(!param.IsNull());
|
||||
return param.ptr();
|
||||
}
|
||||
|
|
|
@ -58,9 +58,8 @@ LibraryPtr LoadTestScript(const char* script,
|
|||
|
||||
FunctionPtr GetFunction(const Library& lib, const char* name);
|
||||
ClassPtr GetClass(const Library& lib, const char* name);
|
||||
TypeParameterPtr GetClassTypeParameter(const Class& klass, const char* name);
|
||||
TypeParameterPtr GetFunctionTypeParameter(const Function& fun,
|
||||
const char* name);
|
||||
TypeParameterPtr GetClassTypeParameter(const Class& klass, intptr_t index);
|
||||
TypeParameterPtr GetFunctionTypeParameter(const Function& fun, intptr_t index);
|
||||
|
||||
ObjectPtr Invoke(const Library& lib, const char* name);
|
||||
|
||||
|
|
|
@ -2797,7 +2797,6 @@ void LoadFieldInstr::InferRange(RangeAnalysis* analysis, Range* range) {
|
|||
case Slot::Kind::kClosure_function:
|
||||
case Slot::Kind::kClosure_function_type_arguments:
|
||||
case Slot::Kind::kClosure_instantiator_type_arguments:
|
||||
case Slot::Kind::kClosureData_default_type_arguments:
|
||||
case Slot::Kind::kFunction_data:
|
||||
case Slot::Kind::kFunction_signature:
|
||||
case Slot::Kind::kFunctionType_parameter_names:
|
||||
|
@ -2807,8 +2806,11 @@ void LoadFieldInstr::InferRange(RangeAnalysis* analysis, Range* range) {
|
|||
case Slot::Kind::kTypedDataView_data:
|
||||
case Slot::Kind::kType_arguments:
|
||||
case Slot::Kind::kTypeArgumentsIndex:
|
||||
case Slot::Kind::kTypeParameters_names:
|
||||
case Slot::Kind::kTypeParameters_flags:
|
||||
case Slot::Kind::kTypeParameters_bounds:
|
||||
case Slot::Kind::kTypeParameters_defaults:
|
||||
case Slot::Kind::kTypeParameter_bound:
|
||||
case Slot::Kind::kTypeParameter_name:
|
||||
case Slot::Kind::kUnhandledException_exception:
|
||||
case Slot::Kind::kUnhandledException_stacktrace:
|
||||
case Slot::Kind::kWeakProperty_key:
|
||||
|
|
|
@ -58,10 +58,13 @@ class ParsedFunction;
|
|||
FINAL) \
|
||||
V(Closure, UntaggedClosure, delayed_type_arguments, TypeArguments, FINAL) \
|
||||
V(Closure, UntaggedClosure, function_type_arguments, TypeArguments, FINAL) \
|
||||
V(ClosureData, UntaggedClosureData, default_type_arguments, TypeArguments, \
|
||||
FINAL_COMPRESSED) \
|
||||
V(Type, UntaggedType, arguments, TypeArguments, FINAL_COMPRESSED) \
|
||||
V(FunctionType, UntaggedFunctionType, type_parameters, TypeArguments, \
|
||||
V(FunctionType, UntaggedFunctionType, type_parameters, TypeParameters, \
|
||||
FINAL_COMPRESSED) \
|
||||
V(TypeParameters, UntaggedTypeParameters, flags, Array, FINAL_COMPRESSED) \
|
||||
V(TypeParameters, UntaggedTypeParameters, bounds, TypeArguments, \
|
||||
FINAL_COMPRESSED) \
|
||||
V(TypeParameters, UntaggedTypeParameters, defaults, TypeArguments, \
|
||||
FINAL_COMPRESSED) \
|
||||
V(WeakProperty, UntaggedWeakProperty, key, Dynamic, VAR) \
|
||||
V(WeakProperty, UntaggedWeakProperty, value, Dynamic, VAR)
|
||||
|
@ -107,8 +110,8 @@ class ParsedFunction;
|
|||
V(ArgumentsDescriptor, UntaggedArray, size, Smi, FINAL) \
|
||||
V(PointerBase, UntaggedPointerBase, data_field, Dynamic, FINAL) \
|
||||
V(TypeArguments, UntaggedTypeArguments, length, Smi, FINAL_COMPRESSED) \
|
||||
V(TypeParameters, UntaggedTypeParameters, names, Array, FINAL_COMPRESSED) \
|
||||
V(TypeParameter, UntaggedTypeParameter, bound, Dynamic, FINAL_COMPRESSED) \
|
||||
V(TypeParameter, UntaggedTypeParameter, name, Dynamic, FINAL_COMPRESSED) \
|
||||
V(UnhandledException, UntaggedUnhandledException, exception, Dynamic, \
|
||||
FINAL_COMPRESSED) \
|
||||
V(UnhandledException, UntaggedUnhandledException, stacktrace, Dynamic, \
|
||||
|
|
|
@ -1387,14 +1387,12 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
|
|||
ASSERT(class_table->HasValidClassAt(kFfiPointerCid));
|
||||
const auto& pointer_class =
|
||||
Class::ZoneHandle(H.zone(), class_table->At(kFfiPointerCid));
|
||||
const auto& pointer_type_args =
|
||||
TypeArguments::Handle(pointer_class.type_parameters());
|
||||
const auto& pointer_type_arg =
|
||||
AbstractType::ZoneHandle(pointer_type_args.TypeAt(0));
|
||||
const auto& pointer_type_param =
|
||||
TypeParameter::ZoneHandle(pointer_class.TypeParameterAt(0));
|
||||
|
||||
// But we type check it as a method on a generic class at runtime.
|
||||
body += LoadLocal(arg_value); // value.
|
||||
body += Constant(pointer_type_arg); // dst_type.
|
||||
body += Constant(pointer_type_param); // dst_type.
|
||||
// We pass the Pointer type argument as instantiator_type_args.
|
||||
//
|
||||
// Call sites to this recognized method are guaranteed to pass a
|
||||
|
@ -1767,26 +1765,27 @@ void FlowGraphBuilder::BuildTypeArgumentTypeChecks(TypeChecksToBuild mode,
|
|||
ASSERT(!forwarding_target->IsNull());
|
||||
}
|
||||
|
||||
TypeArguments& type_parameters = TypeArguments::Handle(Z);
|
||||
TypeParameters& type_parameters = TypeParameters::Handle(Z);
|
||||
if (dart_function.IsFactory()) {
|
||||
type_parameters = Class::Handle(Z, dart_function.Owner()).type_parameters();
|
||||
} else {
|
||||
type_parameters = dart_function.type_parameters();
|
||||
}
|
||||
intptr_t num_type_params = type_parameters.Length();
|
||||
const intptr_t num_type_params = type_parameters.Length();
|
||||
if (num_type_params == 0) return;
|
||||
if (forwarding_target != nullptr) {
|
||||
type_parameters = forwarding_target->type_parameters();
|
||||
ASSERT(type_parameters.Length() == num_type_params);
|
||||
}
|
||||
|
||||
if (type_parameters.AllDynamicBounds()) {
|
||||
return; // All bounds are dynamic.
|
||||
}
|
||||
TypeParameter& type_param = TypeParameter::Handle(Z);
|
||||
String& name = String::Handle(Z);
|
||||
AbstractType& bound = AbstractType::Handle(Z);
|
||||
Fragment check_bounds;
|
||||
for (intptr_t i = 0; i < num_type_params; ++i) {
|
||||
type_param ^= type_parameters.TypeAt(i);
|
||||
|
||||
bound = type_param.bound();
|
||||
bound = type_parameters.BoundAt(i);
|
||||
if (bound.IsTopTypeForSubtyping()) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1795,19 +1794,26 @@ void FlowGraphBuilder::BuildTypeArgumentTypeChecks(TypeChecksToBuild mode,
|
|||
case TypeChecksToBuild::kCheckAllTypeParameterBounds:
|
||||
break;
|
||||
case TypeChecksToBuild::kCheckCovariantTypeParameterBounds:
|
||||
if (!type_param.IsGenericCovariantImpl()) {
|
||||
if (!type_parameters.IsGenericCovariantImplAt(i)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case TypeChecksToBuild::kCheckNonCovariantTypeParameterBounds:
|
||||
if (type_param.IsGenericCovariantImpl()) {
|
||||
if (type_parameters.IsGenericCovariantImplAt(i)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
name = type_param.name();
|
||||
name = type_parameters.NameAt(i);
|
||||
|
||||
if (forwarding_target != nullptr) {
|
||||
type_param = forwarding_target->TypeParameterAt(i);
|
||||
} else if (dart_function.IsFactory()) {
|
||||
type_param = Class::Handle(Z, dart_function.Owner()).TypeParameterAt(i);
|
||||
} else {
|
||||
type_param = dart_function.TypeParameterAt(i);
|
||||
}
|
||||
ASSERT(type_param.IsFinalized());
|
||||
check_bounds +=
|
||||
AssertSubtype(TokenPosition::kNoSource, type_param, bound, name);
|
||||
|
@ -2076,8 +2082,8 @@ struct FlowGraphBuilder::ClosureCallInfo {
|
|||
const ArgumentsDescriptor descriptor;
|
||||
ParsedFunction::DynamicClosureCallVars* const vars;
|
||||
|
||||
// Set up by BuildDynamicCallChecks() when needed. These values are
|
||||
// read-only, so they don't need real local variables and are created
|
||||
// Set up by BuildClosureCallDefaultTypeHandling() when needed. These values
|
||||
// are read-only, so they don't need real local variables and are created
|
||||
// using MakeTemporary().
|
||||
LocalVariable* signature = nullptr;
|
||||
LocalVariable* num_fixed_params = nullptr;
|
||||
|
@ -2087,8 +2093,11 @@ struct FlowGraphBuilder::ClosureCallInfo {
|
|||
LocalVariable* parameter_names = nullptr;
|
||||
LocalVariable* parameter_types = nullptr;
|
||||
LocalVariable* type_parameters = nullptr;
|
||||
LocalVariable* num_type_parameters = nullptr;
|
||||
LocalVariable* type_parameter_flags = nullptr;
|
||||
LocalVariable* instantiator_type_args = nullptr;
|
||||
LocalVariable* parent_function_type_args = nullptr;
|
||||
LocalVariable* num_parent_type_args = nullptr;
|
||||
};
|
||||
|
||||
Fragment FlowGraphBuilder::TestClosureFunctionGeneric(
|
||||
|
@ -2239,8 +2248,8 @@ Fragment FlowGraphBuilder::BuildClosureCallDefaultTypeHandling(
|
|||
store_default += BranchIfEqual(&can_share_instantiator, &can_share_function);
|
||||
|
||||
Fragment instantiated(is_instantiated);
|
||||
instantiated += LoadLocal(closure_data);
|
||||
instantiated += LoadNativeField(Slot::ClosureData_default_type_arguments());
|
||||
instantiated += LoadLocal(info.type_parameters);
|
||||
instantiated += LoadNativeField(Slot::TypeParameters_defaults());
|
||||
instantiated += StoreLocal(info.vars->function_type_args);
|
||||
instantiated += Drop();
|
||||
instantiated += Goto(done);
|
||||
|
@ -2252,9 +2261,8 @@ Fragment FlowGraphBuilder::BuildClosureCallDefaultTypeHandling(
|
|||
// can be used within the defaults).
|
||||
do_instantiation += LoadLocal(info.parent_function_type_args);
|
||||
// Load the default type arguments to instantiate.
|
||||
do_instantiation += LoadLocal(closure_data);
|
||||
do_instantiation +=
|
||||
LoadNativeField(Slot::ClosureData_default_type_arguments());
|
||||
do_instantiation += LoadLocal(info.type_parameters);
|
||||
do_instantiation += LoadNativeField(Slot::TypeParameters_defaults());
|
||||
do_instantiation += InstantiateDynamicTypeArguments();
|
||||
do_instantiation += StoreLocal(info.vars->function_type_args);
|
||||
do_instantiation += Drop();
|
||||
|
@ -2433,7 +2441,8 @@ Fragment FlowGraphBuilder::BuildClosureCallArgumentsValidCheck(
|
|||
check_type_args_length += BranchIfNull(&null, ¬_null);
|
||||
check_type_args_length.current = not_null; // Continue in non-error case.
|
||||
check_type_args_length += LoadLocal(info.type_parameters);
|
||||
check_type_args_length += LoadNativeField(Slot::TypeArguments_length());
|
||||
check_type_args_length += LoadNativeField(Slot::TypeParameters_names());
|
||||
check_type_args_length += LoadNativeField(Slot::Array_length());
|
||||
check_type_args_length += IntConstant(info.descriptor.TypeArgsLen());
|
||||
TargetEntryInstr *equal, *not_equal;
|
||||
check_type_args_length += BranchIfEqual(&equal, ¬_equal);
|
||||
|
@ -2522,6 +2531,16 @@ Fragment FlowGraphBuilder::BuildClosureCallTypeArgumentsTypeCheck(
|
|||
// We assume that the value stored in :t_type_parameters is not null (i.e.,
|
||||
// the function stored in :t_function is generic).
|
||||
Fragment loop_init;
|
||||
|
||||
// A null bounds vector represents a vector of dynamic and no check is needed.
|
||||
loop_init += LoadLocal(info.type_parameters);
|
||||
loop_init += LoadNativeField(Slot::TypeParameters_bounds());
|
||||
TargetEntryInstr *null_bounds, *non_null_bounds;
|
||||
loop_init += BranchIfNull(&null_bounds, &non_null_bounds);
|
||||
|
||||
Fragment(null_bounds) + Goto(done);
|
||||
|
||||
loop_init.current = non_null_bounds;
|
||||
// Loop over the type parameters array.
|
||||
loop_init += IntConstant(0);
|
||||
loop_init += StoreLocal(info.vars->current_param_index);
|
||||
|
@ -2530,54 +2549,93 @@ Fragment FlowGraphBuilder::BuildClosureCallTypeArgumentsTypeCheck(
|
|||
|
||||
Fragment loop_check(loop);
|
||||
loop_check += LoadLocal(info.vars->current_param_index);
|
||||
loop_check += LoadLocal(info.type_parameters);
|
||||
loop_check += LoadNativeField(Slot::TypeArguments_length());
|
||||
loop_check += LoadLocal(info.num_type_parameters);
|
||||
loop_check += SmiRelationalOp(Token::kLT);
|
||||
TargetEntryInstr *more, *no_more;
|
||||
loop_check += BranchIfTrue(&more, &no_more);
|
||||
|
||||
Fragment(no_more) + Goto(done);
|
||||
|
||||
Fragment loop_body(more);
|
||||
loop_body += LoadLocal(info.type_parameters);
|
||||
loop_body += LoadLocal(info.vars->current_param_index);
|
||||
loop_body += LoadIndexed(
|
||||
kTypeArgumentsCid, /*index_scale*/ compiler::target::kCompressedWordSize);
|
||||
LocalVariable* current_param = MakeTemporary("current_param"); // Read-only.
|
||||
|
||||
// One read-only local variable on stack (param) to drop after joining.
|
||||
Fragment loop_test_flag(more);
|
||||
JoinEntryInstr* next = BuildJoinEntry();
|
||||
JoinEntryInstr* check = BuildJoinEntry();
|
||||
loop_test_flag += LoadLocal(info.type_parameter_flags);
|
||||
TargetEntryInstr *null_flags, *non_null_flags;
|
||||
loop_test_flag += BranchIfNull(&null_flags, &non_null_flags);
|
||||
|
||||
loop_body += LoadLocal(current_param);
|
||||
loop_body += LoadNativeField(Slot::TypeParameter_flags());
|
||||
loop_body += Box(kUnboxedUint8);
|
||||
loop_body += IntConstant(
|
||||
UntaggedTypeParameter::GenericCovariantImplBit::mask_in_place());
|
||||
loop_body += SmiBinaryOp(Token::kBIT_AND);
|
||||
loop_body += IntConstant(0);
|
||||
Fragment(null_flags) + Goto(check); // Check type if null (non-covariant).
|
||||
|
||||
loop_test_flag.current = non_null_flags; // Test flags if not null.
|
||||
loop_test_flag += LoadLocal(info.type_parameter_flags);
|
||||
loop_test_flag += LoadLocal(info.vars->current_param_index);
|
||||
loop_test_flag += IntConstant(TypeParameters::kFlagsPerSmiShift);
|
||||
loop_test_flag += SmiBinaryOp(Token::kSHR);
|
||||
loop_test_flag += LoadIndexed(kArrayCid);
|
||||
loop_test_flag += LoadLocal(info.vars->current_param_index);
|
||||
loop_test_flag += IntConstant(TypeParameters::kFlagsPerSmiMask);
|
||||
loop_test_flag += SmiBinaryOp(Token::kBIT_AND);
|
||||
loop_test_flag += SmiBinaryOp(Token::kSHR);
|
||||
loop_test_flag += IntConstant(1);
|
||||
loop_test_flag += SmiBinaryOp(Token::kBIT_AND);
|
||||
loop_test_flag += IntConstant(0);
|
||||
TargetEntryInstr *is_noncovariant, *is_covariant;
|
||||
loop_body += BranchIfEqual(&is_noncovariant, &is_covariant);
|
||||
loop_test_flag += BranchIfEqual(&is_noncovariant, &is_covariant);
|
||||
|
||||
Fragment(is_covariant) + Goto(next); // Continue if covariant.
|
||||
Fragment(is_noncovariant) + Goto(check); // Check type if non-covariant.
|
||||
|
||||
loop_body.current = is_noncovariant; // Type check if non-covariant.
|
||||
loop_body += LoadLocal(info.instantiator_type_args);
|
||||
loop_body += LoadLocal(info.vars->function_type_args);
|
||||
// Load parameter.
|
||||
loop_body += LoadLocal(current_param);
|
||||
// Load bounds from parameter.
|
||||
loop_body += LoadLocal(current_param);
|
||||
loop_body += LoadNativeField(Slot::TypeParameter_bound());
|
||||
// Load name from parameter.
|
||||
loop_body += LoadLocal(current_param);
|
||||
loop_body += LoadNativeField(Slot::TypeParameter_name());
|
||||
// Assert that the type the parameter is instantiated as is consistent with
|
||||
// the bounds of the parameter.
|
||||
loop_body += AssertSubtype(TokenPosition::kNoSource);
|
||||
loop_body += Goto(next);
|
||||
Fragment loop_prep_type_param(check);
|
||||
JoinEntryInstr* dynamic_type_param = BuildJoinEntry();
|
||||
JoinEntryInstr* call = BuildJoinEntry();
|
||||
|
||||
// Load type argument already stored in function_type_args if non null.
|
||||
loop_prep_type_param += LoadLocal(info.vars->function_type_args);
|
||||
TargetEntryInstr *null_ftav, *non_null_ftav;
|
||||
loop_prep_type_param += BranchIfNull(&null_ftav, &non_null_ftav);
|
||||
|
||||
Fragment(null_ftav) + Goto(dynamic_type_param);
|
||||
|
||||
loop_prep_type_param.current = non_null_ftav;
|
||||
loop_prep_type_param += LoadLocal(info.vars->function_type_args);
|
||||
loop_prep_type_param += LoadLocal(info.vars->current_param_index);
|
||||
loop_prep_type_param += LoadLocal(info.num_parent_type_args);
|
||||
loop_prep_type_param += SmiBinaryOp(Token::kADD, /*is_truncating=*/true);
|
||||
loop_prep_type_param += LoadIndexed(
|
||||
kTypeArgumentsCid, /*index_scale*/ compiler::target::kCompressedWordSize);
|
||||
loop_prep_type_param += StoreLocal(info.vars->current_type_param);
|
||||
loop_prep_type_param += Drop();
|
||||
loop_prep_type_param += Goto(call);
|
||||
|
||||
Fragment loop_dynamic_type_param(dynamic_type_param);
|
||||
// If function_type_args is null, the instantiated type param is dynamic.
|
||||
loop_dynamic_type_param += Constant(Type::ZoneHandle(Type::DynamicType()));
|
||||
loop_dynamic_type_param += StoreLocal(info.vars->current_type_param);
|
||||
loop_dynamic_type_param += Drop();
|
||||
loop_dynamic_type_param += Goto(call);
|
||||
|
||||
Fragment loop_call_check(call);
|
||||
// Load instantiators.
|
||||
loop_call_check += LoadLocal(info.instantiator_type_args);
|
||||
loop_call_check += LoadLocal(info.vars->function_type_args);
|
||||
// Load instantiated type parameter.
|
||||
loop_call_check += LoadLocal(info.vars->current_type_param);
|
||||
// Load bound from type parameters.
|
||||
loop_call_check += LoadLocal(info.type_parameters);
|
||||
loop_call_check += LoadNativeField(Slot::TypeParameters_bounds());
|
||||
loop_call_check += LoadLocal(info.vars->current_param_index);
|
||||
loop_call_check += LoadIndexed(
|
||||
kTypeArgumentsCid, /*index_scale*/ compiler::target::kCompressedWordSize);
|
||||
// Load (canonicalized) name of type parameter in signature.
|
||||
loop_call_check += LoadLocal(info.type_parameters);
|
||||
loop_call_check += LoadNativeField(Slot::TypeParameters_names());
|
||||
loop_call_check += LoadLocal(info.vars->current_param_index);
|
||||
loop_call_check += LoadIndexed(kArrayCid);
|
||||
// Assert that the passed-in type argument is consistent with the bound of
|
||||
// the corresponding type parameter.
|
||||
loop_call_check += AssertSubtype(TokenPosition::kNoSource);
|
||||
loop_call_check += Goto(next);
|
||||
|
||||
Fragment loop_incr(next);
|
||||
loop_incr += DropTemporary(¤t_param);
|
||||
loop_incr += LoadLocal(info.vars->current_param_index);
|
||||
loop_incr += IntConstant(1);
|
||||
loop_incr += SmiBinaryOp(Token::kADD, /*is_truncating=*/true);
|
||||
|
@ -2717,23 +2775,38 @@ Fragment FlowGraphBuilder::BuildDynamicClosureCallChecks(
|
|||
// full set of function type arguments, then check the local function type
|
||||
// arguments against the closure function's type parameter bounds.
|
||||
Fragment generic;
|
||||
// Calculate the number of parent type arguments and store them in
|
||||
// info.num_parent_type_args.
|
||||
generic += LoadLocal(info.signature);
|
||||
generic += BuildExtractUnboxedSlotBitFieldIntoSmi<
|
||||
UntaggedFunctionType::PackedNumParentTypeArguments>(
|
||||
Slot::FunctionType_packed_fields());
|
||||
info.num_parent_type_args = MakeTemporary("num_parent_type_args");
|
||||
|
||||
// Hoist number of type parameters.
|
||||
generic += LoadLocal(info.type_parameters);
|
||||
generic += LoadNativeField(Slot::TypeParameters_names());
|
||||
generic += LoadNativeField(Slot::Array_length());
|
||||
info.num_type_parameters = MakeTemporary("num_type_parameters");
|
||||
|
||||
// Hoist type parameter flags.
|
||||
generic += LoadLocal(info.type_parameters);
|
||||
generic += LoadNativeField(Slot::TypeParameters_flags());
|
||||
info.type_parameter_flags = MakeTemporary("type_parameter_flags");
|
||||
|
||||
// Calculate the local function type arguments and store them in
|
||||
// info.vars->function_type_args.
|
||||
generic += BuildClosureCallDefaultTypeHandling(info);
|
||||
|
||||
// Load the local function type args.
|
||||
generic += LoadLocal(info.vars->function_type_args);
|
||||
// Load the parent function type args.
|
||||
generic += LoadLocal(info.parent_function_type_args);
|
||||
// Load the number of parent type parameters.
|
||||
generic += LoadLocal(info.signature);
|
||||
generic += BuildExtractUnboxedSlotBitFieldIntoSmi<
|
||||
UntaggedFunctionType::PackedNumParentTypeArguments>(
|
||||
Slot::FunctionType_packed_fields());
|
||||
generic += LoadLocal(info.num_parent_type_args);
|
||||
// Load the number of total type parameters.
|
||||
LocalVariable* num_parents = MakeTemporary();
|
||||
generic += LoadLocal(info.type_parameters);
|
||||
generic += LoadNativeField(Slot::TypeArguments_length());
|
||||
generic += LoadLocal(num_parents);
|
||||
generic += LoadLocal(info.num_parent_type_args);
|
||||
generic += LoadLocal(info.num_type_parameters);
|
||||
generic += SmiBinaryOp(Token::kADD, /*is_truncating=*/true);
|
||||
|
||||
// Call the static function for prepending type arguments.
|
||||
|
@ -2753,6 +2826,9 @@ Fragment FlowGraphBuilder::BuildDynamicClosureCallChecks(
|
|||
} else {
|
||||
generic += check_bounds;
|
||||
}
|
||||
generic += DropTemporary(&info.type_parameter_flags);
|
||||
generic += DropTemporary(&info.num_type_parameters);
|
||||
generic += DropTemporary(&info.num_parent_type_args);
|
||||
|
||||
// Call the appropriate fragment for setting up the function type arguments
|
||||
// and performing any needed type argument checking.
|
||||
|
|
|
@ -710,7 +710,18 @@ Type& TranslationHelper::GetDeclarationType(const Class& klass) {
|
|||
type = klass.DeclarationType();
|
||||
} else {
|
||||
// Note that the type argument vector is not yet extended.
|
||||
type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()));
|
||||
TypeArguments& type_args = TypeArguments::Handle(Z);
|
||||
const intptr_t num_type_params = klass.NumTypeParameters();
|
||||
if (num_type_params > 0) {
|
||||
type_args = TypeArguments::New(num_type_params);
|
||||
TypeParameter& type_param = TypeParameter::Handle();
|
||||
for (intptr_t i = 0; i < num_type_params; i++) {
|
||||
type_param = klass.TypeParameterAt(i);
|
||||
ASSERT(type_param.bound() != AbstractType::null());
|
||||
type_args.SetTypeAt(i, type_param);
|
||||
}
|
||||
}
|
||||
type = Type::New(klass, type_args, Nullability::kNonNullable);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
@ -2916,19 +2927,13 @@ ExternalTypedDataPtr KernelReaderHelper::GetConstantCoverageFor(
|
|||
intptr_t ActiveClass::MemberTypeParameterCount(Zone* zone) {
|
||||
ASSERT(member != NULL);
|
||||
if (member->IsFactory()) {
|
||||
TypeArguments& class_types =
|
||||
TypeArguments::Handle(zone, klass->type_parameters());
|
||||
return class_types.Length();
|
||||
return klass->NumTypeParameters();
|
||||
} else if (member->IsMethodExtractor()) {
|
||||
Function& extracted =
|
||||
Function::Handle(zone, member->extracted_method_closure());
|
||||
TypeArguments& function_types =
|
||||
TypeArguments::Handle(zone, extracted.type_parameters());
|
||||
return function_types.Length();
|
||||
return extracted.NumTypeParameters();
|
||||
} else {
|
||||
TypeArguments& function_types =
|
||||
TypeArguments::Handle(zone, member->type_parameters());
|
||||
return function_types.Length();
|
||||
return member->NumTypeParameters();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2937,17 +2942,15 @@ ActiveTypeParametersScope::ActiveTypeParametersScope(
|
|||
const Function& innermost,
|
||||
const FunctionType* innermost_signature,
|
||||
Zone* Z)
|
||||
: active_class_(active_class), saved_(*active_class) {
|
||||
: active_class_(active_class), saved_(*active_class), zone_(Z) {
|
||||
active_class_->enclosing = innermost_signature;
|
||||
|
||||
intptr_t num_params = 0;
|
||||
|
||||
Function& f = Function::Handle(Z);
|
||||
TypeArguments& f_params = TypeArguments::Handle(Z);
|
||||
for (f = innermost.ptr(); f.parent_function() != Object::null();
|
||||
f = f.parent_function()) {
|
||||
f_params = f.type_parameters();
|
||||
num_params += f_params.Length();
|
||||
num_params += f.NumTypeParameters();
|
||||
}
|
||||
if (num_params == 0) return;
|
||||
|
||||
|
@ -2957,9 +2960,10 @@ ActiveTypeParametersScope::ActiveTypeParametersScope(
|
|||
intptr_t index = num_params;
|
||||
for (f = innermost.ptr(); f.parent_function() != Object::null();
|
||||
f = f.parent_function()) {
|
||||
f_params = f.type_parameters();
|
||||
for (intptr_t j = f_params.Length() - 1; j >= 0; --j) {
|
||||
params.SetTypeAt(--index, AbstractType::Handle(Z, f_params.TypeAt(j)));
|
||||
for (intptr_t j = f.NumTypeParameters() - 1; j >= 0; --j) {
|
||||
const auto& type_param = TypeParameter::Handle(Z, f.TypeParameterAt(j));
|
||||
params.SetTypeAt(--index, type_param);
|
||||
active_class_->RecordDerivedTypeParameter(Z, type_param);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2969,32 +2973,55 @@ ActiveTypeParametersScope::ActiveTypeParametersScope(
|
|||
ActiveTypeParametersScope::ActiveTypeParametersScope(
|
||||
ActiveClass* active_class,
|
||||
const FunctionType* innermost_signature,
|
||||
const TypeArguments& new_params,
|
||||
Zone* Z)
|
||||
: active_class_(active_class), saved_(*active_class) {
|
||||
: active_class_(active_class), saved_(*active_class), zone_(Z) {
|
||||
active_class_->enclosing = innermost_signature;
|
||||
|
||||
if (new_params.IsNull()) return;
|
||||
const intptr_t num_new_params =
|
||||
innermost_signature == nullptr ? active_class->klass->NumTypeParameters()
|
||||
: innermost_signature->NumTypeParameters();
|
||||
if (num_new_params == 0) return;
|
||||
|
||||
const TypeArguments* old_params = active_class->local_type_parameters;
|
||||
const intptr_t old_param_count =
|
||||
old_params == NULL ? 0 : old_params->Length();
|
||||
const TypeArguments& extended_params = TypeArguments::Handle(
|
||||
Z, TypeArguments::New(old_param_count + new_params.Length()));
|
||||
Z, TypeArguments::New(old_param_count + num_new_params));
|
||||
|
||||
intptr_t index = 0;
|
||||
for (intptr_t i = 0; i < old_param_count; ++i) {
|
||||
extended_params.SetTypeAt(
|
||||
index++, AbstractType::ZoneHandle(Z, old_params->TypeAt(i)));
|
||||
extended_params.SetTypeAt(index++,
|
||||
AbstractType::Handle(Z, old_params->TypeAt(i)));
|
||||
}
|
||||
for (intptr_t i = 0; i < new_params.Length(); ++i) {
|
||||
extended_params.SetTypeAt(
|
||||
index++, AbstractType::ZoneHandle(Z, new_params.TypeAt(i)));
|
||||
for (intptr_t i = 0; i < num_new_params; ++i) {
|
||||
const auto& type_param =
|
||||
TypeParameter::Handle(Z, innermost_signature == nullptr
|
||||
? active_class->klass->TypeParameterAt(i)
|
||||
: innermost_signature->TypeParameterAt(i));
|
||||
extended_params.SetTypeAt(index++, type_param);
|
||||
active_class->RecordDerivedTypeParameter(Z, type_param);
|
||||
}
|
||||
|
||||
active_class_->local_type_parameters = &extended_params;
|
||||
}
|
||||
|
||||
ActiveTypeParametersScope::~ActiveTypeParametersScope() {
|
||||
GrowableObjectArray* dropped = active_class_->derived_type_parameters;
|
||||
const bool preserve_unpatched =
|
||||
dropped != nullptr && saved_.derived_type_parameters == nullptr;
|
||||
*active_class_ = saved_;
|
||||
if (preserve_unpatched) {
|
||||
// Preserve still unpatched derived type parameters that would be dropped.
|
||||
auto& derived = TypeParameter::Handle(Z);
|
||||
for (intptr_t i = 0, n = dropped->Length(); i < n; ++i) {
|
||||
derived ^= dropped->At(i);
|
||||
if (derived.bound() == AbstractType::null()) {
|
||||
active_class_->RecordDerivedTypeParameter(Z, derived);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TypeTranslator::TypeTranslator(KernelReaderHelper* helper,
|
||||
ConstantReader* constant_reader,
|
||||
ActiveClass* active_class,
|
||||
|
@ -3135,14 +3162,12 @@ void TypeTranslator::BuildFunctionType(bool simple) {
|
|||
|
||||
if (!simple) {
|
||||
type_parameter_count = helper_->ReadListLength();
|
||||
LoadAndSetupTypeParameters(
|
||||
active_class_, Object::null_function(), Object::null_class(), signature,
|
||||
type_parameter_count, active_class_->klass->nnbd_mode());
|
||||
LoadAndSetupTypeParameters(active_class_, Object::null_function(),
|
||||
Object::null_class(), signature,
|
||||
type_parameter_count);
|
||||
}
|
||||
|
||||
ActiveTypeParametersScope scope(
|
||||
active_class_, &signature,
|
||||
TypeArguments::Handle(Z, signature.type_parameters()), Z);
|
||||
ActiveTypeParametersScope scope(active_class_, &signature, Z);
|
||||
|
||||
if (!simple) {
|
||||
LoadAndSetupBounds(active_class_, Object::null_function(),
|
||||
|
@ -3230,19 +3255,16 @@ void TypeTranslator::BuildTypeParameterType() {
|
|||
// If the type is from a constant, the parameter index isn't offset by the
|
||||
// enclosing context.
|
||||
if (!in_constant_context_) {
|
||||
const TypeArguments& class_types =
|
||||
TypeArguments::Handle(Z, active_class_->klass->type_parameters());
|
||||
if (parameter_index < class_types.Length()) {
|
||||
// The index of the type parameter in [parameters] is
|
||||
// the same index into the `klass->type_parameters()` array.
|
||||
const auto& type_param =
|
||||
TypeParameter::CheckedHandle(Z, class_types.TypeAt(parameter_index));
|
||||
result_ = type_param.ToNullability(nullability, Heap::kOld);
|
||||
active_class_->RecordDerivedTypeParameter(Z, type_param,
|
||||
const intptr_t class_type_parameter_count =
|
||||
active_class_->klass->NumTypeParameters();
|
||||
if (class_type_parameter_count > parameter_index) {
|
||||
result_ =
|
||||
active_class_->klass->TypeParameterAt(parameter_index, nullability);
|
||||
active_class_->RecordDerivedTypeParameter(Z,
|
||||
TypeParameter::Cast(result_));
|
||||
return;
|
||||
}
|
||||
parameter_index -= class_types.Length();
|
||||
parameter_index -= class_type_parameter_count;
|
||||
|
||||
if (active_class_->HasMember()) {
|
||||
if (active_class_->MemberIsFactoryProcedure()) {
|
||||
|
@ -3263,33 +3285,32 @@ void TypeTranslator::BuildTypeParameterType() {
|
|||
// static A.x<T'>() { return new B<T'>(); }
|
||||
// }
|
||||
//
|
||||
if (class_types.Length() > parameter_index) {
|
||||
const auto& type_param = TypeParameter::CheckedHandle(
|
||||
Z, class_types.TypeAt(parameter_index));
|
||||
result_ = type_param.ToNullability(nullability, Heap::kOld);
|
||||
if (class_type_parameter_count > parameter_index) {
|
||||
result_ = active_class_->klass->TypeParameterAt(parameter_index,
|
||||
nullability);
|
||||
active_class_->RecordDerivedTypeParameter(
|
||||
Z, type_param, TypeParameter::Cast(result_));
|
||||
Z, TypeParameter::Cast(result_));
|
||||
return;
|
||||
}
|
||||
parameter_index -= class_types.Length();
|
||||
parameter_index -= class_type_parameter_count;
|
||||
}
|
||||
// Factory function should not be considered as procedure.
|
||||
intptr_t procedure_type_parameter_count =
|
||||
const intptr_t procedure_type_parameter_count =
|
||||
(active_class_->MemberIsProcedure() &&
|
||||
!active_class_->MemberIsFactoryProcedure())
|
||||
? active_class_->MemberTypeParameterCount(Z)
|
||||
: 0;
|
||||
if (procedure_type_parameter_count > 0) {
|
||||
if (procedure_type_parameter_count > parameter_index) {
|
||||
const auto& type_param = TypeParameter::CheckedHandle(
|
||||
Z,
|
||||
TypeArguments::Handle(Z, active_class_->member->type_parameters())
|
||||
.TypeAt(parameter_index));
|
||||
result_ = type_param.ToNullability(nullability, Heap::kOld);
|
||||
active_class_->RecordDerivedTypeParameter(
|
||||
Z, type_param, TypeParameter::Cast(result_));
|
||||
result_ = active_class_->member->TypeParameterAt(parameter_index,
|
||||
nullability);
|
||||
if (finalize_) {
|
||||
ASSERT(TypeParameter::Cast(result_).bound() !=
|
||||
AbstractType::null());
|
||||
result_ = ClassFinalizer::FinalizeType(result_);
|
||||
} else {
|
||||
active_class_->RecordDerivedTypeParameter(
|
||||
Z, TypeParameter::Cast(result_));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -3302,10 +3323,12 @@ void TypeTranslator::BuildTypeParameterType() {
|
|||
const auto& type_param = TypeParameter::CheckedHandle(
|
||||
Z, active_class_->local_type_parameters->TypeAt(parameter_index));
|
||||
result_ = type_param.ToNullability(nullability, Heap::kOld);
|
||||
active_class_->RecordDerivedTypeParameter(Z, type_param,
|
||||
TypeParameter::Cast(result_));
|
||||
if (finalize_) {
|
||||
ASSERT(TypeParameter::Cast(result_).bound() != AbstractType::null());
|
||||
result_ = ClassFinalizer::FinalizeType(result_);
|
||||
} else {
|
||||
active_class_->RecordDerivedTypeParameter(Z,
|
||||
TypeParameter::Cast(result_));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -3381,8 +3404,7 @@ void TypeTranslator::LoadAndSetupTypeParameters(
|
|||
const Function& function,
|
||||
const Class& parameterized_class,
|
||||
const FunctionType& parameterized_signature,
|
||||
intptr_t type_parameter_count,
|
||||
const NNBDMode nnbd_mode) {
|
||||
intptr_t type_parameter_count) {
|
||||
ASSERT(parameterized_class.IsNull() != parameterized_signature.IsNull());
|
||||
ASSERT(type_parameter_count >= 0);
|
||||
if (type_parameter_count == 0) {
|
||||
|
@ -3398,23 +3420,18 @@ void TypeTranslator::LoadAndSetupTypeParameters(
|
|||
|
||||
// First setup the type parameters, so if any of the following code uses it
|
||||
// (in a recursive way) we're fine.
|
||||
TypeArguments& type_parameters = TypeArguments::Handle(Z);
|
||||
TypeParameter& parameter = TypeParameter::Handle(Z);
|
||||
|
||||
// - Create a [ TypeParameters ] object.
|
||||
const TypeParameters& type_parameters =
|
||||
TypeParameters::Handle(Z, TypeParameters::New(type_parameter_count));
|
||||
const Type& null_bound = Type::Handle(Z);
|
||||
|
||||
const Nullability nullability = (nnbd_mode == NNBDMode::kOptedInLib)
|
||||
? Nullability::kNonNullable
|
||||
: Nullability::kLegacy;
|
||||
|
||||
// - Create array of [TypeParameter] objects (without bound).
|
||||
// - Create array of [String] objects.
|
||||
type_parameters = TypeArguments::New(type_parameter_count);
|
||||
intptr_t offset = 0;
|
||||
if (!parameterized_class.IsNull()) {
|
||||
ASSERT(parameterized_class.type_parameters() == TypeArguments::null());
|
||||
ASSERT(parameterized_class.type_parameters() == TypeParameters::null());
|
||||
parameterized_class.set_type_parameters(type_parameters);
|
||||
} else {
|
||||
ASSERT(parameterized_signature.type_parameters() == TypeArguments::null());
|
||||
ASSERT(parameterized_signature.type_parameters() == TypeParameters::null());
|
||||
parameterized_signature.set_type_parameters(type_parameters);
|
||||
offset = parameterized_signature.NumParentTypeArguments();
|
||||
if (!function.IsNull()) {
|
||||
|
@ -3425,22 +3442,15 @@ void TypeTranslator::LoadAndSetupTypeParameters(
|
|||
const Library& lib = Library::Handle(Z, active_class->klass->library());
|
||||
{
|
||||
AlternativeReadingScope alt(&helper_->reader_);
|
||||
String& name = String::Handle(Z);
|
||||
for (intptr_t i = 0; i < type_parameter_count; i++) {
|
||||
TypeParameterHelper helper(helper_);
|
||||
helper.Finish();
|
||||
if (parameterized_class.IsNull() && function.IsNull()) {
|
||||
// Erase provided name and use a canonical one instead.
|
||||
name = Symbols::NewFormatted(H.thread(), "X%" Pd, offset + i);
|
||||
} else {
|
||||
name = H.DartIdentifier(lib, helper.name_index_).ptr();
|
||||
}
|
||||
type_parameters.SetNameAt(i, H.DartIdentifier(lib, helper.name_index_));
|
||||
type_parameters.SetIsGenericCovariantImplAt(
|
||||
i, helper.IsGenericCovariantImpl());
|
||||
// Bounds are filled later in LoadAndSetupBounds as bound types may
|
||||
// reference type parameters which are not created yet.
|
||||
parameter = TypeParameter::New(
|
||||
parameterized_class, offset, offset + i, name, null_bound,
|
||||
helper.IsGenericCovariantImpl(), nullability);
|
||||
type_parameters.SetTypeAt(i, parameter);
|
||||
type_parameters.SetBoundAt(i, null_bound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3457,52 +3467,45 @@ void TypeTranslator::LoadAndSetupBounds(
|
|||
return;
|
||||
}
|
||||
|
||||
const TypeArguments& type_parameters =
|
||||
TypeArguments::Handle(Z, !parameterized_class.IsNull()
|
||||
const TypeParameters& type_parameters = TypeParameters::Handle(
|
||||
Z, !parameterized_class.IsNull()
|
||||
? parameterized_class.type_parameters()
|
||||
: parameterized_signature.type_parameters());
|
||||
TypeParameter& parameter = TypeParameter::Handle(Z);
|
||||
|
||||
// Fill in the bounds and default arguments of all [TypeParameter]s.
|
||||
for (intptr_t i = 0; i < type_parameter_count; i++) {
|
||||
TypeParameterHelper helper(helper_);
|
||||
helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);
|
||||
|
||||
parameter ^= type_parameters.TypeAt(i);
|
||||
AbstractType& bound = BuildTypeWithoutFinalization(); // read ith bound.
|
||||
parameter.set_bound(bound);
|
||||
ASSERT(!bound.IsNull());
|
||||
type_parameters.SetBoundAt(i, bound);
|
||||
helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kDefaultType);
|
||||
AbstractType& default_arg = BuildTypeWithoutFinalization();
|
||||
parameter.set_default_argument(default_arg);
|
||||
ASSERT(!default_arg.IsNull());
|
||||
type_parameters.SetDefaultAt(i, default_arg);
|
||||
helper.Finish();
|
||||
}
|
||||
|
||||
// Note that function.UpdateCachedDefaultTypeArguments() is called in
|
||||
// function.set_signature() and is not required here.
|
||||
|
||||
// Fix bounds and default arguments in all derived type parameters (with
|
||||
// different nullabilities).
|
||||
// Fix bounds in all derived type parameters.
|
||||
const intptr_t offset = !parameterized_signature.IsNull()
|
||||
? parameterized_signature.NumParentTypeArguments()
|
||||
: 0;
|
||||
if (active_class->derived_type_parameters != nullptr) {
|
||||
auto& derived = TypeParameter::Handle(Z);
|
||||
auto& type = AbstractType::Handle(Z);
|
||||
auto& bound = AbstractType::Handle(Z);
|
||||
for (intptr_t i = 0, n = active_class->derived_type_parameters->Length();
|
||||
i < n; ++i) {
|
||||
derived ^= active_class->derived_type_parameters->At(i);
|
||||
if (derived.bound() == AbstractType::null() &&
|
||||
((!parameterized_class.IsNull() &&
|
||||
derived.parameterized_class() == parameterized_class.ptr()) ||
|
||||
derived.parameterized_class_id() == parameterized_class.id()) ||
|
||||
(!parameterized_signature.IsNull() &&
|
||||
derived.parameterized_class() == Class::null() &&
|
||||
derived.parameterized_class_id() == kFunctionCid &&
|
||||
derived.index() >= offset &&
|
||||
derived.index() < offset + type_parameter_count))) {
|
||||
parameter ^= type_parameters.TypeAt(derived.index() - offset);
|
||||
type = parameter.bound();
|
||||
derived.set_bound(type);
|
||||
type = parameter.default_argument();
|
||||
derived.set_default_argument(type);
|
||||
bound = type_parameters.BoundAt(derived.index() - offset);
|
||||
derived.set_bound(bound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3516,8 +3519,18 @@ const Type& TypeTranslator::ReceiverType(const Class& klass) {
|
|||
if (finalize_ || klass.is_type_finalized()) {
|
||||
type = klass.DeclarationType();
|
||||
} else {
|
||||
type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
|
||||
Nullability::kNonNullable);
|
||||
TypeArguments& type_args = TypeArguments::Handle(Z);
|
||||
const intptr_t num_type_params = klass.NumTypeParameters();
|
||||
if (num_type_params > 0) {
|
||||
type_args = TypeArguments::New(num_type_params);
|
||||
TypeParameter& type_param = TypeParameter::Handle();
|
||||
for (intptr_t i = 0; i < num_type_params; i++) {
|
||||
type_param = klass.TypeParameterAt(i);
|
||||
ASSERT(type_param.bound() != AbstractType::null());
|
||||
type_args.SetTypeAt(i, type_param);
|
||||
}
|
||||
}
|
||||
type = Type::New(klass, type_args, Nullability::kNonNullable);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
@ -3631,8 +3644,8 @@ void TypeTranslator::SetupFunctionParameters(
|
|||
if (!is_factory) {
|
||||
type_parameter_count = helper_->ReadListLength();
|
||||
LoadAndSetupTypeParameters(active_class_, function, Class::Handle(Z),
|
||||
signature, type_parameter_count,
|
||||
function.nnbd_mode());
|
||||
signature, type_parameter_count);
|
||||
function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
|
||||
}
|
||||
|
||||
ActiveTypeParametersScope scope(active_class_, function, &signature, Z);
|
||||
|
|
|
@ -1344,11 +1344,8 @@ class ActiveClass {
|
|||
return klass->NumTypeArguments();
|
||||
}
|
||||
|
||||
void RecordDerivedTypeParameter(Zone* zone,
|
||||
const TypeParameter& original,
|
||||
const TypeParameter& derived) {
|
||||
if (original.ptr() != derived.ptr() &&
|
||||
original.bound() == AbstractType::null()) {
|
||||
void RecordDerivedTypeParameter(Zone* zone, const TypeParameter& derived) {
|
||||
if (derived.bound() == AbstractType::null()) {
|
||||
if (derived_type_parameters == nullptr) {
|
||||
derived_type_parameters = &GrowableObjectArray::Handle(
|
||||
zone, GrowableObjectArray::New(Heap::kOld));
|
||||
|
@ -1442,14 +1439,14 @@ class ActiveTypeParametersScope {
|
|||
// Also, the enclosing signature is set to 'signature'.
|
||||
ActiveTypeParametersScope(ActiveClass* active_class,
|
||||
const FunctionType* innermost_signature,
|
||||
const TypeArguments& new_params,
|
||||
Zone* Z);
|
||||
|
||||
~ActiveTypeParametersScope() { *active_class_ = saved_; }
|
||||
~ActiveTypeParametersScope();
|
||||
|
||||
private:
|
||||
ActiveClass* active_class_;
|
||||
ActiveClass saved_;
|
||||
Zone* zone_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ActiveTypeParametersScope);
|
||||
};
|
||||
|
@ -1476,8 +1473,7 @@ class TypeTranslator {
|
|||
const Function& function,
|
||||
const Class& parameterized_class,
|
||||
const FunctionType& parameterized_signature,
|
||||
intptr_t type_parameter_count,
|
||||
const NNBDMode nnbd_mode);
|
||||
intptr_t type_parameter_count);
|
||||
|
||||
void LoadAndSetupBounds(ActiveClass* active_class,
|
||||
const Function& function,
|
||||
|
|
|
@ -1180,6 +1180,10 @@ word Field::NextFieldOffset() {
|
|||
return -kWordSize;
|
||||
}
|
||||
|
||||
word TypeParameters::NextFieldOffset() {
|
||||
return -kWordSize;
|
||||
}
|
||||
|
||||
word TypeArguments::NextFieldOffset() {
|
||||
return -kWordSize;
|
||||
}
|
||||
|
|
|
@ -922,7 +922,6 @@ class TypeParameter : public AllStatic {
|
|||
public:
|
||||
static word bound_offset();
|
||||
static word flags_offset();
|
||||
static word name_offset();
|
||||
static word InstanceSize();
|
||||
static word NextFieldOffset();
|
||||
static word parameterized_class_id_offset();
|
||||
|
@ -1303,7 +1302,6 @@ class Closure : public AllStatic {
|
|||
|
||||
class ClosureData : public AllStatic {
|
||||
public:
|
||||
static word default_type_arguments_offset();
|
||||
static word default_type_arguments_kind_offset();
|
||||
static word InstanceSize();
|
||||
static word NextFieldOffset();
|
||||
|
@ -1373,6 +1371,16 @@ class Field : public AllStatic {
|
|||
static word NextFieldOffset();
|
||||
};
|
||||
|
||||
class TypeParameters : public AllStatic {
|
||||
public:
|
||||
static word names_offset();
|
||||
static word flags_offset();
|
||||
static word bounds_offset();
|
||||
static word defaults_offset();
|
||||
static word InstanceSize();
|
||||
static word NextFieldOffset();
|
||||
};
|
||||
|
||||
class TypeArguments : public AllStatic {
|
||||
public:
|
||||
static word instantiations_offset();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -110,7 +110,6 @@
|
|||
FIELD(Closure, function_type_arguments_offset) \
|
||||
FIELD(Closure, hash_offset) \
|
||||
FIELD(Closure, instantiator_type_arguments_offset) \
|
||||
FIELD(ClosureData, default_type_arguments_offset) \
|
||||
FIELD(ClosureData, default_type_arguments_kind_offset) \
|
||||
FIELD(Code, object_pool_offset) \
|
||||
FIELD(Code, saved_instructions_offset) \
|
||||
|
@ -301,9 +300,12 @@
|
|||
FIELD(TypeArguments, length_offset) \
|
||||
FIELD(TypeArguments, nullability_offset) \
|
||||
FIELD(TypeArguments, types_offset) \
|
||||
FIELD(TypeParameters, names_offset) \
|
||||
FIELD(TypeParameters, flags_offset) \
|
||||
FIELD(TypeParameters, bounds_offset) \
|
||||
FIELD(TypeParameters, defaults_offset) \
|
||||
FIELD(TypeParameter, bound_offset) \
|
||||
FIELD(TypeParameter, flags_offset) \
|
||||
FIELD(TypeParameter, name_offset) \
|
||||
FIELD(TypeRef, type_offset) \
|
||||
FIELD(TypedDataBase, length_offset) \
|
||||
FIELD(TypedDataView, data_offset) \
|
||||
|
@ -384,6 +386,7 @@
|
|||
SIZEOF(TransferableTypedData, InstanceSize, UntaggedTransferableTypedData) \
|
||||
SIZEOF(Type, InstanceSize, UntaggedType) \
|
||||
SIZEOF(TypeParameter, InstanceSize, UntaggedTypeParameter) \
|
||||
SIZEOF(TypeParameters, InstanceSize, UntaggedTypeParameters) \
|
||||
SIZEOF(TypeRef, InstanceSize, UntaggedTypeRef) \
|
||||
SIZEOF(TypedData, HeaderSize, UntaggedTypedData) \
|
||||
SIZEOF(TypedDataBase, InstanceSize, UntaggedTypedDataBase) \
|
||||
|
|
|
@ -482,7 +482,8 @@ static void GenerateNullIsAssignableToType(Assembler* assembler,
|
|||
__ BranchIf(EQUAL, &is_assignable, Assembler::kNearJump);
|
||||
// Resolve the type parameter to its instantiated type and loop.
|
||||
__ LoadFieldFromOffset(kIndexReg, kCurrentTypeReg,
|
||||
target::TypeParameter::index_offset(), kTwoBytes);
|
||||
target::TypeParameter::index_offset(),
|
||||
kUnsignedByte);
|
||||
__ LoadIndexedCompressed(kCurrentTypeReg, tav,
|
||||
target::TypeArguments::types_offset(),
|
||||
kIndexReg);
|
||||
|
@ -597,7 +598,8 @@ static void BuildTypeParameterTypeTestStub(Assembler* assembler,
|
|||
// Resolve the type parameter to its instantiated type and tail call the
|
||||
// instantiated type's TTS.
|
||||
__ LoadFieldFromOffset(TypeTestABI::kScratchReg, TypeTestABI::kDstTypeReg,
|
||||
target::TypeParameter::index_offset(), kTwoBytes);
|
||||
target::TypeParameter::index_offset(),
|
||||
kUnsignedByte);
|
||||
__ LoadIndexedCompressed(TypeTestABI::kScratchReg, tav,
|
||||
target::TypeArguments::types_offset(),
|
||||
TypeTestABI::kScratchReg);
|
||||
|
|
|
@ -1328,20 +1328,19 @@ TypeArgumentsPtr ActivationFrame::BuildParameters(
|
|||
intptr_t num_vars = function().NumTypeArguments();
|
||||
type_params_names.Grow(num_vars);
|
||||
type_params_names.SetLength(num_vars);
|
||||
TypeArguments& type_params = TypeArguments::Handle();
|
||||
TypeParameter& type_param = TypeParameter::Handle();
|
||||
TypeParameters& type_params = TypeParameters::Handle();
|
||||
Function& current = Function::Handle(function().ptr());
|
||||
intptr_t mapping_offset = num_vars;
|
||||
for (intptr_t i = 0; !current.IsNull(); i += current.NumTypeParameters(),
|
||||
current = current.parent_function()) {
|
||||
type_params = current.type_parameters();
|
||||
if (type_params.IsNull()) continue;
|
||||
intptr_t size = current.NumTypeParameters();
|
||||
ASSERT(size == 0 || type_params.Length() == size);
|
||||
ASSERT(size > 0 && type_params.Length() == size);
|
||||
ASSERT(mapping_offset >= size);
|
||||
mapping_offset -= size;
|
||||
for (intptr_t j = 0; j < size; ++j) {
|
||||
type_param = TypeParameter::RawCast(type_params.TypeAt(j));
|
||||
name = type_param.name();
|
||||
name = type_params.NameAt(j);
|
||||
// Write the names in backwards in terms of chain of functions.
|
||||
// But keep the order of names within the same function. so they
|
||||
// match up with the order of the types in 'type_arguments'.
|
||||
|
|
|
@ -703,15 +703,13 @@ bool NeedsDynamicInvocationForwarder(const Function& function) {
|
|||
}
|
||||
|
||||
const auto& type_params =
|
||||
TypeArguments::Handle(zone, function.type_parameters());
|
||||
TypeParameters::Handle(zone, function.type_parameters());
|
||||
if (!type_params.IsNull()) {
|
||||
auto& type_param = TypeParameter::Handle(zone);
|
||||
auto& bound = AbstractType::Handle(zone);
|
||||
for (intptr_t i = 0, n = type_params.Length(); i < n; ++i) {
|
||||
type_param ^= type_params.TypeAt(i);
|
||||
bound = type_param.bound();
|
||||
bound = type_params.BoundAt(i);
|
||||
if (!bound.IsTopTypeForSubtyping() &&
|
||||
!type_param.IsGenericCovariantImpl()) {
|
||||
!type_params.IsGenericCovariantImplAt(i)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -830,6 +830,18 @@ ObjectPtr KernelLoader::LoadExpressionEvaluationFunction(
|
|||
|
||||
function.set_owner(real_class);
|
||||
|
||||
ASSERT(real_class.is_finalized());
|
||||
// The owner class has already been marked as finalized so the signature of
|
||||
// this added function must be finalized here, since finalization of member
|
||||
// types will not be called anymore.
|
||||
FunctionType& signature = FunctionType::Handle(Z, function.signature());
|
||||
if (!function.is_static()) {
|
||||
// Patch the illegal receiver type (type class with kIllegalCid) to dynamic.
|
||||
signature.SetParameterTypeAt(0, Object::dynamic_type());
|
||||
}
|
||||
signature ^= ClassFinalizer::FinalizeType(signature);
|
||||
function.set_signature(signature);
|
||||
|
||||
return function.ptr();
|
||||
}
|
||||
|
||||
|
@ -1425,7 +1437,9 @@ void KernelLoader::LoadPreliminaryClass(ClassHelper* class_helper,
|
|||
// Set type parameters.
|
||||
T.LoadAndSetupTypeParameters(&active_class_, Object::null_function(), *klass,
|
||||
Object::null_function_type(),
|
||||
type_parameter_count, klass->nnbd_mode());
|
||||
type_parameter_count);
|
||||
|
||||
ActiveTypeParametersScope scope(&active_class_, nullptr, Z);
|
||||
|
||||
T.LoadAndSetupBounds(&active_class_, Object::null_function(), *klass,
|
||||
Object::null_function_type(), type_parameter_count);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -460,6 +460,7 @@ class Object {
|
|||
static ClassPtr class_class() { return class_class_; }
|
||||
static ClassPtr dynamic_class() { return dynamic_class_; }
|
||||
static ClassPtr void_class() { return void_class_; }
|
||||
static ClassPtr type_parameters_class() { return type_parameters_class_; }
|
||||
static ClassPtr type_arguments_class() { return type_arguments_class_; }
|
||||
static ClassPtr patch_class_class() { return patch_class_class_; }
|
||||
static ClassPtr function_class() { return function_class_; }
|
||||
|
@ -777,6 +778,7 @@ class Object {
|
|||
static ClassPtr class_class_; // Class of the Class vm object.
|
||||
static ClassPtr dynamic_class_; // Class of the 'dynamic' type.
|
||||
static ClassPtr void_class_; // Class of the 'void' type.
|
||||
static ClassPtr type_parameters_class_; // Class of TypeParameters vm object.
|
||||
static ClassPtr type_arguments_class_; // Class of TypeArguments vm object.
|
||||
static ClassPtr patch_class_class_; // Class of the PatchClass vm object.
|
||||
static ClassPtr function_class_; // Class of the Function vm object.
|
||||
|
@ -1103,21 +1105,22 @@ class Class : public Object {
|
|||
LibraryPtr library() const { return untag()->library(); }
|
||||
void set_library(const Library& value) const;
|
||||
|
||||
// The type parameters (and their bounds) are specified as an array of
|
||||
// TypeParameter.
|
||||
TypeArgumentsPtr type_parameters() const {
|
||||
// The formal type parameters and their bounds (no defaults), are specified as
|
||||
// an object of type TypeParameters.
|
||||
TypeParametersPtr type_parameters() const {
|
||||
ASSERT(is_declaration_loaded());
|
||||
return untag()->type_parameters();
|
||||
}
|
||||
void set_type_parameters(const TypeArguments& value) const;
|
||||
void set_type_parameters(const TypeParameters& value) const;
|
||||
intptr_t NumTypeParameters(Thread* thread) const;
|
||||
intptr_t NumTypeParameters() const {
|
||||
return NumTypeParameters(Thread::Current());
|
||||
}
|
||||
|
||||
// Return a TypeParameter if the type_name is a type parameter of this class.
|
||||
// Return null otherwise.
|
||||
TypeParameterPtr LookupTypeParameter(const String& type_name) const;
|
||||
// Return the type parameter declared at index.
|
||||
TypeParameterPtr TypeParameterAt(
|
||||
intptr_t index,
|
||||
Nullability nullability = Nullability::kNonNullable) const;
|
||||
|
||||
// The type argument vector is flattened and includes the type arguments of
|
||||
// the super class.
|
||||
|
@ -2614,9 +2617,9 @@ class Function : public Object {
|
|||
// are packed into SMIs, but omitted if they're 0.
|
||||
bool IsRequiredAt(intptr_t index) const;
|
||||
|
||||
// The type parameters (and their bounds) are specified as an array of
|
||||
// TypeParameter stored in the signature. They are part of the function type.
|
||||
TypeArgumentsPtr type_parameters() const {
|
||||
// The formal type parameters, their bounds, and defaults, are specified as an
|
||||
// object of type TypeParameters stored in the signature.
|
||||
TypeParametersPtr type_parameters() const {
|
||||
return untag()->signature()->untag()->type_parameters();
|
||||
}
|
||||
|
||||
|
@ -2635,12 +2638,10 @@ class Function : public Object {
|
|||
return NumParentTypeArguments() + NumTypeParameters();
|
||||
}
|
||||
|
||||
// Return a TypeParameter if the type_name is a type parameter of this
|
||||
// function or of one of its parent functions.
|
||||
// Unless NULL, adjust function_level accordingly (in and out parameter).
|
||||
// Return null otherwise.
|
||||
TypeParameterPtr LookupTypeParameter(const String& type_name,
|
||||
intptr_t* function_level) const;
|
||||
// Return the type parameter declared at index.
|
||||
TypeParameterPtr TypeParameterAt(
|
||||
intptr_t index,
|
||||
Nullability nullability = Nullability::kNonNullable) const;
|
||||
|
||||
// Return true if this function declares type parameters.
|
||||
// Generic dispatchers only set the number without actual type parameters.
|
||||
|
@ -2735,21 +2736,9 @@ class Function : public Object {
|
|||
Thread* thread,
|
||||
DefaultTypeArgumentsKind* kind_out = nullptr) const;
|
||||
|
||||
// Whether this function should have a cached type arguments vector for the
|
||||
// instantiated-to-bounds version of the type parameters.
|
||||
bool CachesDefaultTypeArguments() const { return IsClosureFunction(); }
|
||||
|
||||
// Updates the cached default type arguments vector for this function if it
|
||||
// caches and for its implicit closure function if it has one. If the
|
||||
// default arguments are all canonical, the cached default type arguments
|
||||
// vector is canonicalized. Should be run any time the type parameters vector
|
||||
// is changed or if the default arguments of any type parameters are updated.
|
||||
void UpdateCachedDefaultTypeArguments(Thread* thread) const;
|
||||
|
||||
// These are only usable for functions that cache the default type arguments.
|
||||
TypeArgumentsPtr default_type_arguments(
|
||||
DefaultTypeArgumentsKind* kind_out = nullptr) const;
|
||||
void set_default_type_arguments(const TypeArguments& value) const;
|
||||
// Only usable for closure functions.
|
||||
DefaultTypeArgumentsKind default_type_arguments_kind() const;
|
||||
void set_default_type_arguments_kind(DefaultTypeArgumentsKind value) const;
|
||||
|
||||
// Enclosing outermost function of this local function.
|
||||
FunctionPtr GetOutermostFunction() const;
|
||||
|
@ -3787,9 +3776,6 @@ class ClosureData : public Object {
|
|||
return RoundedAllocationSize(sizeof(UntaggedClosureData));
|
||||
}
|
||||
|
||||
static intptr_t default_type_arguments_offset() {
|
||||
return OFFSET_OF(UntaggedClosureData, default_type_arguments_);
|
||||
}
|
||||
static intptr_t default_type_arguments_kind_offset() {
|
||||
return OFFSET_OF(UntaggedClosureData, default_type_arguments_kind_);
|
||||
}
|
||||
|
@ -3816,11 +3802,6 @@ class ClosureData : public Object {
|
|||
}
|
||||
void set_implicit_static_closure(const Instance& closure) const;
|
||||
|
||||
TypeArgumentsPtr default_type_arguments() const {
|
||||
return untag()->default_type_arguments();
|
||||
}
|
||||
void set_default_type_arguments(const TypeArguments& value) const;
|
||||
|
||||
DefaultTypeArgumentsKind default_type_arguments_kind() const;
|
||||
void set_default_type_arguments_kind(DefaultTypeArgumentsKind value) const;
|
||||
|
||||
|
@ -4222,7 +4203,7 @@ class Field : public Object {
|
|||
// Returns false if any value read from this field is guaranteed to be
|
||||
// not null.
|
||||
// Internally we is_nullable_ field contains either kNullCid (nullable) or
|
||||
// kInvalidCid (non-nullable) instead of boolean. This is done to simplify
|
||||
// kIllegalCid (non-nullable) instead of boolean. This is done to simplify
|
||||
// guarding sequence in the generated code.
|
||||
bool is_nullable() const;
|
||||
void set_is_nullable(bool val) const {
|
||||
|
@ -7483,6 +7464,90 @@ class LibraryPrefix : public Instance {
|
|||
friend class Class;
|
||||
};
|
||||
|
||||
// TypeParameters represents a list of formal type parameters with their bounds
|
||||
// and their default values as calculated by CFE.
|
||||
class TypeParameters : public Object {
|
||||
public:
|
||||
intptr_t Length() const;
|
||||
|
||||
static intptr_t names_offset() {
|
||||
return OFFSET_OF(UntaggedTypeParameters, names_);
|
||||
}
|
||||
StringPtr NameAt(intptr_t index) const;
|
||||
void SetNameAt(intptr_t index, const String& value) const;
|
||||
|
||||
static intptr_t flags_offset() {
|
||||
return OFFSET_OF(UntaggedTypeParameters, flags_);
|
||||
}
|
||||
|
||||
static intptr_t bounds_offset() {
|
||||
return OFFSET_OF(UntaggedTypeParameters, bounds_);
|
||||
}
|
||||
AbstractTypePtr BoundAt(intptr_t index) const;
|
||||
void SetBoundAt(intptr_t index, const AbstractType& value) const;
|
||||
bool AllDynamicBounds() const;
|
||||
|
||||
static intptr_t defaults_offset() {
|
||||
return OFFSET_OF(UntaggedTypeParameters, defaults_);
|
||||
}
|
||||
AbstractTypePtr DefaultAt(intptr_t index) const;
|
||||
void SetDefaultAt(intptr_t index, const AbstractType& value) const;
|
||||
bool AllDynamicDefaults() const;
|
||||
|
||||
// The isGenericCovariantImpl bits are packed into SMIs in the flags array,
|
||||
// but omitted if they're 0.
|
||||
bool IsGenericCovariantImplAt(intptr_t index) const;
|
||||
void SetIsGenericCovariantImplAt(intptr_t index, bool value) const;
|
||||
|
||||
// The number of flags per Smi should be a power of 2 in order to simplify the
|
||||
// generated code accessing the flags array.
|
||||
#if !defined(DART_COMPRESSED_POINTERS)
|
||||
static const intptr_t kFlagsPerSmiShift = kBitsPerWordLog2 - 1;
|
||||
#else
|
||||
static const intptr_t kFlagsPerSmiShift = kBitsPerWordLog2 - 2;
|
||||
#endif
|
||||
static const intptr_t kFlagsPerSmi = 1LL << kFlagsPerSmiShift;
|
||||
COMPILE_ASSERT(kFlagsPerSmi < kSmiBits);
|
||||
static const intptr_t kFlagsPerSmiMask = kFlagsPerSmi - 1;
|
||||
|
||||
void Print(Thread* thread,
|
||||
Zone* zone,
|
||||
bool are_class_type_parameters,
|
||||
intptr_t base,
|
||||
NameVisibility name_visibility,
|
||||
BaseTextBuffer* printer) const;
|
||||
|
||||
static intptr_t InstanceSize() {
|
||||
return RoundedAllocationSize(sizeof(UntaggedTypeParameters));
|
||||
}
|
||||
|
||||
static TypeParametersPtr New(Heap::Space space = Heap::kOld);
|
||||
static TypeParametersPtr New(intptr_t count, Heap::Space space = Heap::kOld);
|
||||
|
||||
private:
|
||||
ArrayPtr names() const { return untag()->names(); }
|
||||
void set_names(const Array& value) const;
|
||||
ArrayPtr flags() const { return untag()->flags(); }
|
||||
void set_flags(const Array& value) const;
|
||||
TypeArgumentsPtr bounds() const { return untag()->bounds(); }
|
||||
void set_bounds(const TypeArguments& value) const;
|
||||
TypeArgumentsPtr defaults() const { return untag()->defaults(); }
|
||||
void set_defaults(const TypeArguments& value) const;
|
||||
|
||||
// Allocate and initialize the flags array to zero.
|
||||
void AllocateFlags(Heap::Space space) const;
|
||||
// Reset the flags array to null if all flags are zero.
|
||||
void OptimizeFlags() const;
|
||||
|
||||
FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeParameters, Object);
|
||||
friend class Class;
|
||||
friend class ClassFinalizer;
|
||||
friend class Function;
|
||||
friend class FunctionType;
|
||||
friend class Object;
|
||||
friend class Precompiler;
|
||||
};
|
||||
|
||||
// A TypeArguments is an array of AbstractType.
|
||||
class TypeArguments : public Instance {
|
||||
public:
|
||||
|
@ -8307,6 +8372,8 @@ class FunctionType : public AbstractType {
|
|||
}
|
||||
|
||||
// Reexported so they can be used by the flow graph builders.
|
||||
using PackedNumParentTypeArguments =
|
||||
UntaggedFunctionType::PackedNumParentTypeArguments;
|
||||
using PackedHasNamedOptionalParameters =
|
||||
UntaggedFunctionType::PackedHasNamedOptionalParameters;
|
||||
using PackedNumFixedParameters =
|
||||
|
@ -8314,6 +8381,11 @@ class FunctionType : public AbstractType {
|
|||
using PackedNumOptionalParameters =
|
||||
UntaggedFunctionType::PackedNumOptionalParameters;
|
||||
|
||||
// Return the type parameter declared at index.
|
||||
TypeParameterPtr TypeParameterAt(
|
||||
intptr_t index,
|
||||
Nullability nullability = Nullability::kNonNullable) const;
|
||||
|
||||
AbstractTypePtr result_type() const { return untag()->result_type(); }
|
||||
void set_result_type(const AbstractType& value) const;
|
||||
|
||||
|
@ -8369,12 +8441,12 @@ class FunctionType : public AbstractType {
|
|||
// parameters don't have flags.
|
||||
static intptr_t NameArrayLengthIncludingFlags(intptr_t num_parameters);
|
||||
|
||||
// The type parameters (and their bounds) are specified as an array of
|
||||
// TypeParameter.
|
||||
TypeArgumentsPtr type_parameters() const {
|
||||
// The formal type parameters, their bounds, and defaults, are specified as an
|
||||
// object of type TypeParameters.
|
||||
TypeParametersPtr type_parameters() const {
|
||||
return untag()->type_parameters();
|
||||
}
|
||||
void set_type_parameters(const TypeArguments& value) const;
|
||||
void set_type_parameters(const TypeParameters& value) const;
|
||||
static intptr_t type_parameters_offset() {
|
||||
return OFFSET_OF(UntaggedFunctionType, type_parameters_);
|
||||
}
|
||||
|
@ -8536,11 +8608,6 @@ class TypeParameter : public AbstractType {
|
|||
return UntaggedTypeParameter::BeingFinalizedBit::decode(untag()->flags_);
|
||||
}
|
||||
virtual void SetIsBeingFinalized() const;
|
||||
bool IsGenericCovariantImpl() const {
|
||||
return UntaggedTypeParameter::GenericCovariantImplBit::decode(
|
||||
untag()->flags_);
|
||||
}
|
||||
void SetGenericCovariantImpl(bool value) const;
|
||||
static intptr_t flags_offset() {
|
||||
return OFFSET_OF(UntaggedTypeParameter, flags_);
|
||||
}
|
||||
|
@ -8575,21 +8642,12 @@ class TypeParameter : public AbstractType {
|
|||
return OFFSET_OF(UntaggedTypeParameter, index_);
|
||||
}
|
||||
|
||||
StringPtr name() const { return untag()->name(); }
|
||||
static intptr_t name_offset() {
|
||||
return OFFSET_OF(UntaggedTypeParameter, name_);
|
||||
}
|
||||
AbstractTypePtr bound() const { return untag()->bound(); }
|
||||
void set_bound(const AbstractType& value) const;
|
||||
static intptr_t bound_offset() {
|
||||
return OFFSET_OF(UntaggedTypeParameter, bound_);
|
||||
}
|
||||
|
||||
AbstractTypePtr default_argument() const {
|
||||
return untag()->default_argument();
|
||||
}
|
||||
void set_default_argument(const AbstractType& value) const;
|
||||
|
||||
virtual bool IsInstantiated(Genericity genericity = kAny,
|
||||
intptr_t num_free_fun_type_params = kAllFree,
|
||||
TrailPtr trail = nullptr) const;
|
||||
|
@ -8625,6 +8683,15 @@ class TypeParameter : public AbstractType {
|
|||
const TypeArguments& instantiator_type_arguments,
|
||||
const TypeArguments& function_type_arguments) const;
|
||||
|
||||
// Return a constructed name for this nameless type parameter.
|
||||
const char* CanonicalNameCString() const {
|
||||
return CanonicalNameCString(IsClassTypeParameter(), base(), index());
|
||||
}
|
||||
|
||||
static const char* CanonicalNameCString(bool is_class_type_parameter,
|
||||
intptr_t base,
|
||||
intptr_t index);
|
||||
|
||||
static intptr_t InstanceSize() {
|
||||
return RoundedAllocationSize(sizeof(UntaggedTypeParameter));
|
||||
}
|
||||
|
@ -8633,9 +8700,7 @@ class TypeParameter : public AbstractType {
|
|||
static TypeParameterPtr New(const Class& parameterized_class,
|
||||
intptr_t base,
|
||||
intptr_t index,
|
||||
const String& name,
|
||||
const AbstractType& bound,
|
||||
bool is_generic_covariant_impl,
|
||||
Nullability nullability);
|
||||
|
||||
private:
|
||||
|
@ -8993,6 +9058,8 @@ class String : public Instance {
|
|||
return GetCachedHash(ptr()) != 0;
|
||||
}
|
||||
|
||||
bool IsRecursive() const { return false; } // Required by HashSet templates.
|
||||
|
||||
static intptr_t hash_offset() {
|
||||
#if defined(HASH_IN_OBJECT_HEADER)
|
||||
COMPILE_ASSERT(UntaggedObject::kHashTagPos % kBitsPerByte == 0);
|
||||
|
|
|
@ -169,6 +169,15 @@ void Class::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
|||
}
|
||||
}
|
||||
|
||||
void TypeParameters::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
||||
JSONObject jsobj(stream);
|
||||
jsobj.AddProperty("kind", "TypeParameters");
|
||||
jsobj.AddProperty("flags", Array::Handle(flags()));
|
||||
jsobj.AddProperty("names", Array::Handle(names()));
|
||||
jsobj.AddProperty("bounds", TypeArguments::Handle(bounds()));
|
||||
jsobj.AddProperty("defaults", TypeArguments::Handle(defaults()));
|
||||
}
|
||||
|
||||
void TypeArguments::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
||||
JSONObject jsobj(stream);
|
||||
// The index in the canonical_type_arguments table cannot be used as part of
|
||||
|
|
|
@ -244,6 +244,7 @@ class ParsedFunction : public ZoneAllocated {
|
|||
V(current_function, Function, CurrentFunction) \
|
||||
V(current_num_processed, Smi, CurrentNumProcessed) \
|
||||
V(current_param_index, Smi, CurrentParamIndex) \
|
||||
V(current_type_param, Dynamic, CurrentTypeParam) \
|
||||
V(function_type_args, Dynamic, FunctionTypeArgs)
|
||||
|
||||
#define DEFINE_FIELD(Name, _, __) LocalVariable* Name = nullptr;
|
||||
|
|
|
@ -572,6 +572,7 @@ COMPRESSED_VISITOR(MirrorReference)
|
|||
COMPRESSED_VISITOR(UserTag)
|
||||
REGULAR_VISITOR(SubtypeTestCache)
|
||||
COMPRESSED_VISITOR(LoadingUnit)
|
||||
COMPRESSED_VISITOR(TypeParameters)
|
||||
VARIABLE_COMPRESSED_VISITOR(TypeArguments,
|
||||
Smi::Value(raw_obj->untag()->length()))
|
||||
VARIABLE_COMPRESSED_VISITOR(LocalVarDescriptors, raw_obj->untag()->num_entries_)
|
||||
|
|
|
@ -954,8 +954,7 @@ class UntaggedClass : public UntaggedObject {
|
|||
COMPRESSED_POINTER_FIELD(ArrayPtr, interfaces) // Array of AbstractType.
|
||||
COMPRESSED_POINTER_FIELD(ScriptPtr, script)
|
||||
COMPRESSED_POINTER_FIELD(LibraryPtr, library)
|
||||
// Array of TypeParameter.
|
||||
COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, type_parameters)
|
||||
COMPRESSED_POINTER_FIELD(TypeParametersPtr, type_parameters)
|
||||
COMPRESSED_POINTER_FIELD(AbstractTypePtr, super_type)
|
||||
// Canonicalized const instances of this class.
|
||||
COMPRESSED_POINTER_FIELD(ArrayPtr, constants)
|
||||
|
@ -1358,9 +1357,7 @@ class UntaggedClosureData : public UntaggedObject {
|
|||
#endif
|
||||
// Closure object for static implicit closures.
|
||||
COMPRESSED_POINTER_FIELD(InstancePtr, closure)
|
||||
// Instantiate-to-bounds TAV for use when no TAV is provided.
|
||||
COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, default_type_arguments)
|
||||
VISIT_TO(CompressedObjectPtr, default_type_arguments)
|
||||
VISIT_TO(CompressedObjectPtr, closure)
|
||||
|
||||
enum class DefaultTypeArgumentsKind : uint8_t {
|
||||
// Only here to make sure it's explicitly set appropriately.
|
||||
|
@ -1458,7 +1455,7 @@ class UntaggedField : public UntaggedObject {
|
|||
TokenPosition end_token_pos_;
|
||||
ClassIdTagType guarded_cid_;
|
||||
ClassIdTagType is_nullable_; // kNullCid if field can contain null value and
|
||||
// kInvalidCid otherwise.
|
||||
// kIllegalCid otherwise.
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
uint32_t kernel_offset_;
|
||||
|
@ -2503,6 +2500,25 @@ class UntaggedTypeArguments : public UntaggedInstance {
|
|||
friend class SnapshotReader;
|
||||
};
|
||||
|
||||
class UntaggedTypeParameters : public UntaggedObject {
|
||||
private:
|
||||
RAW_HEAP_OBJECT_IMPLEMENTATION(TypeParameters);
|
||||
|
||||
VISIT_FROM(CompressedObjectPtr, names)
|
||||
// Length of names reflects the number of type parameters.
|
||||
COMPRESSED_POINTER_FIELD(ArrayPtr, names)
|
||||
// flags: isGenericCovariantImpl and (todo) variance.
|
||||
COMPRESSED_POINTER_FIELD(ArrayPtr, flags)
|
||||
COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, bounds)
|
||||
// defaults is the instantiation to bounds (calculated by CFE).
|
||||
COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, defaults)
|
||||
VISIT_TO(CompressedObjectPtr, defaults)
|
||||
CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
|
||||
|
||||
friend class Object;
|
||||
friend class SnapshotReader;
|
||||
};
|
||||
|
||||
class UntaggedAbstractType : public UntaggedInstance {
|
||||
public:
|
||||
enum TypeState {
|
||||
|
@ -2551,8 +2567,7 @@ class UntaggedFunctionType : public UntaggedAbstractType {
|
|||
RAW_HEAP_OBJECT_IMPLEMENTATION(FunctionType);
|
||||
|
||||
VISIT_FROM(CompressedObjectPtr, type_test_stub)
|
||||
// Array of TypeParameter.
|
||||
COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, type_parameters)
|
||||
COMPRESSED_POINTER_FIELD(TypeParametersPtr, type_parameters)
|
||||
COMPRESSED_POINTER_FIELD(AbstractTypePtr, result_type)
|
||||
COMPRESSED_POINTER_FIELD(ArrayPtr, parameter_types)
|
||||
COMPRESSED_POINTER_FIELD(ArrayPtr, parameter_names);
|
||||
|
@ -2624,21 +2639,13 @@ class UntaggedTypeParameter : public UntaggedAbstractType {
|
|||
RAW_HEAP_OBJECT_IMPLEMENTATION(TypeParameter);
|
||||
|
||||
VISIT_FROM(CompressedObjectPtr, type_test_stub)
|
||||
COMPRESSED_POINTER_FIELD(StringPtr, name)
|
||||
COMPRESSED_POINTER_FIELD(SmiPtr, hash)
|
||||
// ObjectType if no explicit bound specified.
|
||||
COMPRESSED_POINTER_FIELD(AbstractTypePtr, bound)
|
||||
// The instantiation to bounds of this parameter as calculated by the CFE.
|
||||
//
|
||||
// TODO(dartbug.com/43901): Once a separate TypeParameters class has been
|
||||
// added, move these there and remove them from TypeParameter objects.
|
||||
COMPRESSED_POINTER_FIELD(AbstractTypePtr, default_argument)
|
||||
VISIT_TO(CompressedObjectPtr, default_argument)
|
||||
VISIT_TO(CompressedObjectPtr, bound)
|
||||
ClassIdTagType parameterized_class_id_; // Or kFunctionCid for function tp.
|
||||
// TODO(regis): Can we use uint8_t twice below? Or keep uint16_t?
|
||||
// Warning: BuildTypeParameterTypeTestStub assumes uint16_t.
|
||||
uint16_t base_; // Number of enclosing function type parameters.
|
||||
uint16_t index_;
|
||||
uint8_t base_; // Number of enclosing function type parameters.
|
||||
uint8_t index_; // Keep size in sync with BuildTypeParameterTypeTestStub.
|
||||
uint8_t flags_;
|
||||
uint8_t nullability_;
|
||||
|
||||
|
@ -2646,9 +2653,7 @@ class UntaggedTypeParameter : public UntaggedAbstractType {
|
|||
using BeingFinalizedBit = BitField<decltype(flags_), bool, 0, 1>;
|
||||
using FinalizedBit =
|
||||
BitField<decltype(flags_), bool, BeingFinalizedBit::kNextBit, 1>;
|
||||
using GenericCovariantImplBit =
|
||||
BitField<decltype(flags_), bool, FinalizedBit::kNextBit, 1>;
|
||||
static constexpr intptr_t kFlagsBitSize = GenericCovariantImplBit::kNextBit;
|
||||
static constexpr intptr_t kFlagsBitSize = FinalizedBit::kNextBit;
|
||||
|
||||
private:
|
||||
CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
|
||||
|
|
|
@ -136,9 +136,12 @@ namespace dart {
|
|||
F(TypeRef, type_test_stub_) \
|
||||
F(TypeRef, type_) \
|
||||
F(TypeParameter, type_test_stub_) \
|
||||
F(TypeParameter, name_) \
|
||||
F(TypeParameter, hash_) \
|
||||
F(TypeParameter, bound_) \
|
||||
F(TypeParameters, names_) \
|
||||
F(TypeParameters, flags_) \
|
||||
F(TypeParameters, bounds_) \
|
||||
F(TypeParameters, defaults_) \
|
||||
F(Closure, instantiator_type_arguments_) \
|
||||
F(Closure, function_type_arguments_) \
|
||||
F(Closure, delayed_type_arguments_) \
|
||||
|
|
|
@ -230,6 +230,8 @@ TypeParameterPtr TypeParameter::ReadFrom(SnapshotReader* reader,
|
|||
reader->AddBackRef(object_id, &type_parameter, kIsDeserialized);
|
||||
|
||||
// Set all non object fields.
|
||||
type_parameter.set_base(reader->Read<uint8_t>());
|
||||
type_parameter.set_index(reader->Read<uint8_t>());
|
||||
const uint8_t combined = reader->Read<uint8_t>();
|
||||
type_parameter.set_flags(combined >> 4);
|
||||
type_parameter.set_nullability(static_cast<Nullability>(combined & 0xf));
|
||||
|
@ -279,8 +281,8 @@ void UntaggedTypeParameter::WriteTo(SnapshotWriter* writer,
|
|||
writer->WriteTags(writer->GetObjectTags(this));
|
||||
|
||||
// Write out all the non object pointer fields.
|
||||
writer->Write<uint16_t>(base_);
|
||||
writer->Write<uint16_t>(index_);
|
||||
writer->Write<uint8_t>(base_);
|
||||
writer->Write<uint8_t>(index_);
|
||||
const uint8_t combined = (flags_ << 4) | nullability_;
|
||||
ASSERT(flags_ == (combined >> 4));
|
||||
ASSERT(nullability_ == (combined & 0xf));
|
||||
|
@ -296,6 +298,43 @@ void UntaggedTypeParameter::WriteTo(SnapshotWriter* writer,
|
|||
writer->WriteObjectImpl(param_class, kAsReference);
|
||||
}
|
||||
|
||||
TypeParametersPtr TypeParameters::ReadFrom(SnapshotReader* reader,
|
||||
intptr_t object_id,
|
||||
intptr_t tags,
|
||||
Snapshot::Kind kind,
|
||||
bool as_reference) {
|
||||
ASSERT(reader != NULL);
|
||||
|
||||
TypeParameters& type_parameters =
|
||||
TypeParameters::ZoneHandle(reader->zone(), TypeParameters::New());
|
||||
reader->AddBackRef(object_id, &type_parameters, kIsDeserialized);
|
||||
|
||||
// Set all the object fields.
|
||||
READ_COMPRESSED_OBJECT_FIELDS(
|
||||
type_parameters, type_parameters.ptr()->untag()->from(),
|
||||
type_parameters.ptr()->untag()->to(), kAsReference);
|
||||
|
||||
return type_parameters.ptr();
|
||||
}
|
||||
|
||||
void UntaggedTypeParameters::WriteTo(SnapshotWriter* writer,
|
||||
intptr_t object_id,
|
||||
Snapshot::Kind kind,
|
||||
bool as_reference) {
|
||||
ASSERT(writer != NULL);
|
||||
|
||||
// Write out the serialization header value for this object.
|
||||
writer->WriteInlinedObjectHeader(object_id);
|
||||
|
||||
// Write out the class and tags information.
|
||||
writer->WriteVMIsolateObject(kTypeParametersCid);
|
||||
writer->WriteTags(writer->GetObjectTags(this));
|
||||
|
||||
// Write out all the object pointer fields.
|
||||
SnapshotWriterVisitor visitor(writer, kAsReference);
|
||||
visitor.VisitCompressedPointers(heap_base(), from(), to());
|
||||
}
|
||||
|
||||
TypeArgumentsPtr TypeArguments::ReadFrom(SnapshotReader* reader,
|
||||
intptr_t object_id,
|
||||
intptr_t tags,
|
||||
|
|
|
@ -109,6 +109,8 @@ REUSABLE_HANDLE_LIST(REUSABLE_SCOPE)
|
|||
ReusableSmiHandleScope reused_smi_handle(thread);
|
||||
#define REUSABLE_STRING_HANDLESCOPE(thread) \
|
||||
ReusableStringHandleScope reused_string_handle(thread);
|
||||
#define REUSABLE_TYPE_PARAMETERS_HANDLESCOPE(thread) \
|
||||
ReusableTypeArgumentsHandleScope reused_type_parameters_handle(thread);
|
||||
#define REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread) \
|
||||
ReusableTypeArgumentsHandleScope reused_type_arguments_handle(thread);
|
||||
#define REUSABLE_TYPE_PARAMETER_HANDLESCOPE(thread) \
|
||||
|
|
|
@ -531,13 +531,20 @@ DEFINE_RUNTIME_ENTRY(SubtypeCheck, 5) {
|
|||
AbstractType::CheckedHandle(zone, arguments.ArgAt(3));
|
||||
const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(4));
|
||||
|
||||
ASSERT(!subtype.IsNull() && !subtype.IsTypeRef());
|
||||
if (supertype.IsTypeRef()) {
|
||||
supertype = TypeRef::Cast(supertype).type();
|
||||
}
|
||||
ASSERT(!supertype.IsNull() && !supertype.IsTypeRef());
|
||||
|
||||
// Now that AssertSubtype may be checking types only available at runtime,
|
||||
// we can't guarantee the supertype isn't the top type.
|
||||
if (supertype.IsTopTypeForSubtyping()) return;
|
||||
|
||||
if (subtype.IsTypeRef()) {
|
||||
subtype = TypeRef::Cast(subtype).type();
|
||||
}
|
||||
ASSERT(!subtype.IsNull() && !subtype.IsTypeRef());
|
||||
|
||||
// TODO(regis): Support for FLAG_trace_type_checks is missing here. Is it
|
||||
// still useful or should we remove it everywhere?
|
||||
|
||||
|
|
|
@ -416,6 +416,7 @@ class SnapshotReader : public BaseReader {
|
|||
friend class Type;
|
||||
friend class FunctionType;
|
||||
friend class TypedDataView;
|
||||
friend class TypeParameters;
|
||||
friend class TypeArguments;
|
||||
friend class TypeParameter;
|
||||
friend class TypeRef;
|
||||
|
|
|
@ -106,6 +106,7 @@ class ObjectPointerVisitor;
|
|||
V(DynamicCallCurrentNumProcessedVar, ":dyn_call_current_num_processed") \
|
||||
V(DynamicCallCurrentFunctionVar, ":dyn_call_current_function") \
|
||||
V(DynamicCallCurrentParamIndexVar, ":dyn_call_current_param_index") \
|
||||
V(DynamicCallCurrentTypeParamVar, ":dyn_call_current_type_param") \
|
||||
V(DynamicCallFunctionTypeArgsVar, ":dyn_call_function_type_args") \
|
||||
V(DynamicPrefix, "dyn:") \
|
||||
V(EntryPointsTemp, ":entry_points_temp") \
|
||||
|
@ -286,6 +287,7 @@ class ObjectPointerVisitor;
|
|||
V(TypeArguments, "TypeArguments") \
|
||||
V(TypeArgumentsParameter, ":type_arguments") \
|
||||
V(TypeError, "_TypeError") \
|
||||
V(TypeParameters, "TypeParameters") \
|
||||
V(TypeQuote, "type '") \
|
||||
V(Uint16List, "Uint16List") \
|
||||
V(Uint32List, "Uint32List") \
|
||||
|
|
|
@ -324,6 +324,7 @@ DEFINE_TAGGED_POINTER(UnwindError, Error)
|
|||
DEFINE_TAGGED_POINTER(Instance, Object)
|
||||
DEFINE_TAGGED_POINTER(LibraryPrefix, Instance)
|
||||
DEFINE_TAGGED_POINTER(TypeArguments, Instance)
|
||||
DEFINE_TAGGED_POINTER(TypeParameters, Object)
|
||||
DEFINE_TAGGED_POINTER(AbstractType, Instance)
|
||||
DEFINE_TAGGED_POINTER(Type, AbstractType)
|
||||
DEFINE_TAGGED_POINTER(FunctionType, AbstractType)
|
||||
|
|
|
@ -83,6 +83,7 @@ class Thread;
|
|||
V(PcDescriptors) \
|
||||
V(Smi) \
|
||||
V(String) \
|
||||
V(TypeParameters) \
|
||||
V(TypeArguments) \
|
||||
V(TypeParameter)
|
||||
|
||||
|
|
|
@ -72,8 +72,8 @@ const char* TypeTestingStubNamer::StringifyType(
|
|||
|
||||
return concatenated;
|
||||
} else if (type.IsTypeParameter()) {
|
||||
string_ = TypeParameter::Cast(type).name();
|
||||
return AssemblerSafeName(OS::SCreate(Z, "%s", string_.ToCString()));
|
||||
return AssemblerSafeName(
|
||||
OS::SCreate(Z, "%s", TypeParameter::Cast(type).CanonicalNameCString()));
|
||||
} else {
|
||||
return AssemblerSafeName(OS::SCreate(Z, "%s", type.ToCString()));
|
||||
}
|
||||
|
@ -359,18 +359,13 @@ void TypeTestingStubGenerator::BuildOptimizedTypeTestStubFastCases(
|
|||
} else {
|
||||
ASSERT(hi->CanUseGenericSubtypeRangeCheckFor(type));
|
||||
|
||||
const intptr_t num_type_parameters = type_class.NumTypeParameters();
|
||||
const intptr_t num_type_arguments = type_class.NumTypeArguments();
|
||||
|
||||
const TypeArguments& tp =
|
||||
TypeArguments::Handle(type_class.type_parameters());
|
||||
ASSERT(tp.Length() == num_type_parameters);
|
||||
|
||||
const TypeArguments& ta = TypeArguments::Handle(type.arguments());
|
||||
ASSERT(ta.Length() == num_type_arguments);
|
||||
|
||||
BuildOptimizedSubclassRangeCheckWithTypeArguments(assembler, hi, type,
|
||||
type_class, tp, ta);
|
||||
type_class, ta);
|
||||
}
|
||||
|
||||
if (Instance::NullIsAssignableTo(type)) {
|
||||
|
@ -411,7 +406,6 @@ void TypeTestingStubGenerator::
|
|||
HierarchyInfo* hi,
|
||||
const Type& type,
|
||||
const Class& type_class,
|
||||
const TypeArguments& tp,
|
||||
const TypeArguments& ta) {
|
||||
// a) First we make a quick sub*class* cid-range check.
|
||||
compiler::Label check_failed;
|
||||
|
@ -941,7 +935,6 @@ void TypeUsageInfo::UpdateAssertAssignableTypes(
|
|||
TypeParameterSet* parameters_tested_against) {
|
||||
Class& klass = Class::Handle(zone_);
|
||||
TypeParameter& param = TypeParameter::Handle(zone_);
|
||||
TypeArguments& params = TypeArguments::Handle(zone_);
|
||||
AbstractType& type = AbstractType::Handle(zone_);
|
||||
|
||||
// Because Object/dynamic are common values for type parameters, we add them
|
||||
|
@ -961,9 +954,8 @@ void TypeUsageInfo::UpdateAssertAssignableTypes(
|
|||
}
|
||||
|
||||
const intptr_t num_parameters = klass.NumTypeParameters();
|
||||
params = klass.type_parameters();
|
||||
for (intptr_t i = 0; i < num_parameters; ++i) {
|
||||
param ^= params.TypeAt(i);
|
||||
param = klass.TypeParameterAt(i);
|
||||
if (parameters_tested_against->HasKey(¶m)) {
|
||||
TypeArgumentsSet& ta_set = instance_creation_arguments_[cid];
|
||||
auto it = ta_set.GetIterator();
|
||||
|
|
|
@ -80,7 +80,6 @@ class TypeTestingStubGenerator {
|
|||
HierarchyInfo* hi,
|
||||
const Type& type,
|
||||
const Class& type_class,
|
||||
const TypeArguments& type_parameters,
|
||||
const TypeArguments& type_arguments);
|
||||
|
||||
static void BuildOptimizedSubclassRangeCheckWithTypeArguments(
|
||||
|
@ -88,7 +87,6 @@ class TypeTestingStubGenerator {
|
|||
HierarchyInfo* hi,
|
||||
const Type& type,
|
||||
const Class& type_class,
|
||||
const TypeArguments& type_parameters,
|
||||
const TypeArguments& type_arguments,
|
||||
const Register class_id_reg,
|
||||
const Register instance_type_args_reg);
|
||||
|
|
|
@ -461,7 +461,7 @@ ISOLATE_UNIT_TEST_CASE(TTS_SubtypeRangeCheck) {
|
|||
auto& tav_dynamic_t = TypeArguments::Handle(TypeArguments::New(2));
|
||||
tav_dynamic_t.SetTypeAt(0, type_dynamic);
|
||||
tav_dynamic_t.SetTypeAt(
|
||||
1, TypeParameter::Handle(GetClassTypeParameter(class_base, "T")));
|
||||
1, TypeParameter::Handle(GetClassTypeParameter(class_base, 0)));
|
||||
CanonicalizeTAV(&tav_dynamic_t);
|
||||
|
||||
// We will generate specialized TTS for instantiated interface types
|
||||
|
@ -750,7 +750,7 @@ ISOLATE_UNIT_TEST_CASE(TTS_GenericSubtypeRangeCheck) {
|
|||
// <...> as Base<T> with T instantiantiator type parameter (T == int)
|
||||
const auto& tav_baset = TypeArguments::Handle(TypeArguments::New(1));
|
||||
tav_baset.SetTypeAt(
|
||||
0, TypeParameter::Handle(GetClassTypeParameter(class_base, "T")));
|
||||
0, TypeParameter::Handle(GetClassTypeParameter(class_base, 0)));
|
||||
auto& type_base_t = AbstractType::Handle(Type::New(class_base, tav_baset));
|
||||
FinalizeAndCanonicalize(&type_base_t);
|
||||
RunTTSTest(obj_base_int, type_base_t, tav_int, tav_null,
|
||||
|
@ -761,7 +761,7 @@ ISOLATE_UNIT_TEST_CASE(TTS_GenericSubtypeRangeCheck) {
|
|||
// <...> as Base<B> with B function type parameter
|
||||
const auto& tav_baseb = TypeArguments::Handle(TypeArguments::New(1));
|
||||
tav_baseb.SetTypeAt(
|
||||
0, TypeParameter::Handle(GetFunctionTypeParameter(fun_generic, "B")));
|
||||
0, TypeParameter::Handle(GetFunctionTypeParameter(fun_generic, 1)));
|
||||
auto& type_base_b = AbstractType::Handle(Type::New(class_base, tav_baseb));
|
||||
FinalizeAndCanonicalize(&type_base_b);
|
||||
// With B == int
|
||||
|
@ -797,8 +797,8 @@ ISOLATE_UNIT_TEST_CASE(TTS_GenericSubtypeRangeCheck) {
|
|||
|
||||
// <...> as Base<A2<T>>
|
||||
const auto& tav_t = TypeArguments::Handle(TypeArguments::New(1));
|
||||
tav_t.SetTypeAt(
|
||||
0, TypeParameter::Handle(GetClassTypeParameter(class_base, "T")));
|
||||
tav_t.SetTypeAt(0,
|
||||
TypeParameter::Handle(GetClassTypeParameter(class_base, 0)));
|
||||
auto& type_a2_t = Type::Handle(Type::New(class_a2, tav_t));
|
||||
type_a2_t = type_a2_t.ToNullability(Nullability::kLegacy, Heap::kNew);
|
||||
FinalizeAndCanonicalize(&type_a2_t);
|
||||
|
@ -855,7 +855,7 @@ ISOLATE_UNIT_TEST_CASE(TTS_Regress40964) {
|
|||
// dst_type = B<T>
|
||||
const auto& dst_tav = TypeArguments::Handle(TypeArguments::New(1));
|
||||
dst_tav.SetTypeAt(0,
|
||||
TypeParameter::Handle(GetClassTypeParameter(class_b, "T")));
|
||||
TypeParameter::Handle(GetClassTypeParameter(class_b, 0)));
|
||||
auto& dst_type = Type::Handle(Type::New(class_b, dst_tav));
|
||||
FinalizeAndCanonicalize(&dst_type);
|
||||
const auto& cint_tav =
|
||||
|
@ -891,10 +891,10 @@ ISOLATE_UNIT_TEST_CASE(TTS_TypeParameter) {
|
|||
Function::Handle(GetFunction(root_library, "genericFun"));
|
||||
|
||||
const auto& dst_type_t =
|
||||
TypeParameter::Handle(GetClassTypeParameter(class_a, "T"));
|
||||
TypeParameter::Handle(GetClassTypeParameter(class_a, 0));
|
||||
|
||||
const auto& dst_type_h =
|
||||
TypeParameter::Handle(GetFunctionTypeParameter(fun_generic, "H"));
|
||||
TypeParameter::Handle(GetFunctionTypeParameter(fun_generic, 0));
|
||||
|
||||
const auto& aint = Object::Handle(Invoke(root_library, "createAInt"));
|
||||
const auto& astring = Object::Handle(Invoke(root_library, "createAString"));
|
||||
|
|
25
tests/language/regress/regress45763_test.dart
Normal file
25
tests/language/regress/regress45763_test.dart
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// SharedOptions=--enable-experiment=generic-metadata
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
Type? capturedTypeArgument;
|
||||
Type typeOf<X>() => X;
|
||||
|
||||
X captureTypeArgument<X>() {
|
||||
capturedTypeArgument = X;
|
||||
throw "";
|
||||
}
|
||||
|
||||
typedef check = void Function<T>();
|
||||
|
||||
void main() {
|
||||
void f(check Function<T>() g) => g();
|
||||
try {
|
||||
f(<T>() => captureTypeArgument());
|
||||
} catch (e) {}
|
||||
Expect.equals(typeOf<void Function<T>()>(), capturedTypeArgument);
|
||||
}
|
|
@ -96,9 +96,6 @@ testD(Env env) {
|
|||
values.forEach((e) {
|
||||
Expect.equals(true, e is TypeVariableMirror);
|
||||
});
|
||||
Expect.equals(#R, values.elementAt(0).simpleName);
|
||||
Expect.equals(#S, values.elementAt(1).simpleName);
|
||||
Expect.equals(#T, values.elementAt(2).simpleName);
|
||||
}
|
||||
|
||||
void testE(Env env) {
|
||||
|
|
|
@ -50,13 +50,6 @@ main() {
|
|||
Expect.equals(reflectClass(Object), xFromGeneric.upperBound); // //# 02: continued
|
||||
Expect.equals(reflectClass(Object), yFromGeneric.upperBound); // //# 02: continued
|
||||
|
||||
typeParameters(superDecl, [#T, #R]);
|
||||
typeParameters(superOfNumAndInt, [#T, #R]);
|
||||
typeParameters(genericDecl, [#X, #Y]); // //# 02: continued
|
||||
typeParameters(superOfXAndY, [#T, #R]); // //# 02: continued
|
||||
typeParameters(genericOfNumAndDouble, [#X, #Y]); // //# 02: continued
|
||||
typeParameters(superOfNumAndDouble, [#T, #R]); // //# 02: continued
|
||||
|
||||
typeArguments(superDecl, []);
|
||||
typeArguments(superOfNumAndInt, [reflectClass(num), reflectClass(int)]);
|
||||
typeArguments(genericDecl, []); // //# 02: continued
|
||||
|
|
|
@ -49,14 +49,6 @@ main() {
|
|||
Expect.equals(reflectClass(num), tFromSuper.upperBound);
|
||||
Expect.equals(reflectClass(Object), rFromGeneric.upperBound); // //# 02: continued
|
||||
|
||||
typeParameters(superDecl, [#T]);
|
||||
typeParameters(superOfInt, [#T]);
|
||||
typeParameters(genericDecl, [#R]); // //# 02: continued
|
||||
typeParameters(superOfR, [#T]); // //# 02: continued
|
||||
typeParameters(genericOfDouble, [#R]); // //# 02: continued
|
||||
typeParameters(superOfDouble, [#T]); // //# 02: continued
|
||||
typeParameters(superOfString, [#T]); // //# 01: continued
|
||||
|
||||
typeArguments(superDecl, []);
|
||||
typeArguments(superOfInt, [reflectClass(int)]);
|
||||
typeArguments(genericDecl, []); // //# 02: continued
|
||||
|
|
|
@ -81,14 +81,4 @@ main() {
|
|||
.where((dm) => dm is MethodMirror && dm.isConstructor)
|
||||
.map(stringify),
|
||||
'constructors');
|
||||
|
||||
Expect.setEquals(
|
||||
[
|
||||
'TypeVariable(s(T) in s(A), upperBound = Class(s(Object) in '
|
||||
's(dart.core), top-level))'
|
||||
],
|
||||
cm.declarations.values
|
||||
.where((dm) => dm is TypeVariableMirror)
|
||||
.map(stringify),
|
||||
'type variables');
|
||||
}
|
||||
|
|
|
@ -43,13 +43,8 @@ main() {
|
|||
Expect.equals(magnitudeDecl, magnitudeOfR.originalDeclaration);
|
||||
Expect.equals(rFromSorter, magnitudeOfR.typeArguments.single);
|
||||
|
||||
typeParameters(magnitudeDecl, [#T]);
|
||||
typeParameters(realDecl, []);
|
||||
typeParameters(sorterDecl, [#R]);
|
||||
typeParameters(realSorterDecl, []);
|
||||
typeParameters(magnitudeOfReal, [#T]);
|
||||
typeParameters(sorterOfReal, [#R]);
|
||||
typeParameters(magnitudeOfR, [#T]);
|
||||
|
||||
typeArguments(magnitudeDecl, []);
|
||||
typeArguments(realDecl, []);
|
||||
|
|
|
@ -91,21 +91,6 @@ main() {
|
|||
Expect.equals(reflectClass(Object), xFromGenericMixinApplication.upperBound);
|
||||
Expect.equals(reflectClass(Object), yFromGenericClass.upperBound);
|
||||
|
||||
typeParameters(interfaceDecl, [#T]);
|
||||
typeParameters(boundedDecl, [#S]);
|
||||
typeParameters(interfaceOfInt, [#T]);
|
||||
typeParameters(interfaceOfR, [#T]);
|
||||
typeParameters(interfaceOfBool, [#T]);
|
||||
typeParameters(boundedOfInt, [#S]);
|
||||
typeParameters(boundedOfString, [#S]); // //# 01: continued
|
||||
typeParameters(interfaceOfFBounded, [#T]);
|
||||
typeParameters(interfaceOfInt2, [#T]);
|
||||
typeParameters(interfaceOfX, [#T]);
|
||||
typeParameters(interfaceOfDouble, [#T]);
|
||||
typeParameters(interfaceOfInt3, [#T]);
|
||||
typeParameters(interfaceOfY, [#T]);
|
||||
typeParameters(interfaceOfDouble2, [#T]);
|
||||
|
||||
typeArguments(interfaceDecl, []);
|
||||
typeArguments(boundedDecl, []);
|
||||
typeArguments(interfaceOfInt, [reflectClass(int)]);
|
||||
|
|
|
@ -35,30 +35,6 @@ class GenericMultipleMixins<A, B, C> extends Super<A> with Mixin<B>, Nixim<C> {}
|
|||
main() {
|
||||
TypeMirror dynamicMirror = currentMirrorSystem().dynamicType;
|
||||
|
||||
typeParameters(reflectClass(NonGenericMixinApplication1).mixin, [#M]);
|
||||
typeParameters(reflectClass(NonGenericMixinApplication2).mixin, [#M]);
|
||||
typeParameters(reflectClass(GenericMixinApplication1).mixin, [#M]);
|
||||
typeParameters(reflectClass(GenericMixinApplication2).mixin, [#M]);
|
||||
typeParameters(reflectClass(NonGenericClass1).mixin, []);
|
||||
typeParameters(reflectClass(NonGenericClass2).mixin, []);
|
||||
typeParameters(reflectClass(GenericClass1).mixin, [#C]);
|
||||
typeParameters(reflectClass(GenericClass2).mixin, [#C]);
|
||||
typeParameters(reflectClass(NonGenericClass1).superclass!.mixin, [#M]);
|
||||
typeParameters(reflectClass(NonGenericClass2).superclass!.mixin, [#M]);
|
||||
typeParameters(reflectClass(GenericClass1).superclass!.mixin, [#M]);
|
||||
typeParameters(reflectClass(GenericClass2).superclass!.mixin, [#M]);
|
||||
typeParameters(reflectClass(GenericMultipleMixins).mixin, [#A, #B, #C]);
|
||||
typeParameters(reflectClass(GenericMultipleMixins).superclass!.mixin, [#N]);
|
||||
typeParameters(
|
||||
reflectClass(GenericMultipleMixins).superclass!.superclass!.mixin, [#M]);
|
||||
typeParameters(
|
||||
reflectClass(GenericMultipleMixins)
|
||||
.superclass!
|
||||
.superclass!
|
||||
.superclass!
|
||||
.mixin,
|
||||
[#S]);
|
||||
|
||||
typeArguments(
|
||||
reflectClass(NonGenericMixinApplication1).mixin, [dynamicMirror]);
|
||||
typeArguments(
|
||||
|
@ -93,46 +69,8 @@ main() {
|
|||
.mixin,
|
||||
[reflectClass(GenericMultipleMixins).typeVariables[0]]);
|
||||
|
||||
typeParameters(reflect(new NonGenericMixinApplication1()).type.mixin, [#M]);
|
||||
typeParameters(reflect(new NonGenericMixinApplication2()).type.mixin, [#M]);
|
||||
typeParameters(
|
||||
reflect(new GenericMixinApplication1<bool>()).type.mixin, [#M]);
|
||||
typeParameters(
|
||||
reflect(new GenericMixinApplication2<bool>()).type.mixin, [#M]);
|
||||
typeParameters(reflect(new NonGenericClass1()).type.mixin, []);
|
||||
typeParameters(reflect(new NonGenericClass2()).type.mixin, []);
|
||||
typeParameters(reflect(new GenericClass1<bool>()).type.mixin, [#C]);
|
||||
typeParameters(reflect(new GenericClass2<bool>()).type.mixin, [#C]);
|
||||
typeParameters(reflect(new NonGenericClass1()).type.superclass!.mixin, [#M]);
|
||||
typeParameters(reflect(new NonGenericClass2()).type.superclass!.mixin, [#M]);
|
||||
typeParameters(
|
||||
reflect(new GenericClass1<bool>()).type.superclass!.mixin, [#M]);
|
||||
typeParameters(
|
||||
reflect(new GenericClass2<bool>()).type.superclass!.mixin, [#M]);
|
||||
typeParameters(
|
||||
reflect(new GenericMultipleMixins<bool, String, int>()).type.mixin,
|
||||
[#A, #B, #C]);
|
||||
typeParameters(
|
||||
reflect(new GenericMultipleMixins<bool, String, int>())
|
||||
.type
|
||||
.superclass!
|
||||
.mixin,
|
||||
[#N]);
|
||||
typeParameters(
|
||||
reflect(new GenericMultipleMixins<bool, String, int>())
|
||||
.type
|
||||
.superclass!
|
||||
.superclass!
|
||||
.mixin,
|
||||
[#M]);
|
||||
typeParameters(
|
||||
reflect(new GenericMultipleMixins<bool, String, int>())
|
||||
.type
|
||||
.superclass!
|
||||
.superclass!
|
||||
.superclass!
|
||||
.mixin,
|
||||
[#S]);
|
||||
|
||||
typeArguments(
|
||||
reflect(new NonGenericMixinApplication1()).type.mixin, [dynamicMirror]);
|
||||
|
|
|
@ -36,18 +36,12 @@ main() {
|
|||
Symbol t(ClassMirror cm) =>
|
||||
(cm.declarations[#t] as MethodMirror).returnType.simpleName;
|
||||
|
||||
Expect.equals(#T, r(genericDecl.superclass!));
|
||||
Expect.equals(#int, s(genericDecl.superclass!));
|
||||
Expect.equals(#T, t(genericDecl));
|
||||
|
||||
Expect.equals(#String, r(genericOfString.superclass!));
|
||||
Expect.equals(#int, s(genericOfString.superclass!));
|
||||
Expect.equals(#String, t(genericOfString));
|
||||
|
||||
Expect.equals(#R, r(superGenericDecl));
|
||||
Expect.equals(#S, s(superGenericDecl));
|
||||
|
||||
Expect.equals(#T, r(superOfTAndInt));
|
||||
Expect.equals(#int, s(superOfTAndInt));
|
||||
|
||||
Expect.equals(#String, r(superOfStringAndInt));
|
||||
|
|
|
@ -33,15 +33,11 @@ class I extends G {}
|
|||
|
||||
main() {
|
||||
// Declarations.
|
||||
typeParameters(reflectClass(A), [#T]);
|
||||
typeParameters(reflectClass(G), []);
|
||||
typeParameters(reflectClass(B), []);
|
||||
typeParameters(reflectClass(C), []);
|
||||
typeParameters(reflectClass(D), []);
|
||||
typeParameters(reflectClass(E), [#S]);
|
||||
typeParameters(reflectClass(F), [#R]);
|
||||
typeParameters(reflectClass(G), []);
|
||||
typeParameters(reflectClass(H), [#A, #B, #C]);
|
||||
typeParameters(reflectClass(I), []);
|
||||
|
||||
typeArguments(reflectClass(A), []);
|
||||
|
@ -75,14 +71,10 @@ main() {
|
|||
Expect.equals(reflectClass(I), reflectClass(I).originalDeclaration);
|
||||
|
||||
// Instantiations.
|
||||
typeParameters(reflect(new A<num>()).type, [#T]);
|
||||
typeParameters(reflect(new B()).type, []);
|
||||
typeParameters(reflect(new C()).type, []);
|
||||
typeParameters(reflect(new D()).type, []);
|
||||
typeParameters(reflect(new E()).type, [#S]);
|
||||
typeParameters(reflect(new F<num>()).type, [#R]);
|
||||
typeParameters(reflect(new G()).type, []);
|
||||
typeParameters(reflect(new H()).type, [#A, #B, #C]);
|
||||
typeParameters(reflect(new I()).type, []);
|
||||
|
||||
var numMirror = reflectClass(num);
|
||||
|
|
|
@ -180,24 +180,7 @@ main() {
|
|||
|
||||
MethodMirror fooInC = cm.declarations[#foo] as MethodMirror;
|
||||
expect('Method(s(foo) in s(C))', fooInC);
|
||||
expect(
|
||||
'[Parameter(s(a) in s(foo),'
|
||||
' type = Class(s(int) in s(dart.core), top-level)), '
|
||||
'Parameter(s(b) in s(foo),'
|
||||
' type = TypeVariable(s(S) in s(Null),'
|
||||
' upperBound = Class(s(int) in s(dart.core), top-level)))]',
|
||||
fooInC.parameters);
|
||||
|
||||
MethodMirror barInC = cm.declarations[#bar] as MethodMirror;
|
||||
expect('Method(s(bar) in s(C))', barInC);
|
||||
expect(
|
||||
'[Parameter(s(a) in s(bar),'
|
||||
' type = TypeVariable(s(S) in s(Null),'
|
||||
' upperBound = Class(s(int) in s(dart.core), top-level))), '
|
||||
'Parameter(s(b) in s(bar),'
|
||||
' type = TypeVariable(s(T) in s(Null),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))), '
|
||||
'Parameter(s(c) in s(bar),'
|
||||
' type = Class(s(num) in s(dart.core), top-level))]',
|
||||
barInC.parameters);
|
||||
}
|
||||
|
|
|
@ -27,14 +27,6 @@ main() {
|
|||
TypeVariableMirror ssFromSuperSuper =
|
||||
superOfSuperOfGeneric.typeVariables.single;
|
||||
|
||||
Expect.equals(#G, gFromGeneric.simpleName);
|
||||
Expect.equals(#S, sFromSuper.simpleName);
|
||||
Expect.equals(#SS, ssFromSuperSuper.simpleName);
|
||||
|
||||
typeParameters(generic, [#G]);
|
||||
typeParameters(superOfGeneric, [#S]);
|
||||
typeParameters(superOfSuperOfGeneric, [#SS]);
|
||||
|
||||
typeArguments(generic, []);
|
||||
typeArguments(superOfGeneric, [gFromGeneric]);
|
||||
typeArguments(superOfSuperOfGeneric, [gFromGeneric]);
|
||||
|
@ -44,10 +36,6 @@ main() {
|
|||
ClassMirror superOfGenericWithInt = genericWithInt.superclass!;
|
||||
ClassMirror superOfSuperOfGenericWithInt = superOfGenericWithInt.superclass!;
|
||||
|
||||
typeParameters(genericWithInt, [#G]);
|
||||
typeParameters(superOfGenericWithInt, [#S]);
|
||||
typeParameters(superOfSuperOfGenericWithInt, [#SS]);
|
||||
|
||||
typeArguments(genericWithInt, [reflectClass(int)]);
|
||||
typeArguments(superOfGenericWithInt, [reflectClass(int)]);
|
||||
typeArguments(superOfSuperOfGenericWithInt, [reflectClass(int)]);
|
||||
|
|
|
@ -98,9 +98,9 @@ testD(Env env) {
|
|||
values.forEach((e) {
|
||||
Expect.equals(true, e is TypeVariableMirror);
|
||||
});
|
||||
Expect.equals(#R, values.elementAt(0).simpleName);
|
||||
Expect.equals(#S, values.elementAt(1).simpleName);
|
||||
Expect.equals(#T, values.elementAt(2).simpleName);
|
||||
|
||||
// Names of type variables are not preserved after type canonicalization
|
||||
// and are therefore not compared to expected names.
|
||||
}
|
||||
|
||||
void testE(Env env) {
|
||||
|
|
|
@ -52,12 +52,8 @@ main() {
|
|||
Expect.equals(reflectClass(Object), xFromGeneric.upperBound); // //# 02: continued
|
||||
Expect.equals(reflectClass(Object), yFromGeneric.upperBound); // //# 02: continued
|
||||
|
||||
typeParameters(superDecl, [#T, #R]);
|
||||
typeParameters(superOfNumAndInt, [#T, #R]);
|
||||
typeParameters(genericDecl, [#X, #Y]); // //# 02: continued
|
||||
typeParameters(superOfXAndY, [#T, #R]); // //# 02: continued
|
||||
typeParameters(genericOfNumAndDouble, [#X, #Y]); // //# 02: continued
|
||||
typeParameters(superOfNumAndDouble, [#T, #R]); // //# 02: continued
|
||||
// Names of type variables are not preserved after type canonicalization
|
||||
// and are therefore not compared to expected names.
|
||||
|
||||
typeArguments(superDecl, []);
|
||||
typeArguments(superOfNumAndInt, [reflectClass(num), reflectClass(int)]);
|
||||
|
|
|
@ -51,13 +51,8 @@ main() {
|
|||
Expect.equals(reflectClass(num), tFromSuper.upperBound);
|
||||
Expect.equals(reflectClass(Object), rFromGeneric.upperBound); // //# 02: continued
|
||||
|
||||
typeParameters(superDecl, [#T]);
|
||||
typeParameters(superOfInt, [#T]);
|
||||
typeParameters(genericDecl, [#R]); // //# 02: continued
|
||||
typeParameters(superOfR, [#T]); // //# 02: continued
|
||||
typeParameters(genericOfDouble, [#R]); // //# 02: continued
|
||||
typeParameters(superOfDouble, [#T]); // //# 02: continued
|
||||
typeParameters(superOfString, [#T]); // //# 01: continued
|
||||
// Names of type variables are not preserved after type canonicalization
|
||||
// and are therefore not compared to expected names.
|
||||
|
||||
typeArguments(superDecl, []);
|
||||
typeArguments(superOfInt, [reflectClass(int)]);
|
||||
|
|
|
@ -84,13 +84,6 @@ main() {
|
|||
.map(stringify),
|
||||
'constructors');
|
||||
|
||||
Expect.setEquals(
|
||||
[
|
||||
'TypeVariable(s(T) in s(A), upperBound = Class(s(Object) in '
|
||||
's(dart.core), top-level))'
|
||||
],
|
||||
cm.declarations.values
|
||||
.where((dm) => dm is TypeVariableMirror)
|
||||
.map(stringify),
|
||||
'type variables');
|
||||
// Names of type variables are not preserved after type canonicalization
|
||||
// and are therefore not compared to expected names.
|
||||
}
|
||||
|
|
|
@ -45,13 +45,14 @@ main() {
|
|||
Expect.equals(magnitudeDecl, magnitudeOfR.originalDeclaration);
|
||||
Expect.equals(rFromSorter, magnitudeOfR.typeArguments.single);
|
||||
|
||||
typeParameters(magnitudeDecl, [#T]);
|
||||
// Names of type variables are not preserved after type canonicalization
|
||||
// and are therefore not compared to expected names.
|
||||
|
||||
typeParameters(realDecl, []);
|
||||
typeParameters(sorterDecl, [#R]);
|
||||
typeParameters(realSorterDecl, []);
|
||||
typeParameters(magnitudeOfReal, [#T]);
|
||||
typeParameters(sorterOfReal, [#R]);
|
||||
typeParameters(magnitudeOfR, [#T]);
|
||||
|
||||
// Names of type variables are not preserved after type canonicalization
|
||||
// and are therefore not compared to expected names.
|
||||
|
||||
typeArguments(magnitudeDecl, []);
|
||||
typeArguments(realDecl, []);
|
||||
|
|
|
@ -93,20 +93,8 @@ main() {
|
|||
Expect.equals(reflectClass(Object), xFromGenericMixinApplication.upperBound);
|
||||
Expect.equals(reflectClass(Object), yFromGenericClass.upperBound);
|
||||
|
||||
typeParameters(interfaceDecl, [#T]);
|
||||
typeParameters(boundedDecl, [#S]);
|
||||
typeParameters(interfaceOfInt, [#T]);
|
||||
typeParameters(interfaceOfR, [#T]);
|
||||
typeParameters(interfaceOfBool, [#T]);
|
||||
typeParameters(boundedOfInt, [#S]);
|
||||
typeParameters(boundedOfString, [#S]); // //# 01: continued
|
||||
typeParameters(interfaceOfFBounded, [#T]);
|
||||
typeParameters(interfaceOfInt2, [#T]);
|
||||
typeParameters(interfaceOfX, [#T]);
|
||||
typeParameters(interfaceOfDouble, [#T]);
|
||||
typeParameters(interfaceOfInt3, [#T]);
|
||||
typeParameters(interfaceOfY, [#T]);
|
||||
typeParameters(interfaceOfDouble2, [#T]);
|
||||
// Names of type variables are not preserved after type canonicalization
|
||||
// and are therefore not compared to expected names.
|
||||
|
||||
typeArguments(interfaceDecl, []);
|
||||
typeArguments(boundedDecl, []);
|
||||
|
|
|
@ -37,29 +37,8 @@ class GenericMultipleMixins<A, B, C> extends Super<A> with Mixin<B>, Nixim<C> {}
|
|||
main() {
|
||||
TypeMirror dynamicMirror = currentMirrorSystem().dynamicType;
|
||||
|
||||
typeParameters(reflectClass(NonGenericMixinApplication1).mixin, [#M]);
|
||||
typeParameters(reflectClass(NonGenericMixinApplication2).mixin, [#M]);
|
||||
typeParameters(reflectClass(GenericMixinApplication1).mixin, [#M]);
|
||||
typeParameters(reflectClass(GenericMixinApplication2).mixin, [#M]);
|
||||
typeParameters(reflectClass(NonGenericClass1).mixin, []);
|
||||
typeParameters(reflectClass(NonGenericClass2).mixin, []);
|
||||
typeParameters(reflectClass(GenericClass1).mixin, [#C]);
|
||||
typeParameters(reflectClass(GenericClass2).mixin, [#C]);
|
||||
typeParameters(reflectClass(NonGenericClass1).superclass.mixin, [#M]);
|
||||
typeParameters(reflectClass(NonGenericClass2).superclass.mixin, [#M]);
|
||||
typeParameters(reflectClass(GenericClass1).superclass.mixin, [#M]);
|
||||
typeParameters(reflectClass(GenericClass2).superclass.mixin, [#M]);
|
||||
typeParameters(reflectClass(GenericMultipleMixins).mixin, [#A, #B, #C]);
|
||||
typeParameters(reflectClass(GenericMultipleMixins).superclass.mixin, [#N]);
|
||||
typeParameters(
|
||||
reflectClass(GenericMultipleMixins).superclass.superclass.mixin, [#M]);
|
||||
typeParameters(
|
||||
reflectClass(GenericMultipleMixins)
|
||||
.superclass
|
||||
.superclass
|
||||
.superclass
|
||||
.mixin,
|
||||
[#S]);
|
||||
// Names of type variables are not preserved after type canonicalization
|
||||
// and are therefore not compared to expected names.
|
||||
|
||||
typeArguments(
|
||||
reflectClass(NonGenericMixinApplication1).mixin, [dynamicMirror]);
|
||||
|
@ -94,46 +73,8 @@ main() {
|
|||
.mixin,
|
||||
[reflectClass(GenericMultipleMixins).typeVariables[0]]);
|
||||
|
||||
typeParameters(reflect(new NonGenericMixinApplication1()).type.mixin, [#M]);
|
||||
typeParameters(reflect(new NonGenericMixinApplication2()).type.mixin, [#M]);
|
||||
typeParameters(
|
||||
reflect(new GenericMixinApplication1<bool>()).type.mixin, [#M]);
|
||||
typeParameters(
|
||||
reflect(new GenericMixinApplication2<bool>()).type.mixin, [#M]);
|
||||
typeParameters(reflect(new NonGenericClass1()).type.mixin, []);
|
||||
typeParameters(reflect(new NonGenericClass2()).type.mixin, []);
|
||||
typeParameters(reflect(new GenericClass1<bool>()).type.mixin, [#C]);
|
||||
typeParameters(reflect(new GenericClass2<bool>()).type.mixin, [#C]);
|
||||
typeParameters(reflect(new NonGenericClass1()).type.superclass.mixin, [#M]);
|
||||
typeParameters(reflect(new NonGenericClass2()).type.superclass.mixin, [#M]);
|
||||
typeParameters(
|
||||
reflect(new GenericClass1<bool>()).type.superclass.mixin, [#M]);
|
||||
typeParameters(
|
||||
reflect(new GenericClass2<bool>()).type.superclass.mixin, [#M]);
|
||||
typeParameters(
|
||||
reflect(new GenericMultipleMixins<bool, String, int>()).type.mixin,
|
||||
[#A, #B, #C]);
|
||||
typeParameters(
|
||||
reflect(new GenericMultipleMixins<bool, String, int>())
|
||||
.type
|
||||
.superclass
|
||||
.mixin,
|
||||
[#N]);
|
||||
typeParameters(
|
||||
reflect(new GenericMultipleMixins<bool, String, int>())
|
||||
.type
|
||||
.superclass
|
||||
.superclass
|
||||
.mixin,
|
||||
[#M]);
|
||||
typeParameters(
|
||||
reflect(new GenericMultipleMixins<bool, String, int>())
|
||||
.type
|
||||
.superclass
|
||||
.superclass
|
||||
.superclass
|
||||
.mixin,
|
||||
[#S]);
|
||||
|
||||
typeArguments(
|
||||
reflect(new NonGenericMixinApplication1()).type.mixin, [dynamicMirror]);
|
||||
|
|
|
@ -38,18 +38,15 @@ main() {
|
|||
Symbol t(ClassMirror cm) =>
|
||||
(cm.declarations[#t] as MethodMirror).returnType.simpleName;
|
||||
|
||||
Expect.equals(#T, r(genericDecl.superclass));
|
||||
// Names of type variables are not preserved after type canonicalization
|
||||
// and are therefore not compared to expected names.
|
||||
|
||||
Expect.equals(#int, s(genericDecl.superclass));
|
||||
Expect.equals(#T, t(genericDecl));
|
||||
|
||||
Expect.equals(#String, r(genericOfString.superclass));
|
||||
Expect.equals(#int, s(genericOfString.superclass));
|
||||
Expect.equals(#String, t(genericOfString));
|
||||
|
||||
Expect.equals(#R, r(superGenericDecl));
|
||||
Expect.equals(#S, s(superGenericDecl));
|
||||
|
||||
Expect.equals(#T, r(superOfTAndInt));
|
||||
Expect.equals(#int, s(superOfTAndInt));
|
||||
|
||||
Expect.equals(#String, r(superOfStringAndInt));
|
||||
|
|
|
@ -35,15 +35,15 @@ class I extends G {}
|
|||
|
||||
main() {
|
||||
// Declarations.
|
||||
typeParameters(reflectClass(A), [#T]);
|
||||
|
||||
// Names of type variables are not preserved after type canonicalization
|
||||
// and are therefore not compared to expected names.
|
||||
|
||||
typeParameters(reflectClass(G), []);
|
||||
typeParameters(reflectClass(B), []);
|
||||
typeParameters(reflectClass(C), []);
|
||||
typeParameters(reflectClass(D), []);
|
||||
typeParameters(reflectClass(E), [#S]);
|
||||
typeParameters(reflectClass(F), [#R]);
|
||||
typeParameters(reflectClass(G), []);
|
||||
typeParameters(reflectClass(H), [#A, #B, #C]);
|
||||
typeParameters(reflectClass(I), []);
|
||||
|
||||
typeArguments(reflectClass(A), []);
|
||||
|
@ -77,14 +77,10 @@ main() {
|
|||
Expect.equals(reflectClass(I), reflectClass(I).originalDeclaration);
|
||||
|
||||
// Instantiations.
|
||||
typeParameters(reflect(new A<num>()).type, [#T]);
|
||||
typeParameters(reflect(new B()).type, []);
|
||||
typeParameters(reflect(new C()).type, []);
|
||||
typeParameters(reflect(new D()).type, []);
|
||||
typeParameters(reflect(new E()).type, [#S]);
|
||||
typeParameters(reflect(new F<num>()).type, [#R]);
|
||||
typeParameters(reflect(new G()).type, []);
|
||||
typeParameters(reflect(new H()).type, [#A, #B, #C]);
|
||||
typeParameters(reflect(new I()).type, []);
|
||||
|
||||
var numMirror = reflectClass(num);
|
||||
|
|
|
@ -182,24 +182,11 @@ main() {
|
|||
|
||||
MethodMirror fooInC = cm.declarations[#foo] as MethodMirror;
|
||||
expect('Method(s(foo) in s(C))', fooInC);
|
||||
expect(
|
||||
'[Parameter(s(a) in s(foo),'
|
||||
' type = Class(s(int) in s(dart.core), top-level)), '
|
||||
'Parameter(s(b) in s(foo),'
|
||||
' type = TypeVariable(s(S) in s(Null),'
|
||||
' upperBound = Class(s(int) in s(dart.core), top-level)))]',
|
||||
fooInC.parameters);
|
||||
|
||||
// Names of type variables are not preserved after type canonicalization
|
||||
// and are therefore not compared to expected names.
|
||||
|
||||
|
||||
MethodMirror barInC = cm.declarations[#bar] as MethodMirror;
|
||||
expect('Method(s(bar) in s(C))', barInC);
|
||||
expect(
|
||||
'[Parameter(s(a) in s(bar),'
|
||||
' type = TypeVariable(s(S) in s(Null),'
|
||||
' upperBound = Class(s(int) in s(dart.core), top-level))), '
|
||||
'Parameter(s(b) in s(bar),'
|
||||
' type = TypeVariable(s(T) in s(Null),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))), '
|
||||
'Parameter(s(c) in s(bar),'
|
||||
' type = Class(s(num) in s(dart.core), top-level))]',
|
||||
barInC.parameters);
|
||||
}
|
||||
|
|
|
@ -29,13 +29,8 @@ main() {
|
|||
TypeVariableMirror ssFromSuperSuper =
|
||||
superOfSuperOfGeneric.typeVariables.single;
|
||||
|
||||
Expect.equals(#G, gFromGeneric.simpleName);
|
||||
Expect.equals(#S, sFromSuper.simpleName);
|
||||
Expect.equals(#SS, ssFromSuperSuper.simpleName);
|
||||
|
||||
typeParameters(generic, [#G]);
|
||||
typeParameters(superOfGeneric, [#S]);
|
||||
typeParameters(superOfSuperOfGeneric, [#SS]);
|
||||
// Names of type variables are not preserved after type canonicalization
|
||||
// and are therefore not compared to expected names.
|
||||
|
||||
typeArguments(generic, []);
|
||||
typeArguments(superOfGeneric, [gFromGeneric]);
|
||||
|
@ -46,10 +41,6 @@ main() {
|
|||
ClassMirror superOfGenericWithInt = genericWithInt.superclass;
|
||||
ClassMirror superOfSuperOfGenericWithInt = superOfGenericWithInt.superclass;
|
||||
|
||||
typeParameters(genericWithInt, [#G]);
|
||||
typeParameters(superOfGenericWithInt, [#S]);
|
||||
typeParameters(superOfSuperOfGenericWithInt, [#SS]);
|
||||
|
||||
typeArguments(genericWithInt, [reflectClass(int)]);
|
||||
typeArguments(superOfGenericWithInt, [reflectClass(int)]);
|
||||
typeArguments(superOfSuperOfGenericWithInt, [reflectClass(int)]);
|
||||
|
|
Loading…
Reference in a new issue