summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorda-woods <dw-git@d-woods.co.uk>2022-07-12 19:00:58 +0100
committerGitHub <noreply@github.com>2022-07-12 20:00:58 +0200
commite4ef0c1e807aab8c20fb08b638550c912c166be3 (patch)
tree45710efa7f23aa646092510acc6e31be8431c99f
parent22f4444a1722fe0fd3f9157f1db35ab1c02522a9 (diff)
downloadcython-e4ef0c1e807aab8c20fb08b638550c912c166be3.tar.gz
Error on memoryview argument capture on 0.29.x (GH-4849)
I don't believe it's easy to fix https://github.com/cython/cython/issues/4798 on 0.29.x Therefore, generate an error message that explains two possible workarounds. This at least makes sure that people don't end up with mysterious crashes.
-rw-r--r--Cython/Compiler/Nodes.py15
-rw-r--r--tests/memoryview/memslice.pyx20
2 files changed, 33 insertions, 2 deletions
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py
index 339b1fa04..743d6959b 100644
--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -2637,8 +2637,11 @@ class CFuncDefNode(FuncDefNode):
def put_into_closure(entry):
if entry.in_closure and not arg.default:
code.putln('%s = %s;' % (entry.cname, entry.original_cname))
- code.put_var_incref(entry)
- code.put_var_giveref(entry)
+ if entry.type.is_memoryviewslice:
+ code.put_incref_memoryviewslice(entry.cname, have_gil=True)
+ else:
+ code.put_var_incref(entry)
+ code.put_var_giveref(entry)
for arg in self.args:
put_into_closure(scope.lookup_here(arg.name))
@@ -3234,6 +3237,14 @@ class DefNode(FuncDefNode):
# Move arguments into closure if required
def put_into_closure(entry):
if entry.in_closure:
+ if entry.type.is_memoryviewslice:
+ error(
+ self.pos,
+ "Referring to a memoryview typed argument directly in a nested closure function "
+ "is not supported in Cython 0.x. "
+ "Either upgrade to Cython 3, or assign the argument to a local variable "
+ "and use that in the nested function."
+ )
code.putln('%s = %s;' % (entry.cname, entry.original_cname))
if entry.xdecref_cleanup:
# mostly applies to the starstar arg - this can sometimes be NULL
diff --git a/tests/memoryview/memslice.pyx b/tests/memoryview/memslice.pyx
index 24af61e17..ccf760c21 100644
--- a/tests/memoryview/memslice.pyx
+++ b/tests/memoryview/memslice.pyx
@@ -2549,3 +2549,23 @@ def test_const_buffer(const int[:] a):
cdef const int[:] c = a
print(a[0])
print(c[-1])
+
+cdef arg_in_closure_cdef(int [:] a):
+ def inner():
+ return (a[0], a[1])
+ return inner
+
+def test_arg_in_closure_cdef(a):
+ """
+ >>> A = IntMockBuffer("A", range(6), shape=(6,))
+ >>> inner = test_arg_in_closure_cdef(A)
+ acquired A
+ >>> inner()
+ (0, 1)
+
+ The assignment below is just to avoid printing what was collected
+ >>> del inner; ignore_me = gc.collect()
+ released A
+ """
+ return arg_in_closure_cdef(a)
+