[vala/staging] vala: Multiple lamdba arguments in method call should all use closure scope



commit 92ba4e178723b1aa6404da556c79b08abe5eaf05
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Tue Jan 15 10:44:12 2019 +0100

    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

 tests/Makefile.am                          |   1 +
 tests/delegates/lambda-shared-closure.vala | 108 +++++++++++++++++++++++++++++
 vala/valamethodcall.vala                   |  14 ++++
 3 files changed, 123 insertions(+)
---
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) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]