diff options
-rw-r--r-- | Cython/Compiler/ExprNodes.py | 28 | ||||
-rw-r--r-- | tests/run/if_else_expr.pyx | 46 |
2 files changed, 65 insertions, 9 deletions
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 746e1772b..305eae9eb 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -12118,30 +12118,40 @@ class CondExprNode(ExprNode): return self.analyse_result_type(env) def analyse_result_type(self, env): - self.type = PyrexTypes.independent_spanning_type( - self.true_val.type, self.false_val.type) + true_val_type = self.true_val.type + false_val_type = self.false_val.type + self.type = PyrexTypes.independent_spanning_type(true_val_type, false_val_type) + if self.type.is_reference: self.type = PyrexTypes.CFakeReferenceType(self.type.ref_base_type) if self.type.is_pyobject: self.result_ctype = py_object_type elif self.true_val.is_ephemeral() or self.false_val.is_ephemeral(): error(self.pos, "Unsafe C derivative of temporary Python reference used in conditional expression") - if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject: - self.true_val = self.true_val.coerce_to(self.type, env) - self.false_val = self.false_val.coerce_to(self.type, env) + + if true_val_type.is_pyobject or false_val_type.is_pyobject: + if true_val_type != self.type: + self.true_val = self.true_val.coerce_to(self.type, env) + if false_val_type != self.type: + self.false_val = self.false_val.coerce_to(self.type, env) + if self.type.is_error: self.type_error() return self def coerce_to_integer(self, env): - self.true_val = self.true_val.coerce_to_integer(env) - self.false_val = self.false_val.coerce_to_integer(env) + if not self.true_val.type.is_int: + self.true_val = self.true_val.coerce_to_integer(env) + if not self.false_val.type.is_int: + self.false_val = self.false_val.coerce_to_integer(env) self.result_ctype = None return self.analyse_result_type(env) def coerce_to(self, dst_type, env): - self.true_val = self.true_val.coerce_to(dst_type, env) - self.false_val = self.false_val.coerce_to(dst_type, env) + if self.true_val.type != dst_type: + self.true_val = self.true_val.coerce_to(dst_type, env) + if self.false_val.type != dst_type: + self.false_val = self.false_val.coerce_to(dst_type, env) self.result_ctype = None return self.analyse_result_type(env) diff --git a/tests/run/if_else_expr.pyx b/tests/run/if_else_expr.pyx index 41657ec5a..1d5143f22 100644 --- a/tests/run/if_else_expr.pyx +++ b/tests/run/if_else_expr.pyx @@ -1,5 +1,6 @@ # mode: run # tag: condexpr +# ticket: 5197 cimport cython @@ -67,3 +68,48 @@ def test_cfunc_ptrs(double x, bint round_down): 3.0 """ return (math.floor if round_down else math.ceil)(x) + + +def performance_gh5197(patternsList): + """ + >>> performance_gh5197([]) # do not actually run anything, just see that things work at all + """ + # Coercing the types in nested conditional expressions used to slow down exponentially. + # See https://github.com/cython/cython/issues/5197 + import re + matched=[] + for _ in range(len(patternsList)): + try: + matched.append(patternsList[_].split('|')[-1].split('/')[-1] + 'pattr1' if re.search('^SomeString.*EndIng$')\ + else patternsList[_].split('|a')[-1].split('/a')[-1] + 'pattr2' if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|a')[-1].split('/a')[-1] + 'pattr2' if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + # else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + # else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + # else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + # else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + # else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + # else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + # else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\ + else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] ) + except Exception as e: + matched.append('Error at Indx:%s-%s' %(_, patternsList[_])) |