diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2016-03-24 20:59:36 +0100 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2016-03-24 21:16:24 +0100 |
commit | 0aded0931318d792750a4f1f8d8dd05339722c4a (patch) | |
tree | 2fab254494eefb939b6b09a188232f09ec277959 | |
parent | 8c7da5502a94b8ed7d37a6ba8bc027167a0734de (diff) | |
download | cython-0aded0931318d792750a4f1f8d8dd05339722c4a.tar.gz |
remove dead left-over code in any()/all() optimisation that issued an "unreachable code" warning
Conflicts:
CHANGES.rst
-rw-r--r-- | CHANGES.rst | 3 | ||||
-rw-r--r-- | Cython/Compiler/Optimize.py | 25 | ||||
-rw-r--r-- | tests/run/all.pyx | 17 | ||||
-rw-r--r-- | tests/run/control_flow_loop.pyx | 55 |
4 files changed, 79 insertions, 21 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index b9529f54c..3ac3d21e6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -22,6 +22,9 @@ Bugs fixed * Fix prange() to behave identically to range(). The end condition was miscalculated when the range was not exactly divisible by the step. +* Optimised `all(genexpr)`/`any(genexpr)` calls could warn about unused code. + This fixes ticket 876. + 0.23.4 (2015-10-10) =================== diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 46291cbb4..e633559d6 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -1510,13 +1510,9 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform): for L in LL: for x in L: if not p(x): - _result = False - break - else: - continue - break + return False else: - _result = True + return True """ return self._transform_any_all(node, pos_args, False) @@ -1530,13 +1526,9 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform): for L in LL: for x in L: if p(x): - _result = True - break - else: - continue - break + return True else: - _result = False + return False """ return self._transform_any_all(node, pos_args, True) @@ -1567,15 +1559,6 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform): value=ExprNodes.BoolNode(yield_expression.pos, value=is_any, constant_result=is_any)) )] ) - loop = loop_node - while isinstance(loop.body, Nodes.LoopNode): - next_loop = loop.body - loop.body = Nodes.StatListNode(loop.body.pos, stats=[ - loop.body, - Nodes.BreakStatNode(yield_expression.pos) - ]) - next_loop.else_clause = Nodes.ContinueStatNode(yield_expression.pos) - loop = next_loop loop_node.else_clause = Nodes.ReturnStatNode( node.pos, value=ExprNodes.BoolNode(yield_expression.pos, value=not is_any, constant_result=not is_any)) diff --git a/tests/run/all.pyx b/tests/run/all.pyx index a5fcda4a9..a9c7f5002 100644 --- a/tests/run/all.pyx +++ b/tests/run/all.pyx @@ -1,3 +1,5 @@ +# mode: run +# tag: all, builtins, werror cdef class VerboseGetItem(object): cdef object sequence @@ -53,6 +55,7 @@ def all_item(x): """ return all(x) + @cython.test_assert_path_exists( "//ForInStatNode", "//InlinedGeneratorExpressionNode" @@ -86,6 +89,7 @@ def all_in_simple_gen(seq): """ return all(x for x in seq) + @cython.test_assert_path_exists( "//ForInStatNode", "//InlinedGeneratorExpressionNode" @@ -122,6 +126,7 @@ def all_in_simple_gen_scope(seq): assert x == 'abc' return result + @cython.test_assert_path_exists( "//ForInStatNode", "//InlinedGeneratorExpressionNode" @@ -158,10 +163,12 @@ def all_in_conditional_gen(seq): """ return all(x%3 for x in seq if x%2 == 1) + mixed_ustring = u'AbcDefGhIjKlmnoP' lower_ustring = mixed_ustring.lower() upper_ustring = mixed_ustring.upper() + @cython.test_assert_path_exists( '//PythonCapiCallNode', '//ForFromStatNode' @@ -181,6 +188,7 @@ def all_lower_case_characters(unicode ustring): """ return all(uchar.islower() for uchar in ustring) + @cython.test_assert_path_exists( "//ForInStatNode", "//InlinedGeneratorExpressionNode", @@ -217,6 +225,7 @@ def all_in_typed_gen(seq): cdef int x return all(x for x in seq) + @cython.test_assert_path_exists( "//ForInStatNode", "//InlinedGeneratorExpressionNode", @@ -268,6 +277,14 @@ def all_in_double_gen(seq): 1 2 False + >>> all_in_double_gen([VerboseGetItem([1,1,1]),VerboseGetItem([1,0,1]),VerboseGetItem([1,1])]) + 0 + 1 + 2 + 3 + 0 + 1 + False """ cdef int x return all(x for L in seq for x in L) diff --git a/tests/run/control_flow_loop.pyx b/tests/run/control_flow_loop.pyx new file mode 100644 index 000000000..6581f6ee3 --- /dev/null +++ b/tests/run/control_flow_loop.pyx @@ -0,0 +1,55 @@ +# mode: run +# tag: forin, control-flow, werror + +def for_in_break(LL, p=bool): + """ + >>> for_in_break([[1,2,3], [4,5,6]]) + True + >>> for_in_break([[1,2,3], [4,5,0]]) + False + >>> for_in_break([[1,2,3], [0,4,5]]) + False + >>> for_in_break([[1,2,3], [0,4,5], [6,7,8]]) + False + + >>> def collect(x): + ... v.append(x) + ... return x + + >>> v = [] + >>> for_in_break([[1,2,3], [4,5,6]], p=collect) + True + >>> v + [1, 2, 3, 4, 5, 6] + + >>> v = [] + >>> for_in_break([[1,2,3], [4,5,0]], p=collect) + False + >>> v + [1, 2, 3, 4, 5, 0] + + >>> v = [] + >>> for_in_break([[1,2,3], [0,4,5]], p=collect) + False + >>> v + [1, 2, 3, 0] + + >>> v = [] + >>> for_in_break([[1,2,3], [0,4,5], [6,7,8]], p=collect) + False + >>> v + [1, 2, 3, 0] + """ + result = 'NOK' + # implements the builtin all() + for L in LL: + for x in L: + if not p(x): + result = False + break + else: + continue + break + else: + result = True + return result |