-
-
Notifications
You must be signed in to change notification settings - Fork 276
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
Revert "Remove useless NoReturn in NodeNG.statement's typing (#1304)" #1307
Revert "Remove useless NoReturn in NodeNG.statement's typing (#1304)" #1307
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can also add pylance to the pre-commit conf ?
Let's start with one (mypy) first. |
are you sure? mypy docs and pep 484 both seem to point that NoReturn should only be in the function signature if the function always never returns. if it's inside a union, the NoReturn is automatically unnecessary. |
Yes!
You are missing that we defined overloads for this method. The Union type you are referring to can never actually be returned. It would be just as valid to use There is one overload that will always and only ever return |
I still don't buy it.
The case of def f() -> Union[int, NoReturn]:
if random() > 0.5:
sys.exit()
return 1 Even though the function does never return in some cases, that doesn't mean this type makes any sense. Even though mypy doesn't complain about it.
It could just as well be a pyright false positive, right? |
True. My wording here wasn't entirely correct.
You are missing the overload definitions. @overload
def statement(self) -> "Module":
...
@overload
def statement(self, *, future: Literal[True]) -> NoReturn:
...
def statement(
self, *, future: Literal[None, True] = None
) -> Union["NoReturn", "Module"]:
# function body
...
A small example. from astroid import nodes
node = nodes.Module("name", "")
reveal_type(node.statement(future=True)) This is what Pylance / pyright infers. No
And for mypy.
I'm quite confident it isn't but by all means feel free to open a new issue in the |
Which is unnecessary, and mypy clearly understands that. Which is my point. |
Mypy just doesn't seem to check overwritten function signature against the parent one, as I already mentioned a false-negative. (This should probably be a feature request for mypy.) class NodeNG:
def statement(
self, *, future: Literal[None, True] = None
) -> Union["nodes.Statement", "nodes.Module", "NoReturn"]:
...
class Module(NodeNG):
def statement(
self, *, future: Literal[None, True] = None
) -> Union["NoReturn", "Module"]: # `NoReturn` is needed here
... All return types of |
$ cat mytest.py
class C:
def f(self, x: int) -> int:
return x
class D(C):
def f(self, x: int) -> str:
return 'some string'
$ mypy mytest.py
mytest.py:7: error: Return type "str" of "f" incompatible with return type "int" in supertype "C"
Found 1 error in 1 file (checked 1 source file) Mypy does check signatures against parent. It's only |
I don't know if it's of any help, but I found this comment which says the same thing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a particular opinion about the issue. I think if Guido think analyzing NoReturn is too complicated -as seen in the linked comment- this is going to move slowly in mypy and probably not have to be changed anytime soon. Also it's probably not worth arguing for a long time over, what do you think @cdce8p ?
I'm going to move this MR to 2.10.0 if the discussion is not resolved when it's the last issue to handle for astroid 2.9.1. I don't think it's worth to block the release for.
It's a really tiny thing to be honest, I'd be fine with it staying here until mypy complains about it one way or another. It doesn't really affect the types in code either way. |
The comment doesn't really change much. Adding
I would prefer (2). Especially considering that the |
Meanwhile, I've gotten in touch with mypy's team, it's getting interesting. We'll figure this case out, such that mypy will (hopefully) only allow one of these two forms in the future. No more ambiguity! |
Did you create an issue? If so, you could post the link? |
I DM'd someone :p I'll be emailing typing-sig soon, I'll drop the link then. |
Mailing list isn't as active it seems, so I posted it in typing discussions |
It seems like Eric mentioned what I already said: It can make sense when used with I would like to merge this PR now. Although I don't expect it to but should the discussion reach another conclusion someday, we can always change it later. |
Yeah, no problems. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for taking the time of asking questions on mailing lists and typing discussions @tushar-deepsource !
Eric, author of pyright, agrees that it is indeed a pyright bug: Though this PR isn't wrong, mypy wasn't giving a false negative here. Just wanted to let you know. |
I just saw in an unrelated topic that Thanks @tushar-deepsource for helping to get to the bottom of it! To finally put this to rest, would you like to do the honors and open the revert-revert PR? |
will do |
…ylint-dev#1304)" (pylint-dev#1307)" This reverts commit 7b049a1.
As mentioned in #1304 (comment), this is actually a false-negative in mypy and not an error.
Pyright / pylance correctly detects it (in
strict
mode).