[vala/wip/bug567269: 5/7] Allow 'static' lambdas before chainup



commit cc7bb2bcf6acba6824456533ffa5d908e8f2b5d9
Author: Simon Werbeck <simon werbeck gmail com>
Date:   Wed Nov 26 14:08:41 2014 +0100

    Allow 'static' lambdas before chainup
    
    If a lambda expression does not use its instance parameter, it is safe
    to use before a chainup expression. To make this work, usage of 'this'
    has to be tracked and the code generator needs to make use of this
    information.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=567269

 codegen/valaccodebasemodule.vala |    2 +-
 vala/valalambdaexpression.vala   |   13 ++++++++++++-
 vala/valamemberaccess.vala       |   22 ++++++++++++++++++++++
 3 files changed, 35 insertions(+), 2 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 3e4da40..23a0300 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -5550,7 +5550,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                set_delegate_target_destroy_notify (lambda, new CCodeConstant ("NULL"));
                        }
                        set_delegate_target (lambda, delegate_target);
-               } else if (get_this_type () != null) {
+               } else if (lambda.method.binding == MemberBinding.INSTANCE && get_this_type () != null) {
                        CCodeExpression delegate_target = get_result_cexpression ("self");
                        delegate_target = convert_to_generic_pointer (delegate_target, get_this_type ());
                        if (expr_owned || delegate_type.is_called_once) {
diff --git a/vala/valalambdaexpression.vala b/vala/valalambdaexpression.vala
index 6c2cf7a..c073e71 100644
--- a/vala/valalambdaexpression.vala
+++ b/vala/valalambdaexpression.vala
@@ -241,6 +241,17 @@ public class Vala.LambdaExpression : Expression {
 
                method.check (context);
 
+               if (method.this_parameter != null) {
+                       if (!method.this_parameter.used) {
+                               method.scope.remove ("this");
+                               method.this_parameter = null;
+                               method.binding = MemberBinding.STATIC;
+                       } else if (m != null && m.this_parameter != null) {
+                               // track usage inside nested lambda expressions
+                               m.this_parameter.used |= method.this_parameter.used;
+                       }
+               }
+
                value_type = new MethodType (method);
                value_type.value_owned = target_type.value_owned;
 
@@ -258,7 +269,7 @@ public class Vala.LambdaExpression : Expression {
                if (method.closure) {
                        method.get_captured_variables ((Collection<LocalVariable>) collection);
                }
-               if (in_creation_method) {
+               if (in_creation_method && method.this_parameter != null && method.this_parameter.used) {
                        Symbol sym = (Block)parent_statement.parent_node;
                        do {
                                sym = sym.parent_symbol;
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index 4a660a9..9447d1c 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -281,6 +281,7 @@ public class Vala.MemberAccess : Expression {
                                                inner.value_type = this_parameter.variable_type.copy ();
                                                inner.value_type.value_owned = false;
                                                inner.symbol_reference = this_parameter;
+                                               inner.symbol_reference.used = true;
 
                                                symbol_reference = inner.value_type.get_member (member_name);
                                        }
@@ -497,6 +498,16 @@ public class Vala.MemberAccess : Expression {
                                local.captured = true;
                                block.captured = true;
                        }
+
+                       // track usage of instance parameter for flow analysis.
+                       // When accessing generic type information, instance access
+                       // is needed to copy/destroy generic values.
+                       if (local.variable_type.type_parameter != null && 
local.variable_type.type_parameter.parent_symbol is TypeSymbol) {
+                               var m = context.analyzer.current_method_or_property_accessor as Method;
+                               if (m != null && m.binding == MemberBinding.INSTANCE) {
+                                       m.this_parameter.used = true;
+                               }
+                       }
                } else if (member is Parameter) {
                        var param = (Parameter) member;
                        var m = param.parent_symbol as Method;
@@ -537,6 +548,16 @@ public class Vala.MemberAccess : Expression {
                                        acc.body.captured = true;
                                }
                        }
+
+                       // track usage of instance parameter for flow analysis.
+                       // When accessing generic type information, instance access
+                       // is needed to copy/destroy generic values.
+                       if (param.variable_type.type_parameter != null && 
param.variable_type.type_parameter.parent_symbol is TypeSymbol) {
+                               m = context.analyzer.current_method_or_property_accessor as Method;
+                               if (m != null && m.binding == MemberBinding.INSTANCE) {
+                                       m.this_parameter.used = true;
+                               }
+                       }
                } else if (member is Field) {
                        var f = (Field) member;
                        access = f.access;
@@ -785,6 +806,7 @@ public class Vala.MemberAccess : Expression {
                                inner.value_type = this_parameter.variable_type.copy ();
                                inner.value_type.value_owned = false;
                                inner.symbol_reference = this_parameter;
+                               inner.symbol_reference.used = true;
                        } else {
                                check_lvalue_access ();
                        }


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