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
Assert at end of if statement does not help mypy value inference #3431
While working on making zulip pass with mypy --strict-optional, I ran into the following piece of code. Mypy was essentially saying that message.get_realm() was not guaranteed to work ("Not all parts of the union have get_realm() method", or somesuch.)
if message is None:
message = Message.objects.select_related().get(id=message_id)
rendered_content = render_markdown(message, content, realm=message.get_realm())
Let's assume, at least for here, that the get() call will never return None. I tried the following change, but mypy was still giving the exact same error:
if message is None:
message = Message.objects.select_related().get(id=message_id)
assert message is not None # ADDED
rendered_content = render_markdown(message, content, realm=message.get_realm())
However, with this change, mypy was now happy with the code snippet:
if message is None:
message = Message.objects.select_related().get(id=message_id)
assert message is not None # ADDED, but outside the if, now.
rendered_content = render_markdown(message, content, realm=message.get_realm())
The two asserts clearly have the same code behavior of making it impossible for message to be None when we reach the rendered_content = ... line, but mypy only understands that currently (version 5.111) for the last code snippet only. Opening this bug report for discussion of that.
(Feel free to change the title of this bug report to a more meaningful / better one.)
I think this is something specific to None checks. The same snippet works perfectly with isinstance:
fromtypingimportUnionx: Union[str, int]
ifisinstance(x, int):
# do something at runtimeassertisinstance(x, str)
reveal_type(x) # Revealed type is 'builtins.str'
fromtypingimportOptionaldeff(s: Optional[str]):
ifsisNone:
s=''reveal_type(s) # Revealed type is 'builtins.str'
However, this fails:
fromtypingimportOptional, Anydeff(s: Optional[str], a: Any):
ifsisNone:
s=areveal_type(s) # Revealed type is 'Union[builtins.str, builtins.None]'
Assignment of Any doesn't narrow down the type:
fromtypingimportOptional, Anydeff(s: Optional[str], a: Any):
ifsisNone:
s=areveal_type(s) # Revealed type is 'Union[builtins.str, builtins.None]'
A potential fix would be to make an assignment of Any to a variable with an optional type strip away optionality. It would be kind of ad hoc, but I'm not sure if we want to infer Any as the variable type, since that could result in false negatives. Example of how this could work:
fromtypingimportOptional, Anydeff(s: Optional[str], a: Any):
ifsisNone:
s=areveal_type(s) # Maybe the inferred type should be just str?
A less ad hoc option would be to infer Any as the type of s after assignment, but only when the type of the variable is a union.
changed the title [-]Assert at end of if statement does not help mpyp value inference[/-][+]Assert at end of if statement does not help mypy value inference[/+]on Jul 25, 2017
No mypy's behavior is not good, but after some thinking it seems to me it is likely a duplicate of #3724 (that I just re-opened), or at least they have the same root cause.
Activity
emmatyping commentedon May 24, 2017
I discussed this with @pkch and we believe it is related to #2008.
ilevkivskyi commentedon May 24, 2017
I think this is something specific to
Nonechecks. The same snippet works perfectly withisinstance:JukkaL commentedon May 26, 2017
This works as expected:
However, this fails:
Assignment of
Anydoesn't narrow down the type:A potential fix would be to make an assignment of
Anyto a variable with an optional type strip away optionality. It would be kind of ad hoc, but I'm not sure if we want to inferAnyas the variable type, since that could result in false negatives. Example of how this could work:A less ad hoc option would be to infer
Anyas the type ofsafter assignment, but only when the type of the variable is a union.[-]Assert at end of if statement does not help mpyp value inference[/-][+]Assert at end of if statement does not help mypy value inference[/+]hauntsaninja commentedon Aug 28, 2023
I think mypy's current behaviour is good
ilevkivskyi commentedon Aug 28, 2023
No mypy's behavior is not good, but after some thinking it seems to me it is likely a duplicate of #3724 (that I just re-opened), or at least they have the same root cause.