Index: runtime/vm/object.cc |
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
index 3b331d687c16f26c939f81e6a9a7e91b48f18e7a..4cb204d3e98847c69f2c437964968dc5c6a10eaa 100644 |
--- a/runtime/vm/object.cc |
+++ b/runtime/vm/object.cc |
@@ -4824,8 +4824,12 @@ bool TypeArguments::IsSubvectorInstantiated(intptr_t from_index, |
AbstractType& type = AbstractType::Handle(); |
for (intptr_t i = 0; i < len; i++) { |
type = TypeAt(from_index + i); |
- // If the type argument is null, the type parameterized with this type |
- // argument is still being finalized. Skip this null type argument. |
+ // If this type argument T is null, the type A containing T in its flattened |
+ // type argument vector V is recursive and is still being finalized. |
+ // T is the type argument of a super type of A. T is being instantiated |
+ // during finalization of V, which is also the instantiator. T depends |
+ // solely on the type parameters of A and will be replaced by a non-null |
+ // type before A is marked as finalized. |
if (!type.IsNull() && !type.IsInstantiated(genericity, trail)) { |
return false; |
} |
@@ -5085,7 +5089,6 @@ RawTypeArguments* TypeArguments::New(intptr_t len, Heap::Space space) { |
RawAbstractType* const* TypeArguments::TypeAddr(intptr_t index) const { |
- // TODO(iposva): Determine if we should throw an exception here. |
ASSERT((index >= 0) && (index < Length())); |
return &raw_ptr()->types()[index]; |
} |
@@ -5625,40 +5628,34 @@ RawType* Function::SignatureType() const { |
type = ClosureData::Cast(obj).signature_type(); |
} |
if (type.IsNull()) { |
- // A function type is parameterized in the same way as the owner class of |
- // its non-static signature function. |
- // It is not type parameterized if its signature function is static. |
- // During type finalization, the type arguments of the super class of the |
- // owner class of its signature function will be prepended to the type |
- // argument vector. Therefore, we only need to set the type arguments |
- // matching the type parameters here. |
- // In case of a function type alias, the function owner is the alias class, |
- // i.e. the typedef. The signature type is therefore parameterized according |
- // to the alias class declaration, even if the function type is not generic. |
- // Otherwise, if the function is static or if its signature type is |
- // non-generic, i.e. it does not depend on any type parameter of the owner |
- // class, then the signature type is not parameterized, although the owner |
- // class may be. In this case, the scope class of the function type is reset |
- // to _Closure class as well as the owner of the signature function. |
+ // The function type of this function is not yet cached and needs to be |
+ // constructed and cached here. |
+ // A function type is type parameterized in the same way as the owner class |
+ // of its non-static signature function. |
+ // It is not type parameterized if its signature function is static, or if |
+ // none of its result type or formal parameter types are type parameterized. |
+ // Unless the function type is a generic typedef, the type arguments of the |
+ // function type are not explicitly stored in the function type as a vector |
+ // of type arguments. |
+ // The type class of a non-typedef function type is always the non-generic |
+ // _Closure class, whether the type is generic or not. |
+ // The type class of a typedef function type is always the typedef class, |
+ // which may be generic, in which case the type stores type arguments. |
// With the introduction of generic functions, we may reach here before the |
// function type parameters have been resolved. Therefore, we cannot yet |
// check whether the function type has an instantiated signature. |
- // We will do it later when resolving the type. |
+ // We can do it only when the signature has been resolved. |
+ // We only set the type class of the function type to the typedef class |
+ // if the signature of the function type is the signature of the typedef. |
+ // Note that a function type can have a typedef class as owner without |
+ // representing the typedef, as in the following example: |
+ // typedef F(f(int x)); where the type of f is a function type with F as |
+ // owner, without representing the function type of F. |
Class& scope_class = Class::Handle(Owner()); |
- if (!scope_class.IsTypedefClass() && |
- (is_static() || !scope_class.IsGeneric())) { |
+ if (!scope_class.IsTypedefClass() || |
+ (scope_class.signature_function() != raw())) { |
scope_class = Isolate::Current()->object_store()->closure_class(); |
- if (IsSignatureFunction()) { |
- set_owner(scope_class); |
- set_token_pos(TokenPosition::kNoSource); |
- } |
} |
- // TODO(regis): With generic functions, this type is not only parameterized |
- // with the type parameters of the scope class, but also with those of all |
- // enclosing generic functions, which may not even have been parsed at this |
- // point. What actually matters is that a signature type can be expressed in |
- // a right-hand side type test by name. This is only possible with a typedef |
- // and the free variables are only the type parameters of the typedef. |
const TypeArguments& signature_type_arguments = |
TypeArguments::Handle(scope_class.type_parameters()); |
// Return the still unfinalized signature type. |
@@ -6384,8 +6381,22 @@ bool Function::HasCompatibleParametersWith(const Function& other, |
ASSERT((bound_error != NULL) && bound_error->IsNull()); |
// Check that this function's signature type is a subtype of the other |
// function's signature type. |
- if (!TypeTest(kIsSubtypeOf, Object::null_type_arguments(), other, |
- Object::null_type_arguments(), bound_error, Heap::kOld)) { |
+ // Map type parameters in the signature to dynamic before the test. |
+ Function& this_fun = Function::Handle(raw()); |
+ if (!this_fun.HasInstantiatedSignature()) { |
+ // TODO(regis): Should we pass the context explicitly here (i.e. null) once |
+ // we support generic functions? |
+ this_fun = this_fun.InstantiateSignatureFrom(Object::null_type_arguments(), |
+ Heap::kOld); |
+ } |
+ Function& other_fun = Function::Handle(other.raw()); |
+ if (!other_fun.HasInstantiatedSignature()) { |
+ // TODO(regis): Should we pass the context explicitly here (i.e. null) once |
+ // we support generic functions? |
+ other_fun = other_fun.InstantiateSignatureFrom( |
+ Object::null_type_arguments(), Heap::kOld); |
+ } |
+ if (!this_fun.TypeTest(kIsSubtypeOf, other_fun, bound_error, Heap::kOld)) { |
// For more informative error reporting, use the location of the other |
// function here, since the caller will use the location of this function. |
*bound_error = LanguageError::NewFormatted( |
@@ -6393,15 +6404,11 @@ bool Function::HasCompatibleParametersWith(const Function& other, |
Script::Handle(other.script()), other.token_pos(), Report::AtLocation, |
Report::kError, Heap::kNew, |
"signature type '%s' of function '%s' is not a subtype of signature " |
- "type '%s' of function '%s' where\n%s%s", |
+ "type '%s' of function '%s'\n", |
String::Handle(UserVisibleSignature()).ToCString(), |
String::Handle(UserVisibleName()).ToCString(), |
String::Handle(other.UserVisibleSignature()).ToCString(), |
- String::Handle(other.UserVisibleName()).ToCString(), |
- String::Handle(Type::Handle(SignatureType()).EnumerateURIs()) |
- .ToCString(), |
- String::Handle(Type::Handle(other.SignatureType()).EnumerateURIs()) |
- .ToCString()); |
+ String::Handle(other.UserVisibleName()).ToCString()); |
return false; |
} |
// We should also check that if the other function explicitly specifies a |
@@ -6414,6 +6421,41 @@ bool Function::HasCompatibleParametersWith(const Function& other, |
} |
+RawFunction* Function::InstantiateSignatureFrom( |
+ const TypeArguments& instantiator_type_arguments, |
+ Heap::Space space) const { |
+ Zone* zone = Thread::Current()->zone(); |
+ const Object& owner = Object::Handle(zone, RawOwner()); |
+ // TODO(regis): Should we change Function::New() to accept a space, since |
+ // InstantiateFrom is sometimes called with Heap::kNew? |
+ ASSERT(!HasInstantiatedSignature()); |
+ Function& sig = Function::Handle( |
+ zone, Function::NewSignatureFunction(owner, TokenPosition::kNoSource)); |
+ sig.set_type_parameters(TypeArguments::Handle(zone, type_parameters())); |
+ AbstractType& type = AbstractType::Handle(zone, result_type()); |
+ if (!type.IsInstantiated()) { |
+ type = type.InstantiateFrom(instantiator_type_arguments, NULL, NULL, NULL, |
+ space); |
+ } |
+ sig.set_result_type(type); |
+ const intptr_t num_params = NumParameters(); |
+ sig.set_num_fixed_parameters(num_fixed_parameters()); |
+ sig.SetNumOptionalParameters(NumOptionalParameters(), |
+ HasOptionalPositionalParameters()); |
+ sig.set_parameter_types(Array::Handle(Array::New(num_params, space))); |
+ for (intptr_t i = 0; i < num_params; i++) { |
+ type = ParameterTypeAt(i); |
+ if (!type.IsInstantiated()) { |
+ type = type.InstantiateFrom(instantiator_type_arguments, NULL, NULL, NULL, |
+ space); |
+ } |
+ sig.SetParameterTypeAt(i, type); |
+ } |
+ sig.set_parameter_names(Array::Handle(zone, parameter_names())); |
+ return sig.raw(); |
+} |
+ |
+ |
// If test_kind == kIsSubtypeOf, checks if the type of the specified parameter |
// of this function is a subtype or a supertype of the type of the specified |
// parameter of the other function. |
@@ -6425,33 +6467,16 @@ bool Function::HasCompatibleParametersWith(const Function& other, |
bool Function::TestParameterType(TypeTestKind test_kind, |
intptr_t parameter_position, |
intptr_t other_parameter_position, |
- const TypeArguments& type_arguments, |
const Function& other, |
- const TypeArguments& other_type_arguments, |
Error* bound_error, |
Heap::Space space) const { |
- AbstractType& other_param_type = |
+ const AbstractType& other_param_type = |
AbstractType::Handle(other.ParameterTypeAt(other_parameter_position)); |
- if (!other_param_type.IsInstantiated()) { |
- other_param_type = |
- other_param_type.InstantiateFrom(other_type_arguments, bound_error, |
- NULL, // instantiation_trail |
- NULL, // bound_trail |
- space); |
- ASSERT((bound_error == NULL) || bound_error->IsNull()); |
- } |
if (other_param_type.IsDynamicType()) { |
return true; |
} |
- AbstractType& param_type = |
+ const AbstractType& param_type = |
AbstractType::Handle(ParameterTypeAt(parameter_position)); |
- if (!param_type.IsInstantiated()) { |
- param_type = param_type.InstantiateFrom(type_arguments, bound_error, |
- NULL, // instantiation_trail |
- NULL, // bound_trail |
- space); |
- ASSERT((bound_error == NULL) || bound_error->IsNull()); |
- } |
if (param_type.IsDynamicType()) { |
return test_kind == kIsSubtypeOf; |
} |
@@ -6472,9 +6497,7 @@ bool Function::TestParameterType(TypeTestKind test_kind, |
bool Function::TypeTest(TypeTestKind test_kind, |
- const TypeArguments& type_arguments, |
const Function& other, |
- const TypeArguments& other_type_arguments, |
Error* bound_error, |
Heap::Space space) const { |
const intptr_t num_fixed_params = num_fixed_parameters(); |
@@ -6498,19 +6521,10 @@ bool Function::TypeTest(TypeTestKind test_kind, |
return false; |
} |
// Check the result type. |
- AbstractType& other_res_type = AbstractType::Handle(other.result_type()); |
- if (!other_res_type.IsInstantiated()) { |
- other_res_type = other_res_type.InstantiateFrom( |
- other_type_arguments, bound_error, NULL, NULL, space); |
- ASSERT((bound_error == NULL) || bound_error->IsNull()); |
- } |
+ const AbstractType& other_res_type = |
+ AbstractType::Handle(other.result_type()); |
if (!other_res_type.IsDynamicType() && !other_res_type.IsVoidType()) { |
- AbstractType& res_type = AbstractType::Handle(result_type()); |
- if (!res_type.IsInstantiated()) { |
- res_type = res_type.InstantiateFrom(type_arguments, bound_error, NULL, |
- NULL, space); |
- ASSERT((bound_error == NULL) || bound_error->IsNull()); |
- } |
+ const AbstractType& res_type = AbstractType::Handle(result_type()); |
if (res_type.IsVoidType()) { |
return false; |
} |
@@ -6532,8 +6546,8 @@ bool Function::TypeTest(TypeTestKind test_kind, |
other_num_opt_pos_params); |
i++) { |
if (!TestParameterType(test_kind, i + num_ignored_params, |
- i + other_num_ignored_params, type_arguments, other, |
- other_type_arguments, bound_error, space)) { |
+ i + other_num_ignored_params, other, bound_error, |
+ space)) { |
return false; |
} |
} |
@@ -6561,8 +6575,7 @@ bool Function::TypeTest(TypeTestKind test_kind, |
ASSERT(String::Handle(ParameterNameAt(j)).IsSymbol()); |
if (ParameterNameAt(j) == other_param_name.raw()) { |
found_param_name = true; |
- if (!TestParameterType(test_kind, j, i, type_arguments, other, |
- other_type_arguments, bound_error, space)) { |
+ if (!TestParameterType(test_kind, j, i, other, bound_error, space)) { |
return false; |
} |
break; |
@@ -6631,7 +6644,7 @@ RawFunction* Function::New(const String& name, |
bool is_native, |
const Object& owner, |
TokenPosition token_pos) { |
- ASSERT(!owner.IsNull()); |
+ ASSERT(!owner.IsNull() || (kind == RawFunction::kSignatureFunction)); |
const Function& result = Function::Handle(Function::New()); |
result.set_parameter_types(Object::empty_array()); |
result.set_parameter_names(Object::empty_array()); |
@@ -6695,6 +6708,7 @@ RawFunction* Function::Clone(const Class& new_owner) const { |
clone.set_optimized_instruction_count(0); |
clone.set_optimized_call_site_count(0); |
clone.set_kernel_function(kernel_function()); |
+ // TODO(regis): Clone function type parameters (their bounds may change). |
if (new_owner.NumTypeParameters() > 0) { |
// Adjust uninstantiated types to refer to type parameters of the new owner. |
AbstractType& type = AbstractType::Handle(clone.result_type()); |
@@ -6733,7 +6747,7 @@ RawFunction* Function::NewClosureFunction(const String& name, |
} |
-RawFunction* Function::NewSignatureFunction(const Class& owner, |
+RawFunction* Function::NewSignatureFunction(const Object& owner, |
TokenPosition token_pos) { |
const Function& result = Function::Handle(Function::New( |
Symbols::AnonymousSignature(), RawFunction::kSignatureFunction, |
@@ -6857,9 +6871,7 @@ RawString* Function::UserVisibleFormalParameters() const { |
// Typically 3, 5,.. elements in 'pieces', e.g.: |
// '_LoadRequest', CommaSpace, '_LoadError'. |
GrowableHandlePtrArray<const String> pieces(zone, 5); |
- const TypeArguments& instantiator = TypeArguments::Handle(zone); |
- BuildSignatureParameters(thread, zone, false, kUserVisibleName, instantiator, |
- &pieces); |
+ BuildSignatureParameters(thread, zone, kUserVisibleName, &pieces); |
return Symbols::FromConcatAll(thread, pieces); |
} |
@@ -6867,9 +6879,7 @@ RawString* Function::UserVisibleFormalParameters() const { |
void Function::BuildSignatureParameters( |
Thread* thread, |
Zone* zone, |
- bool instantiate, |
NameVisibility name_visibility, |
- const TypeArguments& instantiator, |
GrowableHandlePtrArray<const String>* pieces) const { |
AbstractType& param_type = AbstractType::Handle(zone); |
const intptr_t num_params = NumParameters(); |
@@ -6887,11 +6897,6 @@ void Function::BuildSignatureParameters( |
while (i < num_fixed_params) { |
param_type = ParameterTypeAt(i); |
ASSERT(!param_type.IsNull()); |
- if (instantiate && param_type.IsFinalized() && |
- !param_type.IsInstantiated()) { |
- param_type = param_type.InstantiateFrom(instantiator, NULL, NULL, NULL, |
- Heap::kNew); |
- } |
name = param_type.BuildName(name_visibility); |
pieces->Add(name); |
if (i != (num_params - 1)) { |
@@ -6907,11 +6912,6 @@ void Function::BuildSignatureParameters( |
} |
for (intptr_t i = num_fixed_params; i < num_params; i++) { |
param_type = ParameterTypeAt(i); |
- if (instantiate && param_type.IsFinalized() && |
- !param_type.IsInstantiated()) { |
- param_type = param_type.InstantiateFrom(instantiator, NULL, NULL, NULL, |
- Heap::kNew); |
- } |
ASSERT(!param_type.IsNull()); |
name = param_type.BuildName(name_visibility); |
pieces->Add(name); |
@@ -6951,12 +6951,10 @@ RawInstance* Function::ImplicitStaticClosure() const { |
RawInstance* Function::ImplicitInstanceClosure(const Instance& receiver) const { |
ASSERT(IsImplicitClosureFunction()); |
Zone* zone = Thread::Current()->zone(); |
- const Type& signature_type = Type::Handle(zone, SignatureType()); |
- const Class& cls = Class::Handle(zone, signature_type.type_class()); |
const Context& context = Context::Handle(zone, Context::New(1)); |
context.SetAt(0, receiver); |
TypeArguments& instantiator = TypeArguments::Handle(zone); |
- if (cls.IsGeneric()) { |
+ if (!HasInstantiatedSignature(kCurrentClass)) { |
instantiator = receiver.GetTypeArguments(); |
} |
return Closure::New(instantiator, *this, context); |
@@ -6985,70 +6983,31 @@ RawSmi* Function::GetClosureHashCode() const { |
} |
-RawString* Function::BuildSignature(bool instantiate, |
- NameVisibility name_visibility, |
- const TypeArguments& instantiator) const { |
+RawString* Function::BuildSignature(NameVisibility name_visibility) const { |
Thread* thread = Thread::Current(); |
Zone* zone = thread->zone(); |
GrowableHandlePtrArray<const String> pieces(zone, 4); |
- String& name = String::Handle(zone); |
- if (!instantiate && !is_static() && (name_visibility == kInternalName)) { |
- // Prefix the signature with its scope class and type parameters, if any |
- // (e.g. "Map<K, V>(K) => bool"). In case of a function type alias, the |
- // scope class name is the alias name. |
- // The signature of static functions cannot be type parameterized. |
- const Class& scope_class = Class::Handle(zone, Owner()); |
- ASSERT(!scope_class.IsNull()); |
- if (scope_class.IsGeneric()) { |
- const TypeArguments& type_parameters = |
- TypeArguments::Handle(zone, scope_class.type_parameters()); |
- const String& scope_class_name = String::Handle(zone, scope_class.Name()); |
- pieces.Add(scope_class_name); |
- const intptr_t num_type_parameters = type_parameters.Length(); |
- pieces.Add(Symbols::LAngleBracket()); |
- TypeParameter& type_parameter = TypeParameter::Handle(zone); |
- AbstractType& bound = AbstractType::Handle(zone); |
- for (intptr_t i = 0; i < num_type_parameters; i++) { |
- type_parameter ^= type_parameters.TypeAt(i); |
- name = type_parameter.name(); |
- pieces.Add(name); |
- bound = type_parameter.bound(); |
- if (!bound.IsNull() && !bound.IsObjectType()) { |
- pieces.Add(Symbols::SpaceExtendsSpace()); |
- name = bound.BuildName(name_visibility); |
- pieces.Add(name); |
- } |
- if (i < num_type_parameters - 1) { |
- pieces.Add(Symbols::CommaSpace()); |
- } |
- } |
- pieces.Add(Symbols::RAngleBracket()); |
- } |
- } |
pieces.Add(Symbols::LParen()); |
- BuildSignatureParameters(thread, zone, instantiate, name_visibility, |
- instantiator, &pieces); |
+ BuildSignatureParameters(thread, zone, name_visibility, &pieces); |
pieces.Add(Symbols::RParenArrow()); |
- AbstractType& res_type = AbstractType::Handle(zone, result_type()); |
- if (instantiate && res_type.IsFinalized() && !res_type.IsInstantiated()) { |
- res_type = |
- res_type.InstantiateFrom(instantiator, NULL, NULL, NULL, Heap::kNew); |
- } |
- name = res_type.BuildName(name_visibility); |
+ const AbstractType& res_type = AbstractType::Handle(zone, result_type()); |
+ const String& name = |
+ String::Handle(zone, res_type.BuildName(name_visibility)); |
pieces.Add(name); |
return Symbols::FromConcatAll(thread, pieces); |
} |
-bool Function::HasInstantiatedSignature() const { |
+bool Function::HasInstantiatedSignature(Genericity genericity, |
+ TrailPtr trail) const { |
AbstractType& type = AbstractType::Handle(result_type()); |
- if (!type.IsInstantiated()) { |
+ if (!type.IsInstantiated(genericity, trail)) { |
return false; |
} |
const intptr_t num_parameters = NumParameters(); |
for (intptr_t i = 0; i < num_parameters; i++) { |
type = ParameterTypeAt(i); |
- if (!type.IsInstantiated()) { |
+ if (!type.IsInstantiated(genericity, trail)) { |
return false; |
} |
} |
@@ -15658,22 +15617,14 @@ RawAbstractType* Instance::GetType(Heap::Space space) const { |
const Function& signature = |
Function::Handle(Closure::Cast(*this).function()); |
Type& type = Type::Handle(signature.SignatureType()); |
- if (type.type_class() == cls.raw()) { |
- // Type is not parameterized. |
- if (!type.IsCanonical()) { |
- type ^= type.Canonicalize(); |
- signature.SetSignatureType(type); |
- } |
- return type.raw(); |
- } |
- const Class& scope_cls = Class::Handle(type.type_class()); |
- ASSERT(scope_cls.NumTypeArguments() > 0); |
- TypeArguments& type_arguments = |
- TypeArguments::Handle(Closure::Cast(*this).instantiator()); |
- type = |
- Type::New(scope_cls, type_arguments, TokenPosition::kNoSource, space); |
- type.set_signature(signature); |
- type.SetIsFinalized(); |
+ if (!type.IsInstantiated()) { |
+ TypeArguments& instantiator_type_arguments = |
+ TypeArguments::Handle(Closure::Cast(*this).instantiator()); |
+ // TODO(regis): Should we pass the context explicitly here (i.e. null) |
+ // once we support generic functions? |
+ type ^= type.InstantiateFrom(instantiator_type_arguments, NULL, NULL, |
+ NULL, space); |
+ } |
type ^= type.Canonicalize(); |
return type.raw(); |
} |
@@ -15731,13 +15682,11 @@ bool Instance::IsInstanceOf(const AbstractType& other, |
other.IsDartClosureType()) { |
return true; |
} |
- Function& other_signature = Function::Handle(zone); |
- TypeArguments& other_type_arguments = TypeArguments::Handle(zone); |
+ AbstractType& instantiated_other = AbstractType::Handle(zone, other.raw()); |
// Note that we may encounter a bound error in checked mode. |
if (!other.IsInstantiated()) { |
- AbstractType& instantiated_other = AbstractType::Handle( |
- zone, other.InstantiateFrom(other_instantiator, bound_error, NULL, |
- NULL, Heap::kOld)); |
+ instantiated_other = other.InstantiateFrom( |
+ other_instantiator, bound_error, NULL, NULL, Heap::kOld); |
if ((bound_error != NULL) && !bound_error->IsNull()) { |
ASSERT(Isolate::Current()->type_checks()); |
return false; |
@@ -15750,27 +15699,24 @@ bool Instance::IsInstanceOf(const AbstractType& other, |
instantiated_other.IsDartFunctionType()) { |
return true; |
} |
- if (!instantiated_other.IsFunctionType()) { |
- return false; |
- } |
- other_signature = Type::Cast(instantiated_other).signature(); |
- other_type_arguments = instantiated_other.arguments(); |
- } else { |
- if (!other.IsFunctionType()) { |
- return false; |
- } |
- other_signature = Type::Cast(other).signature(); |
- other_type_arguments = other.arguments(); |
} |
- const Function& signature = |
- Function::Handle(zone, Closure::Cast(*this).function()); |
- const TypeArguments& type_arguments = |
- TypeArguments::Handle(zone, Closure::Cast(*this).instantiator()); |
- // TODO(regis): If signature function is generic, pass its type parameters |
- // as function instantiator, otherwise pass null. |
- // Pass the closure context as well to the the IsSubtypeOf call. |
- return signature.IsSubtypeOf(type_arguments, other_signature, |
- other_type_arguments, bound_error, Heap::kOld); |
+ if (!instantiated_other.IsFunctionType()) { |
+ return false; |
+ } |
+ Function& other_signature = |
+ Function::Handle(zone, Type::Cast(instantiated_other).signature()); |
+ Function& sig_fun = Function::Handle(zone, Closure::Cast(*this).function()); |
+ if (!sig_fun.HasInstantiatedSignature()) { |
+ const TypeArguments& instantiator_type_arguments = |
+ TypeArguments::Handle(zone, Closure::Cast(*this).instantiator()); |
+ // TODO(regis): If sig_fun is generic, pass its type parameters |
+ // as function instantiator, otherwise pass null. |
+ // Pass the closure context as well to InstantiateSignatureFrom(). |
+ // No bound error possible, since the instance exists. |
+ sig_fun = sig_fun.InstantiateSignatureFrom(instantiator_type_arguments, |
+ Heap::kOld); |
+ } |
+ return sig_fun.IsSubtypeOf(other_signature, bound_error, Heap::kOld); |
} |
TypeArguments& type_arguments = TypeArguments::Handle(zone); |
if (cls.NumTypeArguments() > 0) { |
@@ -15809,17 +15755,22 @@ bool Instance::IsInstanceOf(const AbstractType& other, |
const bool other_is_dart_function = instantiated_other.IsDartFunctionType(); |
if (other_is_dart_function || instantiated_other.IsFunctionType()) { |
// Check if this instance understands a call() method of a compatible type. |
- const Function& call_function = |
+ Function& sig_fun = |
Function::Handle(zone, cls.LookupCallFunctionForTypeTest()); |
- if (!call_function.IsNull()) { |
+ if (!sig_fun.IsNull()) { |
if (other_is_dart_function) { |
return true; |
} |
+ if (!sig_fun.HasInstantiatedSignature()) { |
+ // TODO(regis): If sig_fun is generic, pass its type parameters |
+ // as function instantiator, otherwise pass null. |
+ // Pass the closure context as well to InstantiateSignatureFrom(). |
+ // No bound error possible, since the instance exists. |
+ sig_fun = sig_fun.InstantiateSignatureFrom(type_arguments, Heap::kOld); |
+ } |
const Function& other_signature = |
Function::Handle(zone, Type::Cast(instantiated_other).signature()); |
- if (call_function.IsSubtypeOf(type_arguments, other_signature, |
- other_type_arguments, bound_error, |
- Heap::kOld)) { |
+ if (sig_fun.IsSubtypeOf(other_signature, bound_error, Heap::kOld)) { |
return true; |
} |
} |
@@ -16328,14 +16279,11 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const { |
cls = type_class(); |
const Function& signature_function = |
Function::Handle(zone, Type::Cast(*this).signature()); |
- if (!cls.IsTypedefClass() || |
- (cls.signature_function() != signature_function.raw())) { |
- if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) { |
- return signature_function.UserVisibleSignature(); |
- } |
- return signature_function.InstantiatedSignatureFrom(args, |
- name_visibility); |
+ if (!cls.IsTypedefClass()) { |
+ return signature_function.UserVisibleSignature(); |
} |
+ // Instead of printing the actual signature, use the typedef name with |
+ // its type arguments, if any. |
class_name = cls.Name(); // Typedef name. |
// We may be reporting an error about a malformed function type. In that |
// case, avoid instantiating the signature, since it may cause divergence. |
@@ -16622,9 +16570,7 @@ bool AbstractType::TypeTest(TypeTestKind test_kind, |
// Check for two function types. |
const Function& fun = |
Function::Handle(zone, Type::Cast(*this).signature()); |
- return fun.TypeTest( |
- test_kind, TypeArguments::Handle(zone, arguments()), other_fun, |
- TypeArguments::Handle(zone, other.arguments()), bound_error, space); |
+ return fun.TypeTest(test_kind, other_fun, bound_error, space); |
} |
// Check if type S has a call() method of function type T. |
const Function& call_function = |
@@ -16632,10 +16578,8 @@ bool AbstractType::TypeTest(TypeTestKind test_kind, |
if (!call_function.IsNull()) { |
if (other_is_dart_function_type || |
call_function.TypeTest( |
- test_kind, TypeArguments::Handle(zone, arguments()), |
- Function::Handle(zone, Type::Cast(other).signature()), |
- TypeArguments::Handle(zone, other.arguments()), bound_error, |
- space)) { |
+ test_kind, Function::Handle(zone, Type::Cast(other).signature()), |
+ bound_error, space)) { |
return true; |
} |
} |
@@ -16911,6 +16855,15 @@ bool Type::IsInstantiated(Genericity genericity, TrailPtr trail) const { |
(raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated)) { |
return false; |
} |
+ if (IsFunctionType()) { |
+ const Function& sig_fun = Function::Handle(signature()); |
+ if (!sig_fun.HasInstantiatedSignature(genericity, trail)) { |
+ return false; |
+ } |
+ // Because a generic typedef with an instantiated signature is considered |
+ // uninstantiated, we still need to check the type arguments, even if the |
+ // signature is instantiated. |
+ } |
if (arguments() == TypeArguments::null()) { |
return true; |
} |
@@ -16951,10 +16904,18 @@ RawAbstractType* Type::InstantiateFrom( |
// finalizing the type argument vector of a recursive type. |
const Class& cls = Class::Handle(zone, type_class()); |
TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments()); |
- ASSERT(type_arguments.Length() == cls.NumTypeArguments()); |
- type_arguments = |
- type_arguments.InstantiateFrom(instantiator_type_arguments, bound_error, |
- instantiation_trail, bound_trail, space); |
+ Function& sig_fun = Function::Handle(zone, signature()); |
+ if (!type_arguments.IsNull() && |
+ (sig_fun.IsNull() || !type_arguments.IsInstantiated())) { |
+ // This type is uninstantiated because either its type arguments or its |
+ // signature, or both are uninstantiated. |
+ // Note that the type arguments of a function type merely document the |
+ // parameterization of a generic typedef. They are otherwise ignored. |
+ ASSERT(type_arguments.Length() == cls.NumTypeArguments()); |
+ type_arguments = |
+ type_arguments.InstantiateFrom(instantiator_type_arguments, bound_error, |
+ instantiation_trail, bound_trail, space); |
+ } |
// This uninstantiated type is not modified, as it can be instantiated |
// with different instantiators. Allocate a new instantiated version of it. |
const Type& instantiated_type = |
@@ -16964,11 +16925,19 @@ RawAbstractType* Type::InstantiateFrom( |
const LanguageError& bound_error = LanguageError::Handle(zone, error()); |
instantiated_type.set_error(bound_error); |
} |
- // Preserve the signature if this type represents a function type. |
- // Note that the types in the signature remain unchanged. They get indirectly |
- // instantiated by instantiating the type arguments above. |
- const Function& sig_fun = Function::Handle(zone, signature()); |
+ // If this type is a function type, instantiate its signature. |
if (!sig_fun.IsNull()) { |
+ // If we are finalizing a typedef, do not yet instantiate its signature. |
+ // Other function types should never be instantiated while unfinalized. |
+ if (IsFinalized()) { |
+ // A generic typedef may actually declare an instantiated signature. |
+ if (!sig_fun.HasInstantiatedSignature()) { |
+ sig_fun = sig_fun.InstantiateSignatureFrom(instantiator_type_arguments, |
+ space); |
+ } |
+ } else { |
+ ASSERT(cls.IsTypedefClass()); |
+ } |
instantiated_type.set_signature(sig_fun); |
} |
if (IsFinalized()) { |
@@ -17220,29 +17189,12 @@ RawAbstractType* Type::CloneUninstantiated(const Class& new_owner, |
const LanguageError& bound_error = LanguageError::Handle(zone, error()); |
clone.set_error(bound_error); |
} |
- TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); |
- bool type_args_cloned = false; |
// Clone the signature if this type represents a function type. |
const Function& fun = Function::Handle(zone, signature()); |
if (!fun.IsNull()) { |
+ ASSERT(type_cls.IsTypedefClass() || type_cls.IsClosureClass()); |
// If the scope class is not a typedef and if it is generic, it must be the |
// mixin class, set it to the new owner. |
- if (!type_cls.IsTypedefClass() && type_cls.IsGeneric()) { |
- clone.set_type_class(new_owner); |
- AbstractType& decl_type = AbstractType::Handle(zone); |
-#ifdef DEBUG |
- decl_type = type_cls.DeclarationType(); |
- ASSERT(decl_type.IsFinalized()); |
- const TypeArguments& decl_type_args = |
- TypeArguments::Handle(zone, decl_type.arguments()); |
- ASSERT(type_args.Equals(decl_type_args)); |
-#endif // DEBUG |
- decl_type = new_owner.DeclarationType(); |
- ASSERT(decl_type.IsFinalized()); |
- type_args = decl_type.arguments(); |
- clone.set_arguments(type_args); |
- type_args_cloned = true; |
- } |
Function& fun_clone = Function::Handle( |
zone, |
Function::NewSignatureFunction(new_owner, TokenPosition::kNoSource)); |
@@ -17263,7 +17215,8 @@ RawAbstractType* Type::CloneUninstantiated(const Class& new_owner, |
fun_clone.set_parameter_names(Array::Handle(zone, fun.parameter_names())); |
clone.set_signature(fun_clone); |
} |
- if (!type_args_cloned) { |
+ TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); |
+ if (!type_args.IsNull()) { |
// Upper bounds of uninstantiated type arguments may form a cycle. |
if (type_args.IsRecursive() || !type_args.IsInstantiated()) { |
AddOnlyBuddyToTrail(&trail, clone); |
@@ -17591,10 +17544,7 @@ const char* Type::ToCString() const { |
} |
if (IsFunctionType()) { |
const Function& sig_fun = Function::Handle(zone, signature()); |
- const String& sig = |
- IsFinalized() ? String::Handle(zone, sig_fun.InstantiatedSignatureFrom( |
- type_args, kInternalName)) |
- : String::Handle(zone, sig_fun.Signature()); |
+ const String& sig = String::Handle(zone, sig_fun.Signature()); |
if (cls.IsClosureClass()) { |
ASSERT(type_args.IsNull()); |
return OS::SCreate(zone, "%sFunction Type: %s", unresolved, |
@@ -18259,10 +18209,19 @@ RawAbstractType* BoundedType::InstantiateFrom( |
// upper_bound, because one or both of them is still being finalized or |
// uninstantiated. For example, instantiated_bounded_type may be the |
// still unfinalized cloned type parameter of a mixin application class. |
+ // There is another special case where we do not want to report a bound |
+ // error yet: if the upper bound is a function type, but the bounded |
+ // type is not and its class is not compiled yet, i.e. we cannot look |
+ // for a call method yet. |
ASSERT(instantiated_bounded_type.IsBeingFinalized() || |
instantiated_upper_bound.IsBeingFinalized() || |
!instantiated_bounded_type.IsInstantiated() || |
- !instantiated_upper_bound.IsInstantiated()); |
+ !instantiated_upper_bound.IsInstantiated() || |
+ (!instantiated_bounded_type.IsFunctionType() && |
+ instantiated_upper_bound.IsFunctionType() && |
+ instantiated_bounded_type.HasResolvedTypeClass() && |
+ !Class::Handle(instantiated_bounded_type.type_class()) |
+ .is_finalized())); |
// Postpone bound check by returning a new BoundedType with unfinalized |
// or partially instantiated bounded_type and upper_bound, but keeping |
// type_param. |