From: Rico Tzschichholz Date: Tue, 15 Jan 2019 09:44:12 +0000 (+0100) Subject: vala: Multiple lamdba arguments in method call should all use closure scope X-Git-Tag: 0.43.5~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=92ba4e178723b1aa6404da556c79b08abe5eaf05;p=thirdparty%2Fvala.git vala: Multiple lamdba arguments in method call should all use closure scope This does not enable proper support for delegates sharing a data argument, but allows this special case. See https://gitlab.gnome.org/GNOME/vala/issues/59 --- diff --git a/tests/Makefile.am b/tests/Makefile.am index 9ad4e4061..4bcd92671 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -238,6 +238,7 @@ TESTS = \ delegates/fields.vala \ delegates/fields-no-target.vala \ delegates/instance-method-to-no-target.test \ + delegates/lambda-shared-closure.vala \ delegates/reference_transfer.vala \ delegates/wrapper.vala \ delegates/bug519949.test \ diff --git a/tests/delegates/lambda-shared-closure.vala b/tests/delegates/lambda-shared-closure.vala new file mode 100644 index 000000000..028eca31a --- /dev/null +++ b/tests/delegates/lambda-shared-closure.vala @@ -0,0 +1,108 @@ +public delegate void FooFunc (); + +public class Foo : Object { + int global = 42; + + void call (FooFunc a, FooFunc b) { + a (); + b (); + } + + void call_owned (owned FooFunc a, owned FooFunc b) { + a (); + b (); + } + + void call_shared ([CCode (delegate_target_cname = "user_data", delegate_target_pos = 2.9)] FooFunc a, [CCode (delegate_target_cname = "user_data", delegate_target_pos = 2.9)] FooFunc b) { + a (); + b (); + } + + void call_shared_owned ([CCode (delegate_target_cname = "user_data", delegate_target_pos = 2.9)] owned FooFunc a, [CCode (delegate_target_cname = "user_data", delegate_target_pos = 2.9)] owned FooFunc b) { + a (); + b (); + } + + public void run_1 () { + int local = 23; + + assert (this.ref_count == 2); + + call ( + () => { + assert (global == 42); + assert (this.ref_count == 2); + }, + () => { + assert (local == 23); + assert (this.ref_count == 2); + } + ); + + assert (this.ref_count == 2); + } + + public void run_2 () { + int local = 23; + + assert (this.ref_count == 2); + + call_owned ( + () => { + assert (global == 42); + }, + () => { + assert (local == 23); + } + ); + + assert (this.ref_count == 2); + } + + public void run_3 () { + int local = 23; + + assert (this.ref_count == 2); + + call_shared ( + () => { + assert (global == 42); + }, + () => { + assert (local == 23); + } + ); + + assert (this.ref_count == 2); + } + + public void run_4 () { + int local = 23; + + assert (this.ref_count == 2); + + call_shared_owned ( + () => { + assert (global == 42); + }, + () => { + assert (local == 23); + } + ); + + assert (this.ref_count == 2); + } +} + +void main () { + var foo = new Foo (); + assert (foo.ref_count == 1); + foo.run_1 (); + assert (foo.ref_count == 1); + foo.run_2 (); + assert (foo.ref_count == 1); + foo.run_3 (); + assert (foo.ref_count == 1); + foo.run_4 (); + assert (foo.ref_count == 1); +} diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala index 3b5917668..e9cfc1c9d 100644 --- a/vala/valamethodcall.vala +++ b/vala/valamethodcall.vala @@ -476,8 +476,22 @@ public class Vala.MethodCall : Expression { } } + bool force_lambda_method_closure = false; foreach (Expression arg in get_argument_list ()) { arg.check (context); + + if (arg is LambdaExpression && ((LambdaExpression) arg).method.closure) { + force_lambda_method_closure = true; + } + } + // force all lambda arguments using the same closure scope + // TODO https://gitlab.gnome.org/GNOME/vala/issues/59 + if (force_lambda_method_closure) { + foreach (Expression arg in get_argument_list ()) { + if (arg is LambdaExpression) { + ((LambdaExpression) arg).method.closure = true; + } + } } if (ret_type is VoidType) {