mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 21:05:08 +00:00
[red-knot] Fix Leaking Narrowing Constraint in ast::ExprIf
(#14590)
## Summary Closes #14588 ```py x: Literal[42, "hello"] = 42 if bool_instance() else "hello" reveal_type(x) # revealed: Literal[42] | Literal["hello"] _ = ... if isinstance(x, str) else ... # The `isinstance` test incorrectly narrows the type of `x`. # As a result, `x` is revealed as Literal["hello"], but it should remain Literal[42, "hello"]. reveal_type(x) # revealed: Literal["hello"] ``` ## Test Plan mdtest included! --------- Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
c606bf014e
commit
f98eebdbab
2 changed files with 20 additions and 1 deletions
|
@ -22,3 +22,22 @@ reveal_type(1 if None else 2) # revealed: Literal[2]
|
||||||
reveal_type(1 if "" else 2) # revealed: Literal[2]
|
reveal_type(1 if "" else 2) # revealed: Literal[2]
|
||||||
reveal_type(1 if 0 else 2) # revealed: Literal[2]
|
reveal_type(1 if 0 else 2) # revealed: Literal[2]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Leaked Narrowing Constraint
|
||||||
|
|
||||||
|
(issue #14588)
|
||||||
|
|
||||||
|
The test inside an if expression should not affect code outside of the block.
|
||||||
|
|
||||||
|
```py
|
||||||
|
def bool_instance() -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
x: Literal[42, "hello"] = 42 if bool_instance() else "hello"
|
||||||
|
|
||||||
|
reveal_type(x) # revealed: Literal[42] | Literal["hello"]
|
||||||
|
|
||||||
|
_ = ... if isinstance(x, str) else ...
|
||||||
|
|
||||||
|
reveal_type(x) # revealed: Literal[42] | Literal["hello"]
|
||||||
|
```
|
||||||
|
|
|
@ -1189,8 +1189,8 @@ where
|
||||||
// AST inspection, so we can't simplify here, need to record test expression for
|
// AST inspection, so we can't simplify here, need to record test expression for
|
||||||
// later checking)
|
// later checking)
|
||||||
self.visit_expr(test);
|
self.visit_expr(test);
|
||||||
let constraint = self.record_expression_constraint(test);
|
|
||||||
let pre_if = self.flow_snapshot();
|
let pre_if = self.flow_snapshot();
|
||||||
|
let constraint = self.record_expression_constraint(test);
|
||||||
self.visit_expr(body);
|
self.visit_expr(body);
|
||||||
let post_body = self.flow_snapshot();
|
let post_body = self.flow_snapshot();
|
||||||
self.flow_restore(pre_if);
|
self.flow_restore(pre_if);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue