Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(659)

Unified Diff: runtime/vm/class_finalizer.cc

Issue 1232613005: Allow super calls in mixins (for now behind a --supermixin flag). (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Address comments Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/object.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/class_finalizer.cc
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 4af663639458e768d06615a0294f9662ee7ee2f3..75b832b970c73ee2c6fbadd69f451ef81d7e8d05 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -18,6 +18,7 @@ namespace dart {
DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes.");
DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization.");
DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization.");
+DECLARE_FLAG(bool, supermixin);
DECLARE_FLAG(bool, use_cha_deopt);
@@ -1561,14 +1562,16 @@ void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
// In other words, decorate this mixin application class with type parameters
// that forward to the super type and mixin type (and interface type).
// Example:
-// class S<T> { }
-// class M<T> { }
-// class C<E> extends S<E> with M<List<E>> { }
+// class S<T extends BT> { }
+// class M<T extends BT> { }
+// class C<E extends BE> extends S<E> with M<List<E>> { }
// results in
-// class S&M<T`, T> extends S<T`> implements M<T> { } // mixin == M<T>
-// class C<E> extends S&M<E, List<E>> { }
+// class S&M<T`, T extends BT> extends S<T`> implements M<T> { }
+// class C<E extends BE> extends S&M<E, List<E>> { }
// CloneMixinAppTypeParameters decorates class S&M with type parameters T` and
// T, and use them as type arguments in S<T`> and M<T>.
+// Note that the bound BT on T of S is not applied to T` of S&M. However, the
+// bound BT on T of M is applied to T of S&M. See comments below.
void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
ASSERT(mixin_app_class.type_parameters() == TypeArguments::null());
Isolate* isolate = Isolate::Current();
@@ -1580,8 +1583,6 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
const Type& mixin_type = Type::Handle(isolate, mixin_app_class.mixin());
const Class& mixin_class = Class::Handle(isolate, mixin_type.type_class());
const intptr_t num_mixin_type_params = mixin_class.NumTypeParameters();
- // The mixin class cannot be Object and this was checked earlier.
- ASSERT(!mixin_class.IsObjectClass());
// The mixin type (in raw form) should have been added to the interfaces
// implemented by the mixin application class. This is necessary so that cycle
@@ -1593,7 +1594,7 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
// If both the super type and the mixin type are non generic, the mixin
// application class is non generic as well and we can skip type parameter
// cloning.
- bool has_uninstantiated_bounds = false;
+ TypeArguments& instantiator = TypeArguments::Handle(isolate);
if ((num_super_type_params + num_mixin_type_params) > 0) {
// If the last ampersand in the name of the mixin application class is
// doubled, the same type parameters can propagate the type arguments to
@@ -1630,7 +1631,12 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
TypeArguments::New(num_super_type_params));
// The cloned super class type parameters do not need to repeat their
// bounds, since the bound checks will be performed at the super class
- // level.
+ // level. As a consequence, if this mixin application is used itself as a
+ // mixin in another mixin application, the bounds will be ignored, which
+ // is correct, because the other mixin application does not inherit from
+ // the super class of its mixin. Note also that the other mixin
+ // application will only mixin the last mixin type listed in the first
+ // mixin application it is mixing in.
param_bound = isolate->object_store()->object_type();
for (intptr_t i = 0; i < num_super_type_params; i++) {
param ^= super_type_params.TypeAt(i);
@@ -1658,12 +1664,16 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
// We need to retain the parameter names of the mixin class
// since the code that will be compiled in the context of the
// mixin application class may refer to the type parameters
- // with that name.
+ // with that name. We also retain the type parameter bounds.
if (num_mixin_type_params > 0) {
const TypeArguments& mixin_params =
TypeArguments::Handle(isolate, mixin_class.type_parameters());
+ const intptr_t offset =
+ mixin_class.NumTypeArguments() - mixin_class.NumTypeParameters();
const TypeArguments& mixin_type_args = TypeArguments::Handle(isolate,
TypeArguments::New(num_mixin_type_params));
+ instantiator ^= TypeArguments::New(offset + num_mixin_type_params);
+ bool has_uninstantiated_bounds = false;
for (intptr_t i = 0; i < num_mixin_type_params; i++) {
param ^= mixin_params.TypeAt(i);
param_name = param.name();
@@ -1672,27 +1682,26 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
has_uninstantiated_bounds = true;
}
cloned_param = TypeParameter::New(mixin_app_class,
- cloned_index,
+ cloned_index, // Unfinalized index.
param_name,
param_bound,
param.token_pos());
cloned_type_params.SetTypeAt(cloned_index, cloned_param);
- mixin_type_args.SetTypeAt(i, cloned_param);
+ mixin_type_args.SetTypeAt(i, cloned_param); // Unfinalized length.
+ instantiator.SetTypeAt(offset + i, cloned_param); // Finalized length.
cloned_index++;
}
// Third, replace the type parameters appearing in the bounds of the mixin
// type parameters, if any, by the cloned type parameters. This can be
- // done by instantiating each bound using the mixin_type_args as
- // instantiator. Since the mixin class must extend Object, its first type
- // parameter has index 0, therefore, the instantiator does not require
- // shifting. There is however an exception where the mixin class is an
- // alias, in which case shifting is required and performed later in
- // ApplyMixinAppAlias.
+ // done by instantiating each bound using the instantiator built above.
+ // If the mixin class extends a generic super class, its first finalized
+ // type parameter has a non-zero index, therefore, the instantiator
+ // requires shifting by the offset calculated above.
// Unfinalized type parameters replace finalized type parameters, which
// is not a problem since they will get finalized shortly as the mixin
// application class gets finalized.
- if (has_uninstantiated_bounds && !mixin_class.is_mixin_app_alias()) {
+ if (has_uninstantiated_bounds) {
Error& bound_error = Error::Handle(isolate);
for (intptr_t i = 0; i < num_mixin_type_params; i++) {
param ^= mixin_type_args.TypeAt(i);
@@ -1705,10 +1714,11 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
FinalizeType(mixin_app_class, param_bound, kCanonicalize);
param.set_bound(param_bound); // In case part of recursive type.
}
- param_bound = param_bound.InstantiateFrom(mixin_type_args,
+ param_bound = param_bound.InstantiateFrom(instantiator,
&bound_error);
// The instantiator contains only TypeParameter objects and no
// BoundedType objects, so no bound error may occur.
+ ASSERT(!param_bound.IsBoundedType());
ASSERT(bound_error.IsNull());
ASSERT(!param_bound.IsInstantiated());
param.set_bound(param_bound);
@@ -1732,7 +1742,7 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
// application class. The new class will have the aliased mixin as actual
// mixin.
if (mixin_class.is_mixin_app_alias()) {
- ApplyMixinAppAlias(mixin_app_class, has_uninstantiated_bounds);
+ ApplyMixinAppAlias(mixin_app_class, instantiator);
}
}
@@ -1742,19 +1752,23 @@ Consider the following example:
class I<T> { }
class J<T> { }
-class S<T> { }
-class M<T> { }
-class A<U, V> = Object with M<Map<U, V>> implements I<V>;
-class C<T, K> = S<T> with A<T, List<K>> implements J<K>;
+class S<T extends num> { }
+class M<T extends Map> { }
+class A<U, V extends List> = Object with M<Map<U, V>> implements I<V>;
+class C<T, K extends T> = S<T> with A<T, List<K>> implements J<K>;
Before the call to ApplyMixinAppAlias, the VM has already synthesized 2 mixin
application classes Object&M and S&A:
-Object&M<T> extends Object implements M<T> { ... members of M applied here ... }
-A<U, V> extends Object&M<Map<U, V>> implements I<V> { }
+Object&M<T extends Map> extends Object implements M<T> {
+ ... members of M applied here ...
+}
+A<U, V extends List> extends Object&M<Map<U, V>> implements I<V> { }
-S&A<T`, U, V> extends S<T`> implements A<U, V> { }
-C<T, K> extends S&A<T, T, List<K>> implements J<K> { }
+S&A<T`, U, V extends List> extends S<T`> implements A<U, V> {
+ ... members of A applied here, but A has no members ...
+}
+C<T, K extends T> extends S&A<T, T, List<K>> implements J<K> { }
In theory, class A should be an alias of Object&M instead of extending it.
In practice, the additional class provides a hook for implemented interfaces
@@ -1764,9 +1778,6 @@ type parameters of the alias A).
Similarly, class C should be an alias of S&A instead of extending it.
-Since A is used as a mixin, it must extend Object. The fact that it extends
-Object&M must be hidden so that no error is wrongly reported.
-
Now, A does not have any members to be mixed into S&A, because A is an alias.
The members to be mixed in are actually those of M, and they should appear in a
scope where the type parameter T is visible. The class S&A declares the type
@@ -1776,11 +1787,13 @@ Therefore, the call to ApplyMixinAppAlias inserts another synthesized class S&A`
as the superclass of S&A. The class S&A` declares a type argument T:
Instead of
-S&A<T`, U, V> extends S<T`> implements A<U, V> { }
+S&A<T`, U, V extends List> extends S<T`> implements A<U, V> { }
We now have:
-S&A`<T`, T> extends S<T`> implements M<T> { ... members of M applied here ... }
-S&A<T`, U, V> extends S&A`<T`, Map<U, V>> implements A<U, V> { }
+S&A`<T`, T extends Map> extends S<T`> implements M<T> {
+ ... members of M applied here ...
+}
+S&A<T`, U, V extends List> extends S&A`<T`, Map<U, V>> implements A<U, V> { }
The main implementation difficulty resides in the fact that the type parameters
U and V in the super type S&A`<T`, Map<U, V>> of S&A must refer to the type
@@ -1789,23 +1802,24 @@ Object&M<Map<U, V>> of A and, therefore, U and V refer to A. An instantiation
step with a properly crafted instantiator vector takes care of the required type
parameter substitution.
The instantiator vector must end with the type parameters U and V of S&A.
-The offset of the first type parameter U of S&A must be at the finalized index
-of type parameter U of A.
+The offset in the instantiator of the type parameter U of S&A must be at the
+finalized index of type parameter U of A.
The same instantiator vector is used to adjust the type parameter bounds on U
-and V, if any. This step was postponed from CloneMixinAppTypeParameters above.
-
-Also, a possible bound on type parameter T of M (not shown in the example above)
-must be applied to type parameter T of S&A`. If the bound is uninstantiated,
-i.e. if it refers to T or other type parameters of M, an instantiation step is
-required to substitute these type parameters of M with type parameters of S&A`.
-The instantiator vector consists of the cloned type parameters of M without
-offset, since class M must extend Object. This is done in the recursive call to
-CloneMixinAppTypeParameters and does not require specific code in
-ApplyMixinAppAlias.
+and V, if any. This step is done in CloneMixinAppTypeParameters above, and the
+already built instantiator is passed here.
+
+Also, a possible bound on type parameter T of M must be applied to type
+parameter T of S&A`. If the bound is uninstantiated, i.e. if it refers to T or
+other type parameters of M, an instantiation step is required to substitute
+these type parameters of M with type parameters of S&A`.
+The instantiator vector consists of the cloned type parameters of M shifted by
+an offset corresponding to the finalized index of the first type parameter of M.
+This is done in the recursive call to CloneMixinAppTypeParameters and does not
+require specific code in ApplyMixinAppAlias.
*/
void ClassFinalizer::ApplyMixinAppAlias(const Class& mixin_app_class,
- bool has_uninstantiated_bounds) {
+ const TypeArguments& instantiator) {
// If this mixin alias is aliasing another mixin alias, another class
// will be inserted via recursion. No need to check here.
// The mixin type may or may not be finalized yet.
@@ -1817,6 +1831,12 @@ void ClassFinalizer::ApplyMixinAppAlias(const Class& mixin_app_class,
ASSERT(mixin_class.is_mixin_app_alias());
const Class& aliased_mixin_app_class = Class::Handle(isolate,
mixin_class.SuperClass());
+ // Note that the super class of aliased_mixin_app_class can itself be a
+ // mixin application class (this happens if the alias is mixing more than one
+ // type). Instead of trying to recursively insert yet another class as the
+ // super class of this inserted class, we apply the composition rules of the
+ // spec and only mixin the members of aliased_mixin_app_class, not those of
+ // its super class. In other words, we only mixin the last mixin of the alias.
const Type& aliased_mixin_type = Type::Handle(isolate,
aliased_mixin_app_class.mixin());
// The name of the inserted mixin application class is the name of mixin
@@ -1851,18 +1871,19 @@ void ClassFinalizer::ApplyMixinAppAlias(const Class& mixin_app_class,
// The mixin type and interface type must also be set before calling
// CloneMixinAppTypeParameters.
- // After FinalizeTypesInClass, they will refer to the type parameters of
- // the mixin class typedef.
- const Type& generic_mixin_type = Type::Handle(isolate,
+ // After FinalizeTypesInClass, if the mixin type and interface type are
+ // generic, their type arguments will refer to the type parameters of
+ // inserted_class.
+ const Type& inserted_class_mixin_type = Type::Handle(isolate,
Type::New(Class::Handle(isolate, aliased_mixin_type.type_class()),
Object::null_type_arguments(),
aliased_mixin_type.token_pos()));
- inserted_class.set_mixin(generic_mixin_type);
+ inserted_class.set_mixin(inserted_class_mixin_type);
// Add the mixin type to the list of interfaces that the mixin application
// class implements. This is necessary so that cycle check work at
// compile time (type arguments are ignored by that check).
const Array& interfaces = Array::Handle(Array::New(1));
- interfaces.SetAt(0, generic_mixin_type);
+ interfaces.SetAt(0, inserted_class_mixin_type);
ASSERT(inserted_class.interfaces() == Object::empty_array().raw());
inserted_class.set_interfaces(interfaces);
// The type arguments of the interface, if any, will be set in
@@ -1885,60 +1906,68 @@ void ClassFinalizer::ApplyMixinAppAlias(const Class& mixin_app_class,
// It is important that the type parameters of the mixin application class
// are not finalized yet, because new type parameters may have been added
// to the super class.
- Class& super_class = Class::Handle(isolate, super_type.type_class());
- ASSERT(mixin_app_class.SuperClass() == super_class.raw());
- while (super_class.IsMixinApplication()) {
- super_class = super_class.SuperClass();
- }
+ const Class& super_class = Class::Handle(isolate, super_type.type_class());
+ ASSERT(mixin_app_class.SuperClass() == super_class.raw()); // Will change.
const intptr_t num_super_type_params = super_class.NumTypeParameters();
- const intptr_t num_mixin_type_params = mixin_class.NumTypeParameters();
- intptr_t offset =
- mixin_class.NumTypeArguments() - mixin_class.NumTypeParameters();
- const TypeArguments& type_params =
- TypeArguments::Handle(isolate, mixin_app_class.type_parameters());
- TypeArguments& instantiator = TypeArguments::Handle(isolate,
- TypeArguments::New(offset + num_mixin_type_params));
AbstractType& type = AbstractType::Handle(isolate);
- for (intptr_t i = 0; i < num_mixin_type_params; i++) {
- type = type_params.TypeAt(num_super_type_params + i);
- instantiator.SetTypeAt(offset + i, type);
- }
+ // The instantiator is mapping finalized type parameters of mixin_class to
+ // unfinalized type parameters of mixin_app_class.
ASSERT(aliased_mixin_type.IsFinalized());
const Class& aliased_mixin_type_class = Class::Handle(isolate,
aliased_mixin_type.type_class());
const intptr_t num_aliased_mixin_type_params =
aliased_mixin_type_class.NumTypeParameters();
- const intptr_t num_aliased_mixin_type_args =
- aliased_mixin_type_class.NumTypeArguments();
- offset = num_aliased_mixin_type_args - num_aliased_mixin_type_params;
ASSERT(inserted_class.NumTypeParameters() ==
(num_super_type_params + num_aliased_mixin_type_params));
+ const AbstractType& mixin_class_super_type =
+ AbstractType::Handle(isolate, mixin_class.super_type());
+ ASSERT(mixin_class_super_type.IsFinalized());
// The aliased_mixin_type may be raw.
const TypeArguments& mixin_class_super_type_args =
- TypeArguments::Handle(isolate,
- AbstractType::Handle(isolate, mixin_class.super_type()).arguments());
+ TypeArguments::Handle(isolate, mixin_class_super_type.arguments());
TypeArguments& new_mixin_type_args = TypeArguments::Handle(isolate);
if ((num_aliased_mixin_type_params > 0) &&
!mixin_class_super_type_args.IsNull()) {
new_mixin_type_args = TypeArguments::New(num_aliased_mixin_type_params);
+ AbstractType& bounded_type = AbstractType::Handle(isolate);
+ AbstractType& upper_bound = AbstractType::Handle(isolate);
+ TypeParameter& type_parameter = TypeParameter::Handle(isolate);
+ Error& bound_error = Error::Handle(isolate);
+ const intptr_t offset =
+ mixin_class_super_type_args.Length() - num_aliased_mixin_type_params;
for (intptr_t i = 0; i < num_aliased_mixin_type_params; i++) {
type = mixin_class_super_type_args.TypeAt(offset + i);
+ if (!type.IsInstantiated()) {
+ // In the presence of bounds, the bounded type and the upper bound must
+ // be instantiated separately. Instantiating a BoundedType would wrap
+ // the BoundedType in another BoundedType.
+ if (type.IsBoundedType()) {
+ bounded_type = BoundedType::Cast(type).type();
+ bounded_type = bounded_type.InstantiateFrom(instantiator,
+ &bound_error);
+ // The instantiator contains only TypeParameter objects and no
+ // BoundedType objects, so no bound error may occur.
+ ASSERT(bound_error.IsNull());
+ upper_bound = BoundedType::Cast(type).bound();
+ upper_bound = upper_bound.InstantiateFrom(instantiator, &bound_error);
+ ASSERT(bound_error.IsNull());
+ type_parameter = BoundedType::Cast(type).type_parameter();
+ // The type parameter that declared the bound does not change.
+ type = BoundedType::New(bounded_type, upper_bound, type_parameter);
+ } else {
+ type = type.InstantiateFrom(instantiator, &bound_error);
+ ASSERT(bound_error.IsNull());
+ }
+ }
new_mixin_type_args.SetTypeAt(i, type);
}
}
- if (!new_mixin_type_args.IsNull() &&
- !new_mixin_type_args.IsInstantiated()) {
- Error& bound_error = Error::Handle(isolate);
- new_mixin_type_args ^=
- new_mixin_type_args.InstantiateFrom(instantiator, &bound_error);
- // The instantiator contains only TypeParameter objects and no BoundedType
- // objects, so no bound error may occur.
- ASSERT(bound_error.IsNull());
- }
TypeArguments& new_super_type_args = TypeArguments::Handle(isolate);
if ((num_super_type_params + num_aliased_mixin_type_params) > 0) {
new_super_type_args = TypeArguments::New(num_super_type_params +
num_aliased_mixin_type_params);
+ const TypeArguments& type_params =
+ TypeArguments::Handle(isolate, mixin_app_class.type_parameters());
for (intptr_t i = 0; i < num_super_type_params; i++) {
type = type_params.TypeAt(i);
new_super_type_args.SetTypeAt(i, type);
@@ -1957,35 +1986,23 @@ void ClassFinalizer::ApplyMixinAppAlias(const Class& mixin_app_class,
mixin_app_class.token_pos());
mixin_app_class.set_super_type(super_type);
- // Perform the bound adjustment posponed from CloneMixinAppTypeParameters.
- if (has_uninstantiated_bounds) {
- TypeParameter& param = TypeParameter::Handle(isolate);
- AbstractType& param_bound = AbstractType::Handle(isolate);
- Error& bound_error = Error::Handle(isolate);
- for (intptr_t i = 0; i < num_mixin_type_params; i++) {
- param ^= type_params.TypeAt(num_super_type_params + i);
- param_bound = param.bound();
- if (!param_bound.IsInstantiated()) {
- param_bound = param_bound.InstantiateFrom(instantiator, &bound_error);
- // The instantiator contains only TypeParameter objects and no
- // BoundedType objects, so no bound error may occur.
- ASSERT(bound_error.IsNull());
- ASSERT(!param_bound.IsInstantiated());
- param.set_bound(param_bound);
- }
- }
- }
-
// Mark this mixin application class as being an alias.
mixin_app_class.set_is_mixin_app_alias();
ASSERT(!mixin_app_class.is_type_finalized());
ASSERT(!mixin_app_class.is_mixin_type_applied());
if (FLAG_trace_class_finalization) {
- OS::Print("Inserting class %s to mixin application alias %s "
- "with super type '%s'\n",
- inserted_class.ToCString(),
- mixin_app_class.ToCString(),
- String::Handle(isolate, super_type.Name()).ToCString());
+ OS::Print("Inserting class '%s' %s\n"
+ " as super type '%s' with %" Pd " type args: %s\n"
+ " of mixin application alias '%s' %s\n",
+ String::Handle(inserted_class.Name()).ToCString(),
+ TypeArguments::Handle(
+ inserted_class.type_parameters()).ToCString(),
+ String::Handle(isolate, super_type.Name()).ToCString(),
+ num_super_type_params + num_aliased_mixin_type_params,
+ super_type.ToCString(),
+ String::Handle(mixin_app_class.Name()).ToCString(),
+ TypeArguments::Handle(
+ mixin_app_class.type_parameters()).ToCString());
}
}
@@ -2007,8 +2024,7 @@ void ClassFinalizer::ApplyMixinType(const Class& mixin_app_class,
mixin_app_class.token_pos());
}
- // Check for illegal self references. This has to be done before checking
- // that the super class of the mixin class is class Object.
+ // Check for illegal self references.
GrowableArray<intptr_t> visited_mixins;
if (!IsMixinCycleFree(mixin_class, &visited_mixins)) {
const String& class_name = String::Handle(mixin_class.Name());
@@ -2017,21 +2033,23 @@ void ClassFinalizer::ApplyMixinType(const Class& mixin_app_class,
class_name.ToCString());
}
- // Check that the super class of the mixin class is class Object.
- Class& mixin_super_class = Class::Handle(mixin_class.SuperClass());
- // Skip over mixin application alias classes, which are implemented as
- // subclasses of the mixin application classes they name.
- if (!mixin_super_class.IsNull() && mixin_class.is_mixin_app_alias()) {
- while (mixin_super_class.is_mixin_app_alias()) {
+ if (!FLAG_supermixin) {
+ // Check that the super class of the mixin class is class Object.
+ Class& mixin_super_class = Class::Handle(mixin_class.SuperClass());
+ // Skip over mixin application alias classes, which are implemented as
+ // subclasses of the mixin application classes they name.
+ if (!mixin_super_class.IsNull() && mixin_class.is_mixin_app_alias()) {
+ while (mixin_super_class.is_mixin_app_alias()) {
+ mixin_super_class = mixin_super_class.SuperClass();
+ }
mixin_super_class = mixin_super_class.SuperClass();
}
- mixin_super_class = mixin_super_class.SuperClass();
- }
- if (mixin_super_class.IsNull() || !mixin_super_class.IsObjectClass()) {
- const String& class_name = String::Handle(mixin_class.Name());
- ReportError(mixin_app_class, mixin_app_class.token_pos(),
- "mixin class '%s' must extend class 'Object'",
- class_name.ToCString());
+ if (mixin_super_class.IsNull() || !mixin_super_class.IsObjectClass()) {
+ const String& class_name = String::Handle(mixin_class.Name());
+ ReportError(mixin_app_class, mixin_app_class.token_pos(),
+ "mixin class '%s' must extend class 'Object'",
+ class_name.ToCString());
+ }
}
// Copy type parameters to mixin application class.
@@ -2297,6 +2315,7 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
// Check whether the interface is duplicated. We need to wait with
// this check until the super type and interface types are finalized,
// so that we can use Type::Equals() for the test.
+ // TODO(regis): This restriction about duplicated interfaces may get lifted.
ASSERT(interface_type.IsFinalized());
ASSERT(super_type.IsNull() || super_type.IsFinalized());
if (!super_type.IsNull() && interface_type.Equals(super_type)) {
@@ -2643,7 +2662,6 @@ RawType* ClassFinalizer::ResolveMixinAppType(
// a BoundedType itself.
CollectTypeArguments(cls, Type::Cast(mixin_super_type), type_args);
AbstractType& mixin_type = AbstractType::Handle(isolate);
- Type& generic_mixin_type = Type::Handle(isolate);
Class& mixin_type_class = Class::Handle(isolate);
Class& mixin_app_class = Class::Handle(isolate);
String& mixin_app_class_name = String::Handle(isolate);
@@ -2704,9 +2722,10 @@ RawType* ClassFinalizer::ResolveMixinAppType(
mixin_type.token_pos());
mixin_app_class.set_super_type(mixin_super_type);
mixin_type_class = mixin_type.type_class();
- generic_mixin_type = Type::New(mixin_type_class,
- Object::null_type_arguments(),
- mixin_type.token_pos());
+ const Type& generic_mixin_type = Type::Handle(isolate,
+ Type::New(mixin_type_class,
+ Object::null_type_arguments(),
+ mixin_type.token_pos()));
mixin_app_class.set_mixin(generic_mixin_type);
// Add the mixin type to the list of interfaces that the mixin application
// class implements. This is necessary so that cycle check work at
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698