From: Robert Bradshaw Date: Tue, 6 Oct 2009 10:12:11 +0000 (-0700) Subject: Fix two more closure bugs. X-Git-Tag: 0.13.beta0~2^2~122 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=cad41704005d33b63b10bbe34cfbb315830d82ba;p=cython.git Fix two more closure bugs. --- diff --git a/Cython/Compiler/ControlFlow.py b/Cython/Compiler/ControlFlow.py index 4ed163f9..f63d52ca 100644 --- a/Cython/Compiler/ControlFlow.py +++ b/Cython/Compiler/ControlFlow.py @@ -70,7 +70,7 @@ class ControlFlow(object): if current is None: return (None, None) state = current._get_pos_state_local(item, pos) - while state is None and current.incoming is not None: + while (state is None or state == (None, None)) and current.incoming is not None: current = current.incoming state = current._get_pos_state_local(item, pos) if state is None: diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 71bf63cc..0e16e029 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -1220,8 +1220,6 @@ class FuncDefNode(StatNode, BlockNode): if lenv.control_flow.get_state((entry.name, 'initalized')) is not True: entry.xdecref_cleanup = 1 - if self.needs_closure: - code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type) for entry in lenv.var_entries: if entry.used and not entry.in_closure: code.put_var_decref(entry) @@ -1234,6 +1232,8 @@ class FuncDefNode(StatNode, BlockNode): code.put_var_giveref(entry) elif not entry.in_closure and src != 'arg': code.put_var_decref(entry) + if self.needs_closure: + code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type) # ----- Return # This code is duplicated in ModuleNode.generate_module_init_func @@ -1861,10 +1861,11 @@ class DefNode(FuncDefNode): for arg in self.args: if not arg.name: error(arg.pos, "Missing argument name") - if arg.needs_conversion: - arg.entry = env.declare_var(arg.name, arg.type, arg.pos) + else: env.control_flow.set_state((), (arg.name, 'source'), 'arg') env.control_flow.set_state((), (arg.name, 'initalized'), True) + if arg.needs_conversion: + arg.entry = env.declare_var(arg.name, arg.type, arg.pos) if arg.type.is_pyobject: arg.entry.init = "0" arg.entry.init_to_none = 0 diff --git a/tests/run/closures_T82.pyx b/tests/run/closures_T82.pyx index 37f39532..0bbb7db1 100644 --- a/tests/run/closures_T82.pyx +++ b/tests/run/closures_T82.pyx @@ -50,6 +50,15 @@ True >>> inner_funcs[0](16), inner_funcs[1](32), inner_funcs[2](64) (19, 37, 73) +>>> switch_funcs([1,2,3], [4,5,6], 0)([10]) +[1, 2, 3, 10] +>>> switch_funcs([1,2,3], [4,5,6], 1)([10]) +[4, 5, 6, 10] +>>> switch_funcs([1,2,3], [4,5,6], 2) is None +True + +>>> call_ignore_func() + """ def add_n(int n): @@ -125,6 +134,25 @@ def cy_twofuncs(x): return x + b return f +def switch_funcs(a, b, int ix): + def f(x): + return a + x + def g(x): + return b + x + if ix == 0: + return f + elif ix == 1: + return g + else: + return None + +def ignore_func(x): + def f(): + return x + return None + +def call_ignore_func(): + ignore_func((1,2,3)) def more_inner_funcs(x): # called with x==1