]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Make lambdas work in chain-ups again
authorSimon Werbeck <simon.werbeck@gmail.com>
Wed, 26 Nov 2014 12:00:29 +0000 (13:00 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 19 Feb 2018 16:54:28 +0000 (17:54 +0100)
Lambdas can confuse the flow analyser when chaining up. The reason is
that lambdas take their instance parameter directly from the enclosing
method without copying it.
Since flow analysis in the lambdas method body is separate from the
creation method it was defined in, 'this' is seen as uninitialized.

https://bugzilla.gnome.org/show_bug.cgi?id=567269

vala/valalambdaexpression.vala

index a3ee20a2fa14ed811225e2d2b8a72fe597ec8520..6d0264e2cb04a3f889d3c3de69da457459d61c2d 100644 (file)
@@ -48,6 +48,8 @@ public class Vala.LambdaExpression : Expression {
 
        private List<Parameter> parameters = new ArrayList<Parameter> ();
 
+       private bool in_creation_method;
+
        /**
         * Creates a new lambda expression.
         *
@@ -141,23 +143,27 @@ public class Vala.LambdaExpression : Expression {
                        method.binding = MemberBinding.STATIC;
                } else {
                        var sym = context.analyzer.current_symbol;
-                       while (method.this_parameter == null) {
+                       Parameter this_parameter = null;
+                       while (this_parameter == null) {
                                if (sym is Property) {
                                        var prop = (Property) sym;
-                                       method.this_parameter = prop.this_parameter;
+                                       this_parameter = prop.this_parameter;
                                } else if (sym is Constructor) {
                                        var c = (Constructor) sym;
-                                       method.this_parameter = c.this_parameter;
+                                       this_parameter = c.this_parameter;
                                } else if (sym is Destructor) {
                                        var d = (Destructor) sym;
-                                       method.this_parameter = d.this_parameter;
+                                       this_parameter = d.this_parameter;
                                } else if (sym is Method) {
                                        var m = (Method) sym;
-                                       method.this_parameter = m.this_parameter;
+                                       this_parameter = m.this_parameter;
+                                       in_creation_method = sym is CreationMethod;
                                }
 
                                sym = sym.parent_symbol;
                        }
+                       method.this_parameter = new Parameter ("this", this_parameter.variable_type.copy ());
+                       method.scope.add ("this", method.this_parameter);
                }
                method.owner = context.analyzer.current_symbol.scope;
 
@@ -250,5 +256,16 @@ public class Vala.LambdaExpression : Expression {
                if (method.closure) {
                        method.get_captured_variables ((Collection<LocalVariable>) collection);
                }
+               if (in_creation_method) {
+                       Symbol sym = (Block) parent_statement.parent_node;
+                       do {
+                               sym = sym.parent_symbol;
+                       } while (sym is Block);
+                       var m = (CreationMethod) sym;
+
+                       if (m.chain_up) {
+                               collection.add (m.this_parameter);
+                       }
+               }
        }
 }