You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Unexpected error where Generic return type is None #4214
I introduced this problem on gitter, and am posting this as an issue after confirmation there.
The code below is a much-simplified piece of code to explore if strict-optional could be valid for some recent improved typing of request.pyi in current zulip.
(zulip/zulip@42f5eea)
The simplified code below produces the error: error: "X" does not return a value
I thought this was just with strict-optional, but the reduced code gives this issue without too, so I think I must have lost the extra code which caused that difference.
So what you're really saying here is that, while we complain about using the return value of a function explicitly declared as -> None, we should not complain if a None return type was the result of expanding a type variable that happens to be None.
I'm not sure I really like that though. Why should generics be special here? Maybe we should just stop complaining about functions with -> None too? At least in strict-optional mode -- after all we'll get other complaints if the None is unacceptable for the target.
I don't think we should remove this error completely even with --strict-optional. If a user writes something like this:
deff() ->None:
# some complex function
...
# 1000 lines laterx: Optional[str] =f()
Then it is probably a mistake. Why would one write this instead of just x: Optional[int] = None? I think a warning like f() always returns None makes sense for such cases. But I agree that we don't need this for inferred None i.e. in cases where f not always returns None.
I still fee like mypy is slightly overreaching here. The code is type-safe.
There may be reasons to write code this way (perhaps some kind of repeated
pattern where an exception would be distracting, or a plan to return
something else in the future).
There is another possibility: for situations that are not errors, but are suspicious, maybe we can have a concept of warning (as opposed to error) that will print some message, but will exit with 0? IIRC there is such level in errors.py but it is not used currently.
I've been looking at this again while continuing to work on strict-optional support in Zulip; for some reason these errors currently don't surface running with the extra parameters used in the Zulip mypy script, but do when strict-optional is enabled.
I'm open to another solution, and perhaps there is another issue masking this, but there are now multiple errors (38) arising from this issue in Zulip, where mypy sees various code like the simplified snippet:
I'm beginning to think this is important -- for now labeling it as "normal" priority (which better than no priority label for sure). I don't really like warnings (that's just an invitation to ignore them). So I think there are approaches:
Stop treating -> None special
Special-case -> None as the expansion of -> T for a type variable that's None in context
After a bit more work today, I wanted to clarify that while I do think this should be retained as an issue, with appropriate type-hinting I have managed to bypass this - assuming my approach is considered reasonable within Zulip.
Essentially, by telling X that there is another piece of type information for T in addition to None, then mypy expands the type (presumably to Optional[T]), which it then considers reasonable. This also caught some typing issues, so this issue definitely needs to be handled carefully if it is changed, as it may not have found them otherwise.
Note that #3295 gives another example where this behaviour is unwanted -- overloads. Currently, I would propose to just special case this error to only be shown if the return type is None as originally annotated. If it is a result of any kind of type inference (generic or overload variants), we suppress it.
Activity
gvanrossum commentedon Nov 7, 2017
So what you're really saying here is that, while we complain about using the return value of a function explicitly declared as
-> None, we should not complain if aNonereturn type was the result of expanding a type variable that happens to beNone.I'm not sure I really like that though. Why should generics be special here? Maybe we should just stop complaining about functions with
-> Nonetoo? At least in strict-optional mode -- after all we'll get other complaints if theNoneis unacceptable for the target.elazarg commentedon Nov 7, 2017
Dropping this check sounds good, except that
Anylvalues will lose an important error.neiljp commentedon Nov 8, 2017
The idea that generics aren't special seems more consistent. In a more general sense, my surprise perhaps come down to the asymmetry of:
gvanrossum commentedon Nov 8, 2017
I'm willing to live without the error if the target/context has type
Any.ilevkivskyi commentedon Nov 13, 2017
I don't think we should remove this error completely even with
--strict-optional. If a user writes something like this:Then it is probably a mistake. Why would one write this instead of just
x: Optional[int] = None? I think a warning likef() always returns Nonemakes sense for such cases. But I agree that we don't need this for inferredNonei.e. in cases wherefnot always returnsNone.gvanrossum commentedon Nov 13, 2017
elazarg commentedon Nov 13, 2017
We can add another flag for that, or provide a
Voidtype.ilevkivskyi commentedon Nov 13, 2017
There is another possibility: for situations that are not errors, but are suspicious, maybe we can have a concept of warning (as opposed to error) that will print some message, but will exit with 0? IIRC there is such level in
errors.pybut it is not used currently.neiljp commentedon Dec 23, 2017
I've been looking at this again while continuing to work on strict-optional support in Zulip; for some reason these errors currently don't surface running with the extra parameters used in the Zulip mypy script, but do when strict-optional is enabled.
I'm open to another solution, and perhaps there is another issue masking this, but there are now multiple errors (38) arising from this issue in Zulip, where mypy sees various code like the simplified snippet:
mypy only errors on line 7; this feels like reasonable code, if a little strange out of context.
(in Zulip, X is
REQ, and accepts various parameters)gvanrossum commentedon Dec 23, 2017
I'm beginning to think this is important -- for now labeling it as "normal" priority (which better than no priority label for sure). I don't really like warnings (that's just an invitation to ignore them). So I think there are approaches:
-> Nonespecial-> Noneas the expansion of-> Tfor a type variable that'sNonein contextI still like (2) best.
neiljp commentedon Dec 24, 2017
After a bit more work today, I wanted to clarify that while I do think this should be retained as an issue, with appropriate type-hinting I have managed to bypass this - assuming my approach is considered reasonable within Zulip.
Essentially, by telling
Xthat there is another piece of type information forTin addition toNone, then mypy expands the type (presumably toOptional[T]), which it then considers reasonable. This also caught some typing issues, so this issue definitely needs to be handled carefully if it is changed, as it may not have found them otherwise.ilevkivskyi commentedon Jun 15, 2018
Note that #3295 gives another example where this behaviour is unwanted -- overloads. Currently, I would propose to just special case this error to only be shown if the return type is
Noneas originally annotated. If it is a result of any kind of type inference (generic or overload variants), we suppress it.ilevkivskyi commentedon Sep 21, 2018
I am raising priority to high because it keeps coming and this error is quite annoying because mypy is complaining about perfectly valid code.
Allow returning inferred None from functions (#5663)
mypy: Remove various mypy.ini exclusions due to REQ/None.
mypy: Remove various mypy.ini exclusions due to REQ/None.
mypy: Remove various mypy.ini exclusions due to REQ/None.