[vala/wip/bug567269: 5/5] Allow 'static' lambdas before chainup
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/bug567269: 5/5] Allow 'static' lambdas before chainup
- Date: Mon, 19 Feb 2018 15:59:34 +0000 (UTC)
commit a305cc3e2f81f344a6a6dad2340efed4a0569b1b
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 +-
tests/Makefile.am | 1 +
tests/chainup/class-with-lambda.vala | 22 ++++++++++++++++++++++
vala/valalambdaexpression.vala | 13 ++++++++++++-
vala/valamemberaccess.vala | 24 ++++++++++++++++++++++++
5 files changed, 60 insertions(+), 2 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index d93db9c..4fd0105 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -5634,7 +5634,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/tests/Makefile.am b/tests/Makefile.am
index 718601f..ab30ae3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -62,6 +62,7 @@ TESTS = \
chainup/class-object.vala \
chainup/class-this.vala \
chainup/class-this-foo.vala \
+ chainup/class-with-lambda.vala \
chainup/method-lambda-base.vala \
chainup/no-chainup.vala \
chainup/struct-base.vala \
diff --git a/tests/chainup/class-with-lambda.vala b/tests/chainup/class-with-lambda.vala
new file mode 100644
index 0000000..6f5c1d0
--- /dev/null
+++ b/tests/chainup/class-with-lambda.vala
@@ -0,0 +1,22 @@
+public class Foo : Object {
+ public Foo.lambda_after () {
+ this ();
+ SourceFunc f = () => this != null;
+ assert (f ());
+ }
+
+ public Foo.lambda_before () {
+ SourceFunc f = () => {
+ SourceFunc g = () => true;
+ return g ();
+ };
+ this ();
+ assert (f ());
+ }
+}
+
+void main () {
+ Foo foo;
+ foo = new Foo.lambda_after ();
+ foo = new Foo.lambda_before ();
+}
diff --git a/vala/valalambdaexpression.vala b/vala/valalambdaexpression.vala
index 6d0264e..737b79d 100644
--- a/vala/valalambdaexpression.vala
+++ b/vala/valalambdaexpression.vala
@@ -239,6 +239,17 @@ public class Vala.LambdaExpression : Expression {
method.check (context);
+ if (in_creation_method && 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;
@@ -256,7 +267,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 b445ecb..4fac98a 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);
}
@@ -508,6 +509,17 @@ 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.
+ var generic_type = local.variable_type as GenericType;
+ if (generic_type != null && generic_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;
@@ -548,6 +560,17 @@ 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.
+ var generic_type = param.variable_type as GenericType;
+ if (generic_type != null && generic_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;
@@ -796,6 +819,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]