summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorda-woods <dw-git@d-woods.co.uk>2022-07-16 09:25:26 +0100
committerStefan Behnel <stefan_ml@behnel.de>2022-07-16 10:26:15 +0200
commit2f1c338ac4e7333823be84cc0d8df80acc5e23f3 (patch)
treebd6a11a13b4cba06133f09267a561ae0a949f65c
parente4ef0c1e807aab8c20fb08b638550c912c166be3 (diff)
downloadcython-2f1c338ac4e7333823be84cc0d8df80acc5e23f3.tar.gz
Fixed over-zealous optimization of append attribute usage to "__Pyx_PyObject_Append" (GH-4834)
Fixes https://github.com/cython/cython/issues/4828
-rw-r--r--Cython/Compiler/ExprNodes.py2
-rw-r--r--Cython/Compiler/Optimize.py2
-rw-r--r--tests/run/append.pyx34
3 files changed, 36 insertions, 2 deletions
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py
index 69632a4fe..2c5d70936 100644
--- a/Cython/Compiler/ExprNodes.py
+++ b/Cython/Compiler/ExprNodes.py
@@ -306,8 +306,8 @@ class ExprNode(Node):
# Cached result of subexpr_nodes()
# use_managed_ref boolean use ref-counted temps/assignments/etc.
# result_is_used boolean indicates that the result will be dropped and the
- # is_numpy_attribute boolean Is a Numpy module attribute
# result_code/temp_result can safely be set to None
+ # is_numpy_attribute boolean Is a Numpy module attribute
# annotation ExprNode or None PEP526 annotation for names or expressions
result_ctype = None
diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py
index 3cb77efe2..7e9435ba0 100644
--- a/Cython/Compiler/Optimize.py
+++ b/Cython/Compiler/Optimize.py
@@ -2860,7 +2860,7 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
"""Optimistic optimisation as X.append() is almost always
referring to a list.
"""
- if len(args) != 2 or node.result_is_used:
+ if len(args) != 2 or node.result_is_used or node.function.entry:
return node
return ExprNodes.PythonCapiCallNode(
diff --git a/tests/run/append.pyx b/tests/run/append.pyx
index 1976780d5..dcc3fe7c9 100644
--- a/tests/run/append.pyx
+++ b/tests/run/append.pyx
@@ -1,3 +1,5 @@
+cimport cython
+
class A:
def append(self, x):
print u"appending", x
@@ -94,3 +96,35 @@ def method_name():
'append'
"""
return [].append.__name__
+
+@cython.test_assert_path_exists(
+ '//PythonCapiCallNode')
+def append_optimized(probably_list):
+ """
+ >>> l = []
+ >>> append_optimized(l)
+ >>> l
+ [1]
+ """
+ probably_list.append(1)
+
+cdef class AppendBug:
+ # https://github.com/cython/cython/issues/4828
+ # if the attribute "append" is found it shouldn't be replaced with
+ # __Pyx_PyObject_Append
+ cdef object append
+ def __init__(self, append):
+ self.append = append
+
+@cython.test_fail_if_path_exists(
+ '//PythonCapiCallNode')
+def specific_attribute(AppendBug a):
+ """
+ >>> def append_to_default_arg(a, arg=[]):
+ ... arg.append(a)
+ ... return arg
+ >>> specific_attribute(AppendBug(append_to_default_arg))
+ >>> append_to_default_arg(None)
+ [1, None]
+ """
+ a.append(1)