-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mypy's narrowing for match statements sometimes fails when the subject of the match is a function call #12998
Comments
Potential workaround (yet this is certainly a bug): match value := fn():
... Overall, I think the problem is with def foo(f: Callable[[], Result[int, str]]) -> str:
match f(): # does not work, mypy complains
case Ok(value):
return f"{value}"
case Err(e):
raise RuntimeError(e) but this is OK: def foo(f: Callable[[], Result[int, str]]) -> str:
value = f()
match value: # does work, mypy is happy
case Ok(value):
return f"{value}"
case Err(e):
raise RuntimeError(e) |
Something similar seems to happen with tuples. Mypy doesn't like this: def foo(i: int | str, j : int | str) -> int:
match (i, j):
case int(), int(): return i + j
case int(), str(): return i + len(j)
# and so on But this is fine: def foo(i: int | str, j : int | str) -> int:
t = (i, j)
match t:
case int(), int(): return t[0] + t[1]
case int(), str(): return t[0] + len(t[1])
# and so on however, even in the latter case, you can't put an |
Fixes python#12998 mypy can't narrow match statements with functions subjects because the callexpr node is not a literal node. This adds a 'dummy' literal node that the match statement visitor can use to do the type narrowing. The python grammar describes the the match subject as a named expression so this uses that nameexpr node as it's literal.
Fixes python#12998 mypy can't narrow match statements with functions subjects because the callexpr node is not a literal node. This adds a 'dummy' literal node that the match statement visitor can use to do the type narrowing. The python grammar describes the the match subject as a named expression so this uses that nameexpr node as it's literal.
Fixes #12998 mypy can't narrow match statements with functions subjects because the callexpr node is not a literal node. This adds a 'dummy' literal node that the match statement visitor can use to do the type narrowing. The python grammar describes the the match subject as a named expression so this uses that nameexpr node as it's literal. --------- Co-authored-by: hauntsaninja <hauntsaninja@gmail.com>
Btw, I'm curious if any of the folks on this thread are encountering this in open source projects. I'd love to add more coverage for match statement to mypy_primer |
Fixes python#12998 mypy can't narrow match statements with functions subjects because the callexpr node is not a literal node. This adds a 'dummy' literal node that the match statement visitor can use to do the type narrowing. The python grammar describes the the match subject as a named expression so this uses that nameexpr node as it's literal. --------- Co-authored-by: hauntsaninja <hauntsaninja@gmail.com>
It seems this is still an issue in the presence of https://mypy-play.net/?mypy=master&python=3.12&gist=53b6a8349cf88907ed6608f7fdb05050 from typing import assert_never
from collections.abc import Awaitable
async def fn() -> int | None:
return None
async def foo() -> None:
match await fn():
case int():
pass
case None:
pass
case _ as unreachable:
assert_never(unreachable)
|
Bug Report
mypy's narrowing for
match
statements sometimes fails when the subject of the match is a function call.To Reproduce
Expected Behavior
The code above should pass a type check because case statements handle all possible return values of
fn()
.Actual Behavior
Note
Assigning the return value of
fn()
to a variable and using that variable as the subject of the match does pass type checking:Handling all cases within the one case statement also passes type checking:
mypy's output for both of the above:
Your Environment
The text was updated successfully, but these errors were encountered: