Index: runtime/vm/object.cc |
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
index f339a50fa24771b5cc7a3bda7757e2c88af0b788..c625db24d0b2f8fe929db5c81d997bf8e2bee874 100644 |
--- a/runtime/vm/object.cc |
+++ b/runtime/vm/object.cc |
@@ -6008,7 +6008,8 @@ intptr_t Function::NumImplicitParameters() const { |
} |
if ((k == RawFunction::kClosureFunction) || |
(k == RawFunction::kImplicitClosureFunction) || |
- (k == RawFunction::kSignatureFunction)) { |
+ (k == RawFunction::kSignatureFunction) || |
+ (k == RawFunction::kConvertedClosureFunction)) { |
return 1; // Closure object. |
} |
if (!is_static()) { |
@@ -6332,10 +6333,22 @@ RawFunction* Function::InstantiateSignatureFrom( |
// the original uninstantiated parent signatures. That is not a problem. |
const Function& parent = Function::Handle(zone, parent_function()); |
ASSERT(!HasInstantiatedSignature()); |
- Function& sig = Function::Handle( |
- zone, Function::NewSignatureFunction(owner, parent, |
- TokenPosition::kNoSource, space)); |
- sig.set_type_parameters(TypeArguments::Handle(zone, type_parameters())); |
+ |
+ Function& sig = Function::Handle(zone, Function::null()); |
+ if (IsConvertedClosureFunction()) { |
+ sig = Function::NewConvertedClosureFunction( |
+ String::Handle(zone, name()), parent, TokenPosition::kNoSource); |
+ // TODO(sjindel): Kernel generic methods undone. Handle type parameters |
+ // correctly when generic closures are supported. Until then, all type |
+ // parameters to this target are used for captured type variables, so they |
+ // aren't relevant to the type of the function. |
+ sig.set_type_parameters(TypeArguments::Handle(zone, TypeArguments::null())); |
+ } else { |
+ sig = Function::NewSignatureFunction(owner, parent, |
+ TokenPosition::kNoSource, space); |
+ sig.set_type_parameters(TypeArguments::Handle(zone, type_parameters())); |
+ } |
+ |
AbstractType& type = AbstractType::Handle(zone, result_type()); |
if (!type.IsInstantiated()) { |
type = |
@@ -6406,6 +6419,7 @@ bool Function::TestParameterType(TypeTestKind test_kind, |
bool Function::HasSameTypeParametersAndBounds(const Function& other) const { |
Thread* thread = Thread::Current(); |
Zone* zone = thread->zone(); |
+ |
const intptr_t num_type_params = NumTypeParameters(thread); |
if (num_type_params != other.NumTypeParameters(thread)) { |
return false; |
@@ -7174,6 +7188,34 @@ RawString* Function::BuildSignature(NameVisibility name_visibility) const { |
bool Function::HasInstantiatedSignature(Genericity genericity, |
intptr_t num_free_fun_type_params, |
TrailPtr trail) const { |
+ // This function works differently for converted closures. |
+ // |
+ // Unlike regular closures, it's not possible to know which type parameters |
+ // are supposed to come from parent functions or classes and which are |
+ // actually parameters to the closure it represents. For example, consider: |
+ // |
+ // class C<T> { |
+ // getf() => (T x) { return x; } |
+ // } |
+ // |
+ // class D { |
+ // getf() { |
+ // dynamic fn<T>(T x) { return x; } |
+ // return fn; |
+ // } |
+ // } |
+ // |
+ // The signature of `fn` as a converted closure will in both cases look like |
+ // `<T>(T) => dynamic`, because the signaute of the converted closure function |
+ // is the same as it's top-level target function. However, in the first case |
+ // the closure's type is instantiated, and in the second case it's not. |
+ // |
+ // Since we can never assume a converted closure is instantiated if it has any |
+ // type parameters, we always return true in these cases. |
+ if (IsConvertedClosureFunction()) { |
+ return genericity == kCurrentClass || NumTypeParameters() == 0; |
+ } |
+ |
if (genericity != kCurrentClass) { |
// A generic typedef may declare a non-generic function type and get |
// instantiated with unrelated function type parameters. In that case, its |
@@ -15361,46 +15403,6 @@ bool Instance::IsInstanceOf( |
Function& other_signature = |
Function::Handle(zone, Type::Cast(instantiated_other).signature()); |
Function& sig_fun = Function::Handle(zone, Closure::Cast(*this).function()); |
- if (sig_fun.IsConvertedClosureFunction()) { |
- const String& closure_name = String::Handle(zone, sig_fun.name()); |
- const Function& new_sig_fun = Function::Handle( |
- zone, |
- Function::NewConvertedClosureFunction( |
- closure_name, Function::Handle(zone, sig_fun.parent_function()), |
- TokenPosition::kNoSource)); |
- |
- new_sig_fun.set_type_parameters( |
- TypeArguments::Handle(zone, sig_fun.type_parameters())); |
- new_sig_fun.set_result_type( |
- AbstractType::Handle(zone, sig_fun.result_type())); |
- new_sig_fun.set_end_token_pos(TokenPosition::kNoSource); |
- |
- new_sig_fun.set_is_debuggable(false); |
- new_sig_fun.set_is_visible(false); |
- |
- // The converted closed top-level function type should have its first |
- // required optional parameter, i.e. context, removed. |
- const int num_fixed_params = sig_fun.num_fixed_parameters() - 1; |
- const int num_opt_params = sig_fun.NumOptionalParameters(); |
- const bool has_opt_pos_params = sig_fun.HasOptionalPositionalParameters(); |
- const int num_params = num_fixed_params + num_opt_params; |
- new_sig_fun.set_num_fixed_parameters(num_fixed_params); |
- new_sig_fun.SetNumOptionalParameters(num_opt_params, has_opt_pos_params); |
- new_sig_fun.set_parameter_types( |
- Array::Handle(zone, Array::New(num_params, Heap::kOld))); |
- new_sig_fun.set_parameter_names( |
- Array::Handle(zone, Array::New(num_params, Heap::kOld))); |
- AbstractType& param_type = AbstractType::Handle(zone); |
- String& param_name = String::Handle(zone); |
- for (int i = 0; i < num_params; i++) { |
- param_type = sig_fun.ParameterTypeAt(i + 1); |
- new_sig_fun.SetParameterTypeAt(i, param_type); |
- param_name = sig_fun.ParameterNameAt(i + 1); |
- new_sig_fun.SetParameterNameAt(i, param_name); |
- } |
- |
- sig_fun = new_sig_fun.raw(); |
- } |
if (!sig_fun.HasInstantiatedSignature()) { |
const TypeArguments& instantiator_type_arguments = TypeArguments::Handle( |
zone, Closure::Cast(*this).instantiator_type_arguments()); |