[vala] codegen: Fix capturing generic variables within generic methods



commit e95bf6437e7f02f7724feca040de4a11096b47c2
Author: Luca Bruno <lucabru src gnome org>
Date:   Wed Nov 2 22:14:10 2011 +0100

    codegen: Fix capturing generic variables within generic methods
    
    Fixes bug 663210.

 codegen/valaccodebasemodule.vala |   43 +++++++++++++++++++++++++++----------
 tests/Makefile.am                |    1 +
 tests/methods/bug663210.vala     |   12 ++++++++++
 3 files changed, 44 insertions(+), 12 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index d008e1f..1d20329 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -1905,21 +1905,40 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 			ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_ref_count_")));
 			ccode.open_if (ccall);
 
+			CCodeExpression outer_block = new CCodeIdentifier ("_data%d_".printf (block_id));
+			unowned Block parent_closure_block = b;
+			while (true) {
+				parent_closure_block = next_closure_block (parent_closure_block.parent_symbol);
+				if (parent_closure_block == null) {
+					break;
+				}
+				int parent_block_id = get_block_id (parent_closure_block);
+				outer_block = new CCodeMemberAccess.pointer (outer_block, "_data%d_".printf (parent_block_id));
+			}
+
 			if (get_this_type () != null) {
 				// assign "self" for type parameters
-				CCodeExpression cself = new CCodeIdentifier ("_data%d_".printf (block_id));
-				unowned Block parent_closure_block = b;
-				while (true) {
-					parent_closure_block = next_closure_block (parent_closure_block.parent_symbol);
-					if (parent_closure_block == null) {
-						break;
-					}
-					int parent_block_id = get_block_id (parent_closure_block);
-					cself = new CCodeMemberAccess.pointer (cself, "_data%d_".printf (parent_block_id));
-				}
-				cself = new CCodeMemberAccess.pointer (cself, "self");
 				ccode.add_declaration ("%s *".printf (get_ccode_name (current_type_symbol)), new CCodeVariableDeclarator ("self"));
-				ccode.add_assignment (new CCodeIdentifier ("self"), cself);
+				ccode.add_assignment (new CCodeIdentifier ("self"), new CCodeMemberAccess.pointer (outer_block, "self"));
+			}
+
+			if (current_method != null) {
+				// assign captured generic type parameters
+				foreach (var type_param in current_method.get_type_parameters ()) {
+					string func_name;
+
+					func_name = "%s_type".printf (type_param.name.down ());
+					ccode.add_declaration ("GType", new CCodeVariableDeclarator (func_name));
+					ccode.add_assignment (new CCodeIdentifier (func_name), new CCodeMemberAccess.pointer (outer_block, func_name));
+
+					func_name = "%s_dup_func".printf (type_param.name.down ());
+					ccode.add_declaration ("GBoxedCopyFunc", new CCodeVariableDeclarator (func_name));
+					ccode.add_assignment (new CCodeIdentifier (func_name), new CCodeMemberAccess.pointer (outer_block, func_name));
+
+					func_name = "%s_destroy_func".printf (type_param.name.down ());
+					ccode.add_declaration ("GDestroyNotify", new CCodeVariableDeclarator (func_name));
+					ccode.add_assignment (new CCodeIdentifier (func_name), new CCodeMemberAccess.pointer (outer_block, func_name));
+				}
 			}
 
 			// free in reverse order
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 180cacc..6619455 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -48,6 +48,7 @@ TESTS = \
 	methods/bug649562.vala \
 	methods/bug653391.vala \
 	methods/bug653908.vala \
+	methods/bug663210.vala \
 	control-flow/break.vala \
 	control-flow/expressions-conditional.vala \
 	control-flow/for.vala \
diff --git a/tests/methods/bug663210.vala b/tests/methods/bug663210.vala
new file mode 100644
index 0000000..61989d3
--- /dev/null
+++ b/tests/methods/bug663210.vala
@@ -0,0 +1,12 @@
+class Foo {
+	void foo<T> () {
+		T retval = null;
+		GLib.SourceFunc f = () => {
+			retval = null;
+			return false;
+		};
+	}
+}
+
+void main () {
+}



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