]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Multiple lamdba arguments in method call should all use closure scope 92ba4e178723b1aa6404da556c79b08abe5eaf05
authorRico Tzschichholz <ricotz@ubuntu.com>
Tue, 15 Jan 2019 09:44:12 +0000 (10:44 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Tue, 15 Jan 2019 15:49:18 +0000 (16:49 +0100)
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
tests/delegates/lambda-shared-closure.vala [new file with mode: 0644]
vala/valamethodcall.vala

index 9ad4e4061982d5614146ba9ff22fb08e38ca5b04..4bcd92671a3b015a64ab393c474d5c8635c04c50 100644 (file)
@@ -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 (file)
index 0000000..028eca3
--- /dev/null
@@ -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);
+}
index 3b5917668b9a100bd9bf89d7449fb8795f7435bc..e9cfc1c9ddaae1237ddd5e391bc009b21201ee70 100644 (file)
@@ -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) {