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 20:59:36 +0100 |
commit | dca035a35678c68fd804769dc6c83effa6172de1 (patch) | |
tree | 5dfeb181875277e2e3a8245df209e4839eff7966 | |
parent | 9c7dac3bdda2fbae69a06eae5ca7791bf8144bdd (diff) | |
download | cython-dca035a35678c68fd804769dc6c83effa6172de1.tar.gz |
remove dead left-over code in any()/all() optimisation that issued an "unreachable code" warning
-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 1ef048fb3..e0bd6c25b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -59,6 +59,9 @@ Bugs fixed * Iteration over ``dict(...).items()`` failed to get optimised when dict arguments included keyword arguments. +* Optimised `all(genexpr)`/`any(genexpr)` calls could warn about unused code. + This fixes ticket 876. + 0.23.5 (2016-03-26) =================== diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index d7f3e772e..95b388097 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -1526,13 +1526,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) @@ -1546,13 +1542,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) @@ -1583,15 +1575,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 |