Index: runtime/vm/class_finalizer.cc |
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc |
index 340883a53f15c0602b02509276cdc7083f9fa1ce..873092feb4bdd7ba2226b5f27bade77d665a0b89 100644 |
--- a/runtime/vm/class_finalizer.cc |
+++ b/runtime/vm/class_finalizer.cc |
@@ -925,7 +925,6 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls, |
// Example: class B<T>; class D<T> extends B<D<T>>; |
// While finalizing D<T>, the super type arg D<T> (a typeref) gets |
// instantiated from vector [T], yielding itself. |
- // |
if (super_type_arg.IsTypeRef() && super_type_arg.IsBeingFinalized() && |
(super_type_arg.arguments() == arguments.raw())) { |
arguments.SetTypeAt(i, super_type_arg); |
@@ -1174,25 +1173,28 @@ RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls, |
const TypeParameter& type_parameter = TypeParameter::Cast(type); |
const Class& parameterized_class = |
Class::Handle(zone, type_parameter.parameterized_class()); |
+ intptr_t offset; |
if (!parameterized_class.IsNull()) { |
// The index must reflect the position of this type parameter in the type |
// arguments vector of its parameterized class. The offset to add is the |
// number of type arguments in the super type, which is equal to the |
// difference in number of type arguments and type parameters of the |
// parameterized class. |
- const intptr_t offset = parameterized_class.NumTypeArguments() - |
- parameterized_class.NumTypeParameters(); |
- // Calling NumTypeParameters() may finalize this type parameter if it |
- // belongs to a mixin application class. |
- if (!type_parameter.IsFinalized()) { |
- type_parameter.set_index(type_parameter.index() + offset); |
- type_parameter.SetIsFinalized(); |
- } else { |
- ASSERT(cls.IsMixinApplication()); |
- } |
+ offset = parameterized_class.NumTypeArguments() - |
+ parameterized_class.NumTypeParameters(); |
+ } else { |
+ const Function& function = |
+ Function::Handle(zone, type_parameter.parameterized_function()); |
+ ASSERT(!function.IsNull()); |
+ offset = function.NumParentTypeParameters(); |
+ } |
+ // Calling NumTypeParameters() may finalize this type parameter if it |
+ // belongs to a mixin application class. |
+ if (!type_parameter.IsFinalized()) { |
+ type_parameter.set_index(type_parameter.index() + offset); |
+ type_parameter.SetIsFinalized(); |
} else { |
- // A function type parameter is always finalized. |
- ASSERT(type_parameter.IsFinalized()); |
+ ASSERT(cls.IsMixinApplication()); |
} |
if (FLAG_trace_type_finalization) { |
@@ -1345,7 +1347,8 @@ void ClassFinalizer::FinalizeSignature(const Class& cls, |
FinalizationKind finalization) { |
AbstractType& type = AbstractType::Handle(); |
AbstractType& finalized_type = AbstractType::Handle(); |
- // Finalize upper bounds of function type parameters. |
+ // Finalize function type parameters and their upper bounds. |
+ const intptr_t num_parent_type_params = function.NumParentTypeParameters(); |
const intptr_t num_type_params = function.NumTypeParameters(); |
if (num_type_params > 0) { |
TypeParameter& type_param = TypeParameter::Handle(); |
@@ -1353,6 +1356,10 @@ void ClassFinalizer::FinalizeSignature(const Class& cls, |
TypeArguments::Handle(function.type_parameters()); |
for (intptr_t i = 0; i < num_type_params; i++) { |
type_param ^= type_params.TypeAt(i); |
+ if (!type_param.IsFinalized()) { |
+ type_param.set_index(num_parent_type_params + i); |
+ type_param.SetIsFinalized(); |
+ } |
type = type_param.bound(); |
finalized_type = FinalizeType(cls, type, finalization); |
if (finalized_type.raw() != type.raw()) { |
@@ -1822,7 +1829,7 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) { |
param_name = |
Symbols::FromConcat(thread, param_name, Symbols::Backtick()); |
cloned_param = |
- TypeParameter::New(mixin_app_class, null_function, cloned_index, 0, |
+ TypeParameter::New(mixin_app_class, null_function, cloned_index, |
param_name, param_bound, param.token_pos()); |
cloned_type_params.SetTypeAt(cloned_index, cloned_param); |
// Change the type arguments of the super type to refer to the |
@@ -1860,7 +1867,7 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) { |
cloned_param = |
TypeParameter::New(mixin_app_class, null_function, |
cloned_index, // Unfinalized index. |
- 0, param_name, param_bound, param.token_pos()); |
+ param_name, param_bound, param.token_pos()); |
cloned_type_params.SetTypeAt(cloned_index, cloned_param); |
mixin_type_args.SetTypeAt(i, cloned_param); // Unfinalized length. |
instantiator.SetTypeAt(offset + i, cloned_param); // Finalized length. |
@@ -2434,8 +2441,8 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { |
FinalizeTypesInClass(super_class); |
} |
// Finalize type parameters before finalizing the super type. |
- FinalizeTypeParameters(cls); // May change super type. |
- super_class = cls.SuperClass(); |
+ FinalizeTypeParameters(cls); // May change super type while applying mixin. |
+ super_class = cls.SuperClass(); // Get again possibly changed super class. |
ASSERT(super_class.IsNull() || super_class.is_type_finalized()); |
// Only resolving rather than finalizing the upper bounds here would result in |
// instantiated type parameters of the super type to temporarily have |