| 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);
|
|
|