Index: runtime/vm/class_finalizer.cc |
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc |
index ace3016cc7194b7b6d850720f829ece352f0e8c6..184772653046a9864fa61350381d2103eb188b76 100644 |
--- a/runtime/vm/class_finalizer.cc |
+++ b/runtime/vm/class_finalizer.cc |
@@ -440,7 +440,8 @@ void ClassFinalizer::ResolveRedirectingFactoryTarget( |
if (!target_type.IsInstantiated()) { |
const TypeArguments& type_args = TypeArguments::Handle(type.arguments()); |
Error& bound_error = Error::Handle(); |
- target_type ^= target_type.InstantiateFrom(type_args, &bound_error); |
+ target_type ^= target_type.InstantiateFrom( |
+ type_args, &bound_error, NULL, Heap::kOld); |
if (bound_error.IsNull()) { |
target_type ^= FinalizeType(cls, target_type, kCanonicalize); |
} else { |
@@ -457,10 +458,10 @@ void ClassFinalizer::ResolveRedirectingFactoryTarget( |
} |
-void ClassFinalizer::ResolveTypeClass(const Class& cls, |
- const AbstractType& type) { |
- if (type.IsFinalized() || type.HasResolvedTypeClass()) { |
- return; |
+RawAbstractType* ClassFinalizer::ResolveTypeClass(const Class& cls, |
+ const Type& type) { |
+ if (type.IsFinalized()) { |
+ return type.raw(); |
} |
if (FLAG_trace_type_finalization) { |
THR_Print("Resolve type class of '%s'\n", |
@@ -473,55 +474,77 @@ void ClassFinalizer::ResolveTypeClass(const Class& cls, |
// that the type parameter appeared in a static scope. Leaving the type as |
// unresolved is the correct thing to do. |
- // Lookup the type class. |
- const UnresolvedClass& unresolved_class = |
- UnresolvedClass::Handle(type.unresolved_class()); |
- const Class& type_class = |
- Class::Handle(ResolveClass(cls, unresolved_class)); |
- |
- // Replace unresolved class with resolved type class. |
- const Type& parameterized_type = Type::Cast(type); |
- if (type_class.IsNull()) { |
- // The type class could not be resolved. The type is malformed. |
- FinalizeMalformedType( |
- Error::Handle(), // No previous error. |
- Script::Handle(cls.script()), |
- parameterized_type, |
- "cannot resolve class '%s' from '%s'", |
- String::Handle(unresolved_class.Name()).ToCString(), |
- String::Handle(cls.Name()).ToCString()); |
- return; |
+ // Lookup the type class if necessary. |
+ Class& type_class = Class::Handle(); |
+ if (type.HasResolvedTypeClass()) { |
+ type_class = type.type_class(); |
+ } else { |
+ const UnresolvedClass& unresolved_class = |
+ UnresolvedClass::Handle(type.unresolved_class()); |
+ type_class = ResolveClass(cls, unresolved_class); |
+ if (type_class.IsNull()) { |
+ // The type class could not be resolved. The type is malformed. |
+ FinalizeMalformedType( |
+ Error::Handle(), // No previous error. |
+ Script::Handle(cls.script()), |
+ type, |
+ "cannot resolve class '%s' from '%s'", |
+ String::Handle(unresolved_class.Name()).ToCString(), |
+ String::Handle(cls.Name()).ToCString()); |
+ return type.raw(); |
+ } |
+ } |
+ // Promote the Type to a FunctionType in case its type class is a typedef. |
+ if (type_class.IsTypedefClass()) { |
+ return FunctionType::New(type_class, |
+ TypeArguments::Handle(type.arguments()), |
+ Function::Handle(type_class.signature_function()), |
+ type.token_pos()); |
} |
- parameterized_type.set_type_class(type_class); |
+ // Replace unresolved class with resolved type class. |
+ type.set_type_class(type_class); |
+ return type.raw(); |
} |
-void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) { |
+RawAbstractType* ClassFinalizer::ResolveType(const Class& cls, |
+ const AbstractType& type) { |
if (type.IsResolved()) { |
- return; |
+ return type.raw(); |
} |
- ASSERT(type.IsType()); |
if (FLAG_trace_type_finalization) { |
THR_Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString()); |
} |
- ResolveTypeClass(cls, type); |
- if (type.IsMalformed()) { |
- ASSERT(type.IsResolved()); |
- return; |
+ AbstractType& resolved_type = AbstractType::Handle(); |
+ if (type.IsType()) { |
+ resolved_type = ResolveTypeClass(cls, Type::Cast(type)); |
+ if (resolved_type.IsMalformed()) { |
+ ASSERT(resolved_type.IsResolved()); |
+ return resolved_type.raw(); |
+ } |
+ } else { |
+ ASSERT(type.IsFunctionType()); |
+ const Function& signature = |
+ Function::Handle(FunctionType::Cast(type).signature()); |
+ ResolveSignature(cls, signature); |
+ resolved_type = type.raw(); |
} |
// Mark type as resolved before resolving its type arguments in order to avoid |
// repeating resolution of recursive types. |
- Type::Cast(type).set_is_resolved(); |
+ resolved_type.SetIsResolved(); |
// Resolve type arguments, if any. |
- const TypeArguments& arguments = TypeArguments::Handle(type.arguments()); |
+ const TypeArguments& arguments = |
+ TypeArguments::Handle(resolved_type.arguments()); |
if (!arguments.IsNull()) { |
const intptr_t num_arguments = arguments.Length(); |
AbstractType& type_argument = AbstractType::Handle(); |
for (intptr_t i = 0; i < num_arguments; i++) { |
type_argument = arguments.TypeAt(i); |
- ResolveType(cls, type_argument); |
+ type_argument = ResolveType(cls, type_argument); |
+ arguments.SetTypeAt(i, type_argument); |
} |
} |
+ return resolved_type.raw(); |
} |
@@ -564,7 +587,7 @@ void ClassFinalizer::FinalizeTypeParameters( |
// A non-contractive type can be detected by looking at the queue of types |
// pending finalization that are mutually recursive with the checked type. |
void ClassFinalizer::CheckRecursiveType(const Class& cls, |
- const Type& type, |
+ const AbstractType& type, |
PendingTypes* pending_types) { |
Zone* zone = Thread::Current()->zone(); |
if (FLAG_trace_type_finalization) { |
@@ -620,6 +643,127 @@ void ClassFinalizer::CheckRecursiveType(const Class& cls, |
} |
+// 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( |
+ const Class& cls, |
+ const AbstractType& type, |
+ PendingTypes* pending_types) { |
+ Zone* Z = Thread::Current()->zone(); |
+ // The type class does not need to be finalized in order to finalize the type, |
+ // however, it must at least be resolved (this was done as part of resolving |
+ // the type itself, a precondition to calling FinalizeType). |
+ // Also, the interfaces of the type class must be resolved and the type |
+ // parameters of the type class must be finalized. |
+ Class& type_class = Class::Handle(Z, type.type_class()); |
+ if (!type_class.is_type_finalized()) { |
+ FinalizeTypeParameters(type_class, pending_types); |
+ ResolveUpperBounds(type_class); |
+ } |
+ |
+ // The finalized type argument vector needs num_type_arguments types. |
+ const intptr_t num_type_arguments = type_class.NumTypeArguments(); |
+ // The class has num_type_parameters type parameters. |
+ const intptr_t num_type_parameters = type_class.NumTypeParameters(); |
+ |
+ // Initialize the type argument vector. |
+ // Check the number of parsed type arguments, if any. |
+ // Specifying no type arguments indicates a raw type, which is not an error. |
+ // However, type parameter bounds are checked below, even for a raw type. |
+ TypeArguments& arguments = TypeArguments::Handle(Z, type.arguments()); |
+ if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) { |
+ // Wrong number of type arguments. The type is mapped to the raw type. |
+ if (Isolate::Current()->flags().error_on_bad_type()) { |
+ const String& type_class_name = String::Handle(Z, type_class.Name()); |
+ ReportError(cls, type.token_pos(), |
+ "wrong number of type arguments for class '%s'", |
+ type_class_name.ToCString()); |
+ } |
+ // Make the type raw and continue without reporting any error. |
+ // A static warning should have been reported. |
+ arguments = TypeArguments::null(); |
+ type.set_arguments(arguments); |
+ } |
+ |
+ // Mark the type as being finalized in order to detect self reference and |
+ // postpone bound checking until after all types in the graph of |
+ // mutually recursive types are finalized. |
+ type.SetIsBeingFinalized(); |
+ pending_types->Add(type); |
+ |
+ // The full type argument vector consists of the type arguments of the |
+ // super types of type_class, which are initialized from the parsed |
+ // type arguments, followed by the parsed type arguments. |
+ TypeArguments& full_arguments = TypeArguments::Handle(Z); |
+ if (num_type_arguments > 0) { |
+ // If no type arguments were parsed and if the super types do not prepend |
+ // type arguments to the vector, we can leave the vector as null. |
+ if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) { |
+ full_arguments = TypeArguments::New(num_type_arguments); |
+ // Copy the parsed type arguments at the correct offset in the full type |
+ // argument vector. |
+ const intptr_t offset = num_type_arguments - num_type_parameters; |
+ AbstractType& type_arg = |
+ AbstractType::Handle(Z, Type::DynamicType()); |
+ // Leave the temporary type arguments at indices [0..offset[ as null. |
+ for (intptr_t i = 0; i < num_type_parameters; i++) { |
+ // If no type parameters were provided, a raw type is desired, so we |
+ // create a vector of dynamic. |
+ if (!arguments.IsNull()) { |
+ type_arg = arguments.TypeAt(i); |
+ // The parsed type_arg may or may not be finalized. |
+ } |
+ full_arguments.SetTypeAt(offset + i, type_arg); |
+ } |
+ // Replace the compile-time argument vector (of length zero or |
+ // num_type_parameters) of this type being finalized with the still |
+ // unfinalized run-time argument vector (of length num_type_arguments). |
+ // This type being finalized may be recursively reached via bounds |
+ // checking or type arguments of its super type. |
+ type.set_arguments(full_arguments); |
+ // Finalize the current type arguments of the type, which are still the |
+ // parsed type arguments. |
+ if (!arguments.IsNull()) { |
+ for (intptr_t i = 0; i < num_type_parameters; i++) { |
+ type_arg = full_arguments.TypeAt(offset + i); |
+ ASSERT(!type_arg.IsBeingFinalized()); |
+ type_arg = FinalizeType(cls, type_arg, kFinalize, pending_types); |
+ if (type_arg.IsMalformed()) { |
+ // Malformed type arguments are mapped to dynamic. |
+ type_arg = Type::DynamicType(); |
+ } |
+ full_arguments.SetTypeAt(offset + i, type_arg); |
+ } |
+ } |
+ if (offset > 0) { |
+ TrailPtr trail = new Trail(Z, 4); |
+ Error& bound_error = Error::Handle(); |
+ FinalizeTypeArguments(type_class, full_arguments, offset, |
+ &bound_error, pending_types, trail); |
+ } |
+ if (full_arguments.IsRaw(0, num_type_arguments)) { |
+ // The parameterized_type is raw. Set its argument vector to null, which |
+ // is more efficient in type tests. |
+ full_arguments = TypeArguments::null(); |
+ } |
+ type.set_arguments(full_arguments); |
+ } else { |
+ ASSERT(full_arguments.IsNull()); // Use null vector for raw type. |
+ } |
+ } |
+ |
+ // Self referencing types may get finalized indirectly. |
+ if (!type.IsFinalized()) { |
+ ASSERT(full_arguments.IsNull() || |
+ !full_arguments.IsRaw(0, num_type_arguments)); |
+ // Mark the type as finalized. |
+ type.SetIsFinalized(); |
+ // Do not yet remove the type from the pending_types array. |
+ } |
+ return full_arguments.IsNull() ? 0 : full_arguments.Length(); |
+} |
+ |
+ |
// Finalize the type argument vector 'arguments' of the type defined by the |
// class 'cls' parameterized with the type arguments 'cls_args'. |
// The vector 'cls_args' is already initialized as a subvector at the correct |
@@ -687,8 +831,8 @@ void ClassFinalizer::FinalizeTypeArguments( |
super_type_arg = super_type_args.TypeAt(i); |
if (!super_type_arg.IsTypeRef()) { |
if (super_type_arg.IsBeingFinalized()) { |
- ASSERT(super_type_arg.IsType()); |
- CheckRecursiveType(cls, Type::Cast(super_type_arg), pending_types); |
+ ASSERT(super_type_arg.IsType() || super_type_arg.IsFunctionType()); |
+ CheckRecursiveType(cls, super_type_arg, pending_types); |
if (FLAG_trace_type_finalization) { |
THR_Print("Creating TypeRef '%s': '%s'\n", |
String::Handle(super_type_arg.Name()).ToCString(), |
@@ -737,7 +881,7 @@ void ClassFinalizer::FinalizeTypeArguments( |
if (super_type_arg.IsTypeRef()) { |
super_type_arg = TypeRef::Cast(super_type_arg).type(); |
} |
- Type::Cast(super_type_arg).set_is_being_finalized(); |
+ Type::Cast(super_type_arg).SetIsBeingFinalized(); |
pending_types->Add(super_type_arg); |
const Class& cls = Class::Handle(super_type_arg.type_class()); |
FinalizeTypeArguments( |
@@ -844,9 +988,10 @@ void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls, |
if (type_arg.IsTypeParameter()) { |
const Class& type_arg_cls = Class::Handle( |
TypeParameter::Cast(type_arg).parameterized_class()); |
- const AbstractType& bound = AbstractType::Handle( |
+ AbstractType& bound = AbstractType::Handle( |
TypeParameter::Cast(type_arg).bound()); |
- ResolveType(type_arg_cls, bound); |
+ bound = ResolveType(type_arg_cls, bound); |
+ TypeParameter::Cast(type_arg).set_bound(bound); |
} |
// This may be called only if type needs to be finalized, therefore |
// seems OK to allocate finalized types in old space. |
@@ -870,24 +1015,17 @@ void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls, |
} |
-void ClassFinalizer::CheckTypeBounds(const Class& cls, const Type& type) { |
+void ClassFinalizer::CheckTypeBounds(const Class& cls, |
+ const AbstractType& type) { |
+ ASSERT(type.IsType() || type.IsFunctionType()); |
ASSERT(type.IsFinalized()); |
TypeArguments& arguments = TypeArguments::Handle(type.arguments()); |
if (arguments.IsNull()) { |
return; |
} |
- Class& owner_class = Class::Handle(); |
- Class& type_class = Class::Handle(type.type_class()); |
- if (type_class.IsSignatureClass()) { |
- const Function& signature_fun = |
- Function::Handle(type_class.signature_function()); |
- ASSERT(!signature_fun.is_static()); |
- owner_class = signature_fun.Owner(); |
- } else { |
- owner_class = type_class.raw(); |
- } |
+ const Class& type_class = Class::Handle(type.type_class()); |
Error& bound_error = Error::Handle(); |
- CheckTypeArgumentBounds(owner_class, arguments, &bound_error); |
+ CheckTypeArgumentBounds(type_class, arguments, &bound_error); |
type.set_arguments(arguments); |
// If a bound error occurred, mark the type as malbounded. |
// The bound error will be ignored in production mode. |
@@ -936,22 +1074,23 @@ RawAbstractType* ClassFinalizer::FinalizeType( |
// encountered here. |
ASSERT(!type.IsBeingFinalized()); |
+ Zone* Z = Thread::Current()->zone(); |
+ const AbstractType& resolved_type = |
+ AbstractType::Handle(Z, ResolveType(cls, type)); |
// A malformed type gets mapped to a finalized type. |
- ResolveType(cls, type); |
- if (type.IsMalformed()) { |
- ASSERT(type.IsFinalized()); |
- return type.raw(); |
+ if (resolved_type.IsMalformed()) { |
+ ASSERT(resolved_type.IsFinalized()); |
+ return resolved_type.raw(); |
} |
- Zone* Z = Thread::Current()->zone(); |
if (FLAG_trace_type_finalization) { |
THR_Print("Finalizing type '%s' for class '%s'\n", |
- String::Handle(Z, type.Name()).ToCString(), |
+ String::Handle(Z, resolved_type.Name()).ToCString(), |
cls.ToCString()); |
} |
- if (type.IsTypeParameter()) { |
- const TypeParameter& type_parameter = TypeParameter::Cast(type); |
+ if (resolved_type.IsTypeParameter()) { |
+ const TypeParameter& type_parameter = TypeParameter::Cast(resolved_type); |
const Class& parameterized_class = |
Class::Handle(Z, type_parameter.parameterized_class()); |
ASSERT(!parameterized_class.IsNull()); |
@@ -966,7 +1105,7 @@ RawAbstractType* ClassFinalizer::FinalizeType( |
// belongs to a mixin application class. |
if (!type_parameter.IsFinalized()) { |
type_parameter.set_index(type_parameter.index() + offset); |
- type_parameter.set_is_finalized(); |
+ type_parameter.SetIsFinalized(); |
} else { |
ASSERT(cls.IsMixinApplication()); |
} |
@@ -981,8 +1120,8 @@ RawAbstractType* ClassFinalizer::FinalizeType( |
return type_parameter.raw(); |
} |
- // At this point, we can only have a parameterized_type. |
- const Type& parameterized_type = Type::Cast(type); |
+ // At this point, we can only have a Type or a FunctionType. |
+ ASSERT(resolved_type.IsType() || resolved_type.IsFunctionType()); |
// This type is the root type of the type graph if no pending types queue is |
// allocated yet. |
@@ -991,197 +1130,93 @@ RawAbstractType* ClassFinalizer::FinalizeType( |
pending_types = new PendingTypes(Z, 4); |
} |
- // The type class does not need to be finalized in order to finalize the type, |
- // however, it must at least be resolved (this was done as part of resolving |
- // the type itself, a precondition to calling FinalizeType). |
- // Also, the interfaces of the type class must be resolved and the type |
- // parameters of the type class must be finalized. |
- Class& type_class = Class::Handle(Z, parameterized_type.type_class()); |
- if (!type_class.is_type_finalized()) { |
- FinalizeTypeParameters(type_class, pending_types); |
- ResolveUpperBounds(type_class); |
- } |
- |
- // The finalized type argument vector needs num_type_arguments types. |
- const intptr_t num_type_arguments = type_class.NumTypeArguments(); |
- // The type class has num_type_parameters type parameters. |
- const intptr_t num_type_parameters = type_class.NumTypeParameters(); |
- |
- // Initialize the type argument vector. |
- // Check the number of parsed type arguments, if any. |
- // Specifying no type arguments indicates a raw type, which is not an error. |
- // However, type parameter bounds are checked below, even for a raw type. |
- TypeArguments& arguments = |
- TypeArguments::Handle(Z, parameterized_type.arguments()); |
- if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) { |
- // Wrong number of type arguments. The type is mapped to the raw type. |
- if (Isolate::Current()->flags().error_on_bad_type()) { |
- const String& type_class_name = |
- String::Handle(Z, type_class.Name()); |
- ReportError(cls, parameterized_type.token_pos(), |
- "wrong number of type arguments for class '%s'", |
- type_class_name.ToCString()); |
- } |
- // Make the type raw and continue without reporting any error. |
- // A static warning should have been reported. |
- arguments = TypeArguments::null(); |
- parameterized_type.set_arguments(arguments); |
- } |
- |
- // Mark the type as being finalized in order to detect self reference and |
- // postpone bound checking until after all types in the graph of |
- // mutually recursive types are finalized. |
- parameterized_type.set_is_being_finalized(); |
- pending_types->Add(parameterized_type); |
- |
- // The full type argument vector consists of the type arguments of the |
- // super types of type_class, which are initialized from the parsed |
- // type arguments, followed by the parsed type arguments. |
- TypeArguments& full_arguments = TypeArguments::Handle(Z); |
- Error& bound_error = Error::Handle(Z); |
- if (num_type_arguments > 0) { |
- // If no type arguments were parsed and if the super types do not prepend |
- // type arguments to the vector, we can leave the vector as null. |
- if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) { |
- full_arguments = TypeArguments::New(num_type_arguments); |
- // Copy the parsed type arguments at the correct offset in the full type |
- // argument vector. |
- const intptr_t offset = num_type_arguments - num_type_parameters; |
- AbstractType& type_arg = |
- AbstractType::Handle(Z, Type::DynamicType()); |
- // Leave the temporary type arguments at indices [0..offset[ as null. |
- for (intptr_t i = 0; i < num_type_parameters; i++) { |
- // If no type parameters were provided, a raw type is desired, so we |
- // create a vector of dynamic. |
- if (!arguments.IsNull()) { |
- type_arg = arguments.TypeAt(i); |
- // The parsed type_arg may or may not be finalized. |
- } |
- full_arguments.SetTypeAt(offset + i, type_arg); |
- } |
- // Replace the compile-time argument vector (of length zero or |
- // num_type_parameters) of this type being finalized with the still |
- // unfinalized run-time argument vector (of length num_type_arguments). |
- // This type being finalized may be recursively reached via bounds |
- // checking or type arguments of its super type. |
- parameterized_type.set_arguments(full_arguments); |
- // Finalize the current type arguments of the type, which are still the |
- // parsed type arguments. |
- if (!arguments.IsNull()) { |
- for (intptr_t i = 0; i < num_type_parameters; i++) { |
- type_arg = full_arguments.TypeAt(offset + i); |
- ASSERT(!type_arg.IsBeingFinalized()); |
- type_arg = FinalizeType(cls, type_arg, kFinalize, pending_types); |
- if (type_arg.IsMalformed()) { |
- // Malformed type arguments are mapped to dynamic. |
- type_arg = Type::DynamicType(); |
- } |
- full_arguments.SetTypeAt(offset + i, type_arg); |
- } |
- } |
- // If the type class is a signature class, the full argument vector |
- // must include the argument vector of the super type. |
- // If the signature class is a function type alias, it is also the owner |
- // of its signature function and no super type is involved. |
- // If the signature class is canonical (not an alias), the owner of its |
- // signature function may either be an alias or the enclosing class of a |
- // local function, in which case the super type of the enclosing class is |
- // also considered when filling up the argument vector. |
- Class& owner_class = Class::Handle(Z); |
- if (type_class.IsSignatureClass()) { |
- const Function& signature_fun = |
- Function::Handle(Z, type_class.signature_function()); |
- ASSERT(!signature_fun.is_static()); |
- owner_class = signature_fun.Owner(); |
- } else { |
- owner_class = type_class.raw(); |
- } |
- if (offset > 0) { |
- TrailPtr trail = new Trail(Z, 4); |
- FinalizeTypeArguments(owner_class, full_arguments, offset, |
- &bound_error, pending_types, trail); |
- } |
- if (full_arguments.IsRaw(0, num_type_arguments)) { |
- // The parameterized_type is raw. Set its argument vector to null, which |
- // is more efficient in type tests. |
- full_arguments = TypeArguments::null(); |
- } |
- parameterized_type.set_arguments(full_arguments); |
- } else { |
- ASSERT(full_arguments.IsNull()); // Use null vector for raw type. |
- } |
- } |
- |
- // Self referencing types may get finalized indirectly. |
- if (!parameterized_type.IsFinalized()) { |
- ASSERT(full_arguments.IsNull() || |
- !full_arguments.IsRaw(0, num_type_arguments)); |
- // Mark the type as finalized. |
- parameterized_type.SetIsFinalized(); |
- // Do not yet remove the type from the pending_types array. |
- } |
+ const intptr_t num_expanded_type_arguments = |
+ ExpandAndFinalizeTypeArguments(cls, resolved_type, pending_types); |
// If we are done finalizing a graph of mutually recursive types, check their |
// bounds. |
if (is_root_type) { |
for (intptr_t i = pending_types->length() - 1; i >= 0; i--) { |
- CheckTypeBounds(cls, Type::Cast(pending_types->At(i))); |
- if (FLAG_trace_type_finalization && type.IsRecursive()) { |
+ CheckTypeBounds(cls, pending_types->At(i)); |
+ if (FLAG_trace_type_finalization && resolved_type.IsRecursive()) { |
THR_Print("Done finalizing recursive type '%s': %s\n", |
- String::Handle(Z, type.Name()).ToCString(), |
- type.ToCString()); |
+ String::Handle(Z, resolved_type.Name()).ToCString(), |
+ resolved_type.ToCString()); |
} |
} |
} |
- // If the type class is a signature class, we are currently finalizing a |
- // signature type, i.e. finalizing the result type and parameter types of the |
- // signature function of this signature type. |
+ // If the type is a FunctionType, we also need to finalize the types in its |
+ // signature, i.e. finalize the result type and parameter types of the |
+ // signature function of this function type. |
// We do this after marking this type as finalized in order to allow a |
// function type to refer to itself via its parameter types and result type. |
- if (type_class.IsSignatureClass()) { |
- // The class may be created while parsing a function body, after all |
- // pending classes have already been finalized. |
- FinalizeTypesInClass(type_class); |
+ // Note that we do not instantiate these types according to the type |
+ // arguments. This will happen on demand when executing a type test. |
+ if (resolved_type.IsFunctionType()) { |
+ const Function& signature = |
+ Function::Handle(Z, FunctionType::Cast(resolved_type).signature()); |
+ FinalizeSignature(cls, signature); |
} |
if (FLAG_trace_type_finalization) { |
THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n", |
- String::Handle(Z, parameterized_type.Name()).ToCString(), |
- parameterized_type.arguments() == TypeArguments::null() ? |
- 0 : num_type_arguments, |
- parameterized_type.ToCString()); |
+ String::Handle(Z, resolved_type.Name()).ToCString(), |
+ num_expanded_type_arguments, |
+ resolved_type.ToCString()); |
} |
if (finalization >= kCanonicalize) { |
- if (FLAG_trace_type_finalization && parameterized_type.IsRecursive()) { |
- AbstractType& type = Type::Handle(Z); |
- type = parameterized_type.Canonicalize(); |
+ if (FLAG_trace_type_finalization && resolved_type.IsRecursive()) { |
+ AbstractType& recursive_type = |
+ AbstractType::Handle(Z, resolved_type.Canonicalize()); |
THR_Print("Done canonicalizing recursive type '%s': %s\n", |
- String::Handle(Z, type.Name()).ToCString(), |
- type.ToCString()); |
- return type.raw(); |
+ String::Handle(Z, recursive_type.Name()).ToCString(), |
+ recursive_type.ToCString()); |
+ return recursive_type.raw(); |
} |
- return parameterized_type.Canonicalize(); |
+ return resolved_type.Canonicalize(); |
} else { |
- return parameterized_type.raw(); |
+ return resolved_type.raw(); |
} |
} |
-void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls, |
- const Function& function) { |
+void ClassFinalizer::ResolveSignature(const Class& cls, |
+ const Function& function) { |
// Resolve result type. |
AbstractType& type = AbstractType::Handle(function.result_type()); |
// It is not a compile time error if this name does not resolve to a class or |
// interface. |
+ AbstractType& resolved_type = AbstractType::Handle(ResolveType(cls, type)); |
+ if (resolved_type.raw() != type.raw()) { |
+ function.set_result_type(resolved_type); |
+ } |
+ // Resolve formal parameter types. |
+ const intptr_t num_parameters = function.NumParameters(); |
+ for (intptr_t i = 0; i < num_parameters; i++) { |
+ type = function.ParameterTypeAt(i); |
+ resolved_type = ResolveType(cls, type); |
+ if (resolved_type.raw() != type.raw()) { |
+ function.SetParameterTypeAt(i, resolved_type); |
+ } |
+ } |
+} |
+ |
+ |
+void ClassFinalizer::FinalizeSignature(const Class& cls, |
+ const Function& function) { |
+ // Finalize result type. |
+ AbstractType& type = AbstractType::Handle(function.result_type()); |
+ // It is not a compile time error if this name does not resolve to a class or |
+ // interface. |
AbstractType& finalized_type = |
AbstractType::Handle(FinalizeType(cls, type, kCanonicalize)); |
// The result type may be malformed or malbounded. |
- if (type.raw() != finalized_type.raw()) { |
+ if (finalized_type.raw() != type.raw()) { |
function.set_result_type(finalized_type); |
} |
- // Resolve formal parameter types. |
+ // Finalize formal parameter types. |
const intptr_t num_parameters = function.NumParameters(); |
for (intptr_t i = 0; i < num_parameters; i++) { |
type = function.ParameterTypeAt(i); |
@@ -1255,7 +1290,8 @@ void ClassFinalizer::ResolveUpperBounds(const Class& cls) { |
for (intptr_t i = 0; i < num_type_params; i++) { |
type_param ^= type_params.TypeAt(i); |
bound = type_param.bound(); |
- ResolveType(cls, bound); |
+ bound = ResolveType(cls, bound); |
+ type_param.set_bound(bound); |
} |
} |
@@ -1445,7 +1481,7 @@ void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { |
Error& error = Error::Handle(Z); |
for (intptr_t i = 0; i < num_functions; i++) { |
function ^= array.At(i); |
- ResolveAndFinalizeSignature(cls, function); |
+ FinalizeSignature(cls, function); |
name = function.name(); |
// Report signature conflicts only. |
if (Isolate::Current()->flags().error_on_bad_override() && |
@@ -1718,8 +1754,8 @@ 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(instantiator, |
- &bound_error); |
+ param_bound = param_bound.InstantiateFrom( |
+ instantiator, &bound_error, NULL, Heap::kOld); |
// The instantiator contains only TypeParameter objects and no |
// BoundedType objects, so no bound error may occur. |
ASSERT(!param_bound.IsBoundedType()); |
@@ -1947,19 +1983,21 @@ void ClassFinalizer::ApplyMixinAppAlias(const Class& mixin_app_class, |
// the BoundedType in another BoundedType. |
if (type.IsBoundedType()) { |
bounded_type = BoundedType::Cast(type).type(); |
- bounded_type = bounded_type.InstantiateFrom(instantiator, |
- &bound_error); |
+ bounded_type = bounded_type.InstantiateFrom( |
+ instantiator, &bound_error, NULL, Heap::kOld); |
// 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); |
+ upper_bound = upper_bound.InstantiateFrom( |
+ instantiator, &bound_error, NULL, Heap::kOld); |
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); |
+ type = type.InstantiateFrom( |
+ instantiator, &bound_error, NULL, Heap::kOld); |
ASSERT(bound_error.IsNull()); |
} |
} |
@@ -2245,6 +2283,8 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { |
// Only resolving rather than finalizing the upper bounds here would result in |
// instantiated type parameters of the super type to temporarily have |
// unfinalized bounds. It is more efficient to finalize them early. |
+ // Finalize bounds even if running in production mode, so that a snapshot |
+ // contains them. |
FinalizeUpperBounds(cls); |
// Finalize super type. |
AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
@@ -2265,10 +2305,13 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { |
mixin_type ^= FinalizeType(cls, mixin_type, kCanonicalizeWellFormed); |
cls.set_mixin(mixin_type); |
} |
- if (cls.IsSignatureClass()) { |
+ if (cls.IsTypedefClass()) { |
+ const Function& signature = Function::Handle(cls.signature_function()); |
+ FunctionType& type = FunctionType::Handle(signature.SignatureType()); |
+ |
// Check for illegal self references. |
GrowableArray<intptr_t> visited_aliases; |
- if (!IsAliasCycleFree(cls, &visited_aliases)) { |
+ if (!IsTypedefCycleFree(cls, type, &visited_aliases)) { |
const String& name = String::Handle(cls.Name()); |
ReportError(cls, cls.token_pos(), |
"typedef '%s' illegally refers to itself", |
@@ -2276,26 +2319,22 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { |
} |
cls.set_is_type_finalized(); |
- // The type parameters of signature classes may have bounds. |
- FinalizeUpperBounds(cls); |
- |
// Resolve and finalize the result and parameter types of the signature |
- // function of this signature class. |
- const Function& sig_function = Function::Handle(cls.signature_function()); |
- ResolveAndFinalizeSignature(cls, sig_function); |
+ // function of this typedef class. |
+ FinalizeSignature(cls, signature); // Does not modify signature type. |
+ ASSERT(signature.SignatureType() == type.raw()); |
- // Resolve and finalize the signature type of this signature class. |
- const Type& sig_type = Type::Handle(cls.SignatureType()); |
- FinalizeType(cls, sig_type, kCanonicalizeWellFormed); |
+ // Resolve and finalize the signature type of this typedef. |
+ type ^= FinalizeType(cls, type, kCanonicalizeWellFormed); |
+ signature.SetSignatureType(type); |
+ |
+ // Closure instances do not refer to this typedef as their class, so there |
+ // is no need to add this typedef class to the subclasses of _Closure. |
+ ASSERT(super_type.IsNull() || super_type.IsObjectType()); |
- // Add this class to the subclasses of the superclass (_FunctionImpl). |
- if (!super_type.IsNull()) { |
- ASSERT(!super_type.IsObjectType()); |
- ASSERT(!super_class.IsNull()); |
- super_class.AddDirectSubclass(cls); |
- } |
return; |
} |
+ |
// Finalize interface types (but not necessarily interface classes). |
Array& interface_types = Array::Handle(cls.interfaces()); |
AbstractType& interface_type = AbstractType::Handle(); |
@@ -2332,9 +2371,6 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { |
// Mark as type finalized before resolving type parameter upper bounds |
// in order to break cycles. |
cls.set_is_type_finalized(); |
- // Finalize bounds even if running in production mode, so that a snapshot |
- // contains them. |
- FinalizeUpperBounds(cls); |
// Add this class to the direct subclasses of the superclass, unless the |
// superclass is Object. |
if (!super_type.IsNull() && !super_type.IsObjectType()) { |
@@ -2401,9 +2437,9 @@ void ClassFinalizer::FinalizeClass(const Class& cls) { |
cls.SetFunctions(functions); |
} |
// Every class should have at least a constructor, unless it is a top level |
- // class or a signature class. |
+ // class or a typedef class. |
ASSERT(cls.IsTopLevel() || |
- cls.IsSignatureClass() || |
+ cls.IsTypedefClass() || |
(Array::Handle(cls.functions()).Length() > 0)); |
// Resolve and finalize all member types. |
ResolveAndFinalizeMemberTypes(cls); |
@@ -2494,82 +2530,74 @@ bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { |
} |
-// Helper function called by IsAliasCycleFree. |
-bool ClassFinalizer::IsTypeCycleFree( |
- const Class& cls, |
- const AbstractType& type, |
- GrowableArray<intptr_t>* visited) { |
+// Returns false if a function type alias illegally refers to itself. |
+bool ClassFinalizer::IsTypedefCycleFree(const Class& cls, |
+ const AbstractType& type, |
+ GrowableArray<intptr_t>* visited) { |
ASSERT(visited != NULL); |
- ResolveType(cls, type); |
- if (type.IsType() && !type.IsMalformed()) { |
- const Class& type_class = Class::Handle(type.type_class()); |
- if (!type_class.is_type_finalized() && |
- type_class.IsSignatureClass() && |
- !IsAliasCycleFree(type_class, visited)) { |
- return false; |
+ AbstractType& resolved_type = AbstractType::Handle(ResolveType(cls, type)); |
+ bool checking_typedef = false; |
+ if ((resolved_type.IsType() || resolved_type.IsFunctionType()) && |
+ !resolved_type.IsMalformed()) { |
+ AbstractType& other_type = AbstractType::Handle(); |
+ if (resolved_type.IsFunctionType()) { |
+ const Class& scope_class = Class::Handle(resolved_type.type_class()); |
+ if (!scope_class.is_type_finalized() && scope_class.IsTypedefClass()) { |
+ checking_typedef = true; |
+ const intptr_t scope_class_id = scope_class.id(); |
+ ASSERT(visited != NULL); |
+ for (intptr_t i = 0; i < visited->length(); i++) { |
+ if ((*visited)[i] == scope_class_id) { |
+ // We have already visited alias 'scope_class'. We found a cycle. |
+ return false; |
+ } |
+ } |
+ visited->Add(scope_class_id); |
+ } |
+ // Check the bounds of this function type. |
+ const intptr_t num_type_params = scope_class.NumTypeParameters(); |
+ TypeParameter& type_param = TypeParameter::Handle(); |
+ const TypeArguments& type_params = |
+ TypeArguments::Handle(scope_class.type_parameters()); |
+ ASSERT((type_params.IsNull() && (num_type_params == 0)) || |
+ (type_params.Length() == num_type_params)); |
+ for (intptr_t i = 0; i < num_type_params; i++) { |
+ type_param ^= type_params.TypeAt(i); |
+ other_type = type_param.bound(); |
+ if (!IsTypedefCycleFree(cls, other_type, visited)) { |
+ return false; |
+ } |
+ } |
+ // Check the result type of the signature of this function type. |
+ const Function& function = |
+ Function::Handle(FunctionType::Cast(resolved_type).signature()); |
+ other_type = function.result_type(); |
+ if (!IsTypedefCycleFree(cls, other_type, visited)) { |
+ return false; |
+ } |
+ // Check the parameter types of the signature of this function type. |
+ const intptr_t num_parameters = function.NumParameters(); |
+ for (intptr_t i = 0; i < num_parameters; i++) { |
+ other_type = function.ParameterTypeAt(i); |
+ if (!IsTypedefCycleFree(cls, other_type, visited)) { |
+ return false; |
+ } |
+ } |
} |
- const TypeArguments& type_args = TypeArguments::Handle(type.arguments()); |
+ const TypeArguments& type_args = |
+ TypeArguments::Handle(resolved_type.arguments()); |
if (!type_args.IsNull()) { |
- AbstractType& type_arg = AbstractType::Handle(); |
for (intptr_t i = 0; i < type_args.Length(); i++) { |
- type_arg = type_args.TypeAt(i); |
- if (!IsTypeCycleFree(cls, type_arg, visited)) { |
+ other_type = type_args.TypeAt(i); |
+ if (!IsTypedefCycleFree(cls, other_type, visited)) { |
return false; |
} |
} |
} |
- } |
- return true; |
-} |
- |
- |
-// Returns false if the function type alias illegally refers to itself. |
-bool ClassFinalizer::IsAliasCycleFree(const Class& cls, |
- GrowableArray<intptr_t>* visited) { |
- ASSERT(cls.IsSignatureClass()); |
- ASSERT(!cls.is_type_finalized()); |
- ASSERT(visited != NULL); |
- const intptr_t cls_index = cls.id(); |
- for (intptr_t i = 0; i < visited->length(); i++) { |
- if ((*visited)[i] == cls_index) { |
- // We have already visited alias 'cls'. We found a cycle. |
- return false; |
- } |
- } |
- |
- // Visit the bounds, result type, and parameter types of this signature type. |
- visited->Add(cls.id()); |
- AbstractType& type = AbstractType::Handle(); |
- |
- // Check the bounds of this signature type. |
- const intptr_t num_type_params = cls.NumTypeParameters(); |
- TypeParameter& type_param = TypeParameter::Handle(); |
- const TypeArguments& type_params = |
- TypeArguments::Handle(cls.type_parameters()); |
- ASSERT((type_params.IsNull() && (num_type_params == 0)) || |
- (type_params.Length() == num_type_params)); |
- for (intptr_t i = 0; i < num_type_params; i++) { |
- type_param ^= type_params.TypeAt(i); |
- type = type_param.bound(); |
- if (!IsTypeCycleFree(cls, type, visited)) { |
- return false; |
- } |
- } |
- // Check the result type of the function of this signature type. |
- const Function& function = Function::Handle(cls.signature_function()); |
- type = function.result_type(); |
- if (!IsTypeCycleFree(cls, type, visited)) { |
- return false; |
- } |
- // Check the formal parameter types of the function of this signature type. |
- const intptr_t num_parameters = function.NumParameters(); |
- for (intptr_t i = 0; i < num_parameters; i++) { |
- type = function.ParameterTypeAt(i); |
- if (!IsTypeCycleFree(cls, type, visited)) { |
- return false; |
+ if (checking_typedef) { |
+ visited->RemoveLast(); |
} |
} |
- visited->RemoveLast(); |
return true; |
} |
@@ -2657,7 +2685,7 @@ RawType* ClassFinalizer::ResolveMixinAppType( |
GrowableObjectArray::Handle(zone, GrowableObjectArray::New()); |
AbstractType& mixin_super_type = |
AbstractType::Handle(zone, mixin_app_type.super_type()); |
- ResolveType(cls, mixin_super_type); |
+ mixin_super_type = ResolveType(cls, mixin_super_type); |
ASSERT(mixin_super_type.HasResolvedTypeClass()); // Even if malformed. |
if (mixin_super_type.IsMalformedOrMalbounded()) { |
ReportError(Error::Handle(zone, mixin_super_type.error())); |
@@ -2681,7 +2709,7 @@ RawType* ClassFinalizer::ResolveMixinAppType( |
for (intptr_t i = 0; i < depth; i++) { |
mixin_type = mixin_app_type.MixinTypeAt(i); |
ASSERT(!mixin_type.IsNull()); |
- ResolveType(cls, mixin_type); |
+ mixin_type = ResolveType(cls, mixin_type); |
ASSERT(mixin_type.HasResolvedTypeClass()); // Even if malformed. |
ASSERT(mixin_type.IsType()); |
const intptr_t num_super_type_args = type_args.Length(); |
@@ -2842,7 +2870,7 @@ void ClassFinalizer::ResolveSuperTypeAndInterfaces( |
Class& interface_class = Class::Handle(zone); |
// Resolve super type. Failures lead to a longjmp. |
- ResolveType(cls, super_type); |
+ super_type = ResolveType(cls, super_type); |
if (super_type.IsMalformedOrMalbounded()) { |
ReportError(Error::Handle(zone, super_type.error())); |
} |
@@ -2852,7 +2880,7 @@ void ClassFinalizer::ResolveSuperTypeAndInterfaces( |
String::Handle(zone, cls.Name()).ToCString()); |
} |
interface_class = super_type.type_class(); |
- if (interface_class.IsSignatureClass()) { |
+ if (interface_class.IsTypedefClass()) { |
ReportError(cls, cls.token_pos(), |
"class '%s' may not extend function type alias '%s'", |
String::Handle(zone, cls.Name()).ToCString(), |
@@ -2922,7 +2950,7 @@ void ClassFinalizer::ResolveSuperTypeAndInterfaces( |
// Resolve interfaces. Failures lead to a longjmp. |
for (intptr_t i = 0; i < super_interfaces.Length(); i++) { |
interface ^= super_interfaces.At(i); |
- ResolveType(cls, interface); |
+ interface = ResolveType(cls, interface); |
ASSERT(!interface.IsTypeParameter()); // Should be detected by parser. |
// A malbounded interface is only reported when involved in a type test. |
if (interface.IsMalformed()) { |
@@ -2933,7 +2961,7 @@ void ClassFinalizer::ResolveSuperTypeAndInterfaces( |
"'dynamic' may not be used as interface"); |
} |
interface_class = interface.type_class(); |
- if (interface_class.IsSignatureClass()) { |
+ if (interface_class.IsTypedefClass()) { |
const String& interface_name = String::Handle(zone, |
interface_class.Name()); |
ReportError(cls, cls.token_pos(), |
@@ -3069,7 +3097,7 @@ void ClassFinalizer::MarkTypeMalformed(const Error& prev_error, |
type.set_arguments(Object::null_type_arguments()); |
if (!type.IsFinalized()) { |
type.SetIsFinalized(); |
- // Do not canonicalize malformed types, since they may not be resolved. |
+ // Do not canonicalize malformed types, since they contain an error field. |
} else { |
// The only case where the malformed type was already finalized is when its |
// type arguments are not within bounds. In that case, we have a prev_error. |
@@ -3111,7 +3139,7 @@ void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, |
void ClassFinalizer::FinalizeMalboundedType(const Error& prev_error, |
const Script& script, |
- const Type& type, |
+ const AbstractType& type, |
const char* format, ...) { |
va_list args; |
va_start(args, format); |