| Index: runtime/vm/class_finalizer.cc
|
| diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
|
| index 4fc3a7718820ef44d093e6a23f6c68339ccbb767..e100cc529ac20a1f76be3db3a729e021f03438aa 100644
|
| --- a/runtime/vm/class_finalizer.cc
|
| +++ b/runtime/vm/class_finalizer.cc
|
| @@ -566,40 +566,40 @@ void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) {
|
| const Function& signature = Function::Handle(Type::Cast(type).signature());
|
| Type& signature_type = Type::Handle(signature.SignatureType());
|
| if (signature_type.raw() != type.raw()) {
|
| + // This type was promoted to a function type because its type class is a
|
| + // typedef class. The promotion is achieved by assigning the signature
|
| + // function of the typedef class to this type. This function is pointing
|
| + // to the original typedef function type, which is not this type.
|
| + // By resolving the typedef function type (which may already be resolved,
|
| + // hence saving work), we will resolve the shared signature function.
|
| + ASSERT(Class::Handle(type.type_class()).IsTypedefClass());
|
| ResolveType(cls, signature_type);
|
| } else {
|
| const Class& scope_class = Class::Handle(type.type_class());
|
| if (scope_class.IsTypedefClass()) {
|
| + // This type is the original function type of the typedef class.
|
| ResolveSignature(scope_class, signature);
|
| } else {
|
| + ASSERT(scope_class.IsClosureClass());
|
| ResolveSignature(cls, signature);
|
| - if ((type.arguments() != TypeArguments::null()) &&
|
| - signature.HasInstantiatedSignature()) {
|
| - ASSERT(scope_class.IsGeneric());
|
| - // Although the scope class of this function type is generic,
|
| - // the signature of this function type does not refer to any
|
| - // of its type parameters. Reset its scope class to _Closure.
|
| - Type::Cast(type).set_type_class(Class::Handle(
|
| - Isolate::Current()->object_store()->closure_class()));
|
| - type.set_arguments(Object::null_type_arguments());
|
| - }
|
| - }
|
| - if (signature.IsSignatureFunction()) {
|
| - // Drop fields that are not necessary anymore after resolution.
|
| - // The parent function, owner, and token position of a shared
|
| - // canonical function type are meaningless, since the canonical
|
| - // representent is picked arbitrarily.
|
| - signature.set_parent_function(Function::Handle());
|
| - // TODO(regis): As long as we support metadata in typedef signatures,
|
| - // we cannot reset these fields used to reparse a typedef.
|
| - // Note that the scope class of a typedef function type is always
|
| - // preserved as the typedef class (not reset to _Closure class), thereby
|
| - // preventing sharing of canonical function types between typedefs.
|
| - // Not being shared, these fields are therefore always meaningful for
|
| - // typedefs.
|
| - if (!scope_class.IsTypedefClass()) {
|
| - signature.set_owner(Object::Handle());
|
| - signature.set_token_pos(TokenPosition::kNoSource);
|
| + ASSERT(type.arguments() == TypeArguments::null());
|
| + if (signature.IsSignatureFunction()) {
|
| + // Drop fields that are not necessary anymore after resolution.
|
| + // The parent function, owner, and token position of a shared
|
| + // canonical function type are meaningless, since the canonical
|
| + // representent is picked arbitrarily.
|
| + signature.set_parent_function(Function::Handle());
|
| + // TODO(regis): As long as we support metadata in typedef signatures,
|
| + // we cannot reset these fields used to reparse a typedef.
|
| + // Note that the scope class of a typedef function type is always
|
| + // preserved as the typedef class (not reset to _Closure class),
|
| + // thereby preventing sharing of canonical function types between
|
| + // typedefs. Not being shared, these fields are therefore always
|
| + // meaningful for typedefs.
|
| + if (!scope_class.IsTypedefClass()) {
|
| + signature.set_owner(Object::Handle());
|
| + signature.set_token_pos(TokenPosition::kNoSource);
|
| + }
|
| }
|
| }
|
| }
|
| @@ -891,6 +891,7 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
|
| TypeArguments::Handle(super_type.arguments());
|
| // Offset of super type's type parameters in cls' type argument vector.
|
| const intptr_t super_offset = num_super_type_args - num_super_type_params;
|
| + // If the super type is raw (i.e. super_type_args is null), set to dynamic.
|
| AbstractType& super_type_arg = AbstractType::Handle(Type::DynamicType());
|
| for (intptr_t i = super_offset; i < num_uninitialized_arguments; i++) {
|
| if (!super_type_args.IsNull()) {
|
| @@ -1239,17 +1240,44 @@ RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
|
| // 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.
|
| - // Note that we do not instantiate these types according to the type
|
| - // arguments. This will happen on demand when executing a type test.
|
| + // typedef function type to refer to itself via its parameter types and
|
| + // result type.
|
| if (type.IsFunctionType()) {
|
| - const Function& signature =
|
| - Function::Handle(zone, Type::Cast(type).signature());
|
| - const Class& scope_class =
|
| - Class::Handle(zone, Type::Cast(type).type_class());
|
| + ASSERT(!type.IsBeingFinalized());
|
| + const Type& fun_type = Type::Cast(type);
|
| + const Class& scope_class = Class::Handle(zone, fun_type.type_class());
|
| if (scope_class.IsTypedefClass()) {
|
| - FinalizeSignature(scope_class, signature);
|
| + Function& signature =
|
| + Function::Handle(zone, scope_class.signature_function());
|
| + if (!scope_class.is_type_finalized()) {
|
| + FinalizeSignature(scope_class, signature);
|
| + }
|
| + // If the function type is a generic typedef, instantiate its signature
|
| + // from its type arguments.
|
| + // Example: typedef T F<T>(T x) has uninstantiated signature (T x) => T.
|
| + // The instantiated signature of F(int) becomes (int x) => int.
|
| + // Note that after this step, the signature of the function type is not
|
| + // identical to the canonical signature of the typedef class anymore.
|
| + if (scope_class.IsGeneric() && !signature.HasInstantiatedSignature()) {
|
| + const TypeArguments& type_args =
|
| + TypeArguments::Handle(zone, fun_type.arguments());
|
| + if (FLAG_trace_type_finalization) {
|
| + THR_Print("Instantiating signature '%s' of typedef '%s'\n",
|
| + String::Handle(zone, signature.Signature()).ToCString(),
|
| + String::Handle(zone, fun_type.Name()).ToCString());
|
| + }
|
| + signature = signature.InstantiateSignatureFrom(type_args, Heap::kOld);
|
| + // Note that if type_args contains type parameters, signature is still
|
| + // uninstantiated here (typedef type parameters were substituted in the
|
| + // signature with typedef type arguments).
|
| + }
|
| + fun_type.set_signature(signature);
|
| + // The type was already marked as finalized and uninstantiated in
|
| + // ExpandAndFinalizeTypeArguments above when its signature was not
|
| + // instantiated yet. Check again by calling ResetIsFinalized().
|
| + fun_type.ResetIsFinalized();
|
| } else {
|
| + const Function& signature = Function::Handle(zone, fun_type.signature());
|
| FinalizeSignature(cls, signature);
|
| }
|
| }
|
|
|