-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[red-knot] Fix merged type after if-else without explicit else branch (…
…#14621) ## Summary Closes: #14593 The final type of a variable after if-statement without explicit else branch should be similar to having an explicit else branch. ## Test Plan Originally failed test cases from the bug are added. --------- Co-authored-by: Carl Meyer <carl@astral.sh> Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
- Loading branch information
1 parent
976c37a
commit 3f6c65e
Showing
2 changed files
with
82 additions
and
12 deletions.
There are no files selected for viewing
64 changes: 64 additions & 0 deletions
64
crates/red_knot_python_semantic/resources/mdtest/narrow/post_if_statement.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# Consolidating narrowed types after if statement | ||
|
||
## After if-else statements, narrowing has no effect if the variable is not mutated in any branch | ||
|
||
```py | ||
def optional_int() -> int | None: ... | ||
|
||
x = optional_int() | ||
|
||
if x is None: | ||
pass | ||
else: | ||
pass | ||
|
||
reveal_type(x) # revealed: int | None | ||
``` | ||
|
||
## Narrowing can have a persistent effect if the variable is mutated in one branch | ||
|
||
```py | ||
def optional_int() -> int | None: ... | ||
|
||
x = optional_int() | ||
|
||
if x is None: | ||
x = 10 | ||
else: | ||
pass | ||
|
||
reveal_type(x) # revealed: int | ||
``` | ||
|
||
## An if statement without an explicit `else` branch is equivalent to one with a no-op `else` branch | ||
|
||
```py | ||
def optional_int() -> int | None: ... | ||
|
||
x = optional_int() | ||
y = optional_int() | ||
|
||
if x is None: | ||
x = 0 | ||
|
||
if y is None: | ||
pass | ||
|
||
reveal_type(x) # revealed: int | ||
reveal_type(y) # revealed: int | None | ||
``` | ||
|
||
## An if-elif without an explicit else branch is equivalent to one with an empty else branch | ||
|
||
```py | ||
def optional_int() -> int | None: ... | ||
|
||
x = optional_int() | ||
|
||
if x is None: | ||
x = 0 | ||
elif x > 50: | ||
x = 50 | ||
|
||
reveal_type(x) # revealed: int | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters