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
Incomplete or inconsistent Literal and Union behavior on conditional checks #9220
I stumbled upon some incomplete behavior related to Literal and Union. In most cases Union is not properly expanded upon conditional check when dealing with literals. Below example should describe clearly the situation.
fromtypingimportUnionfromtyping_extensionsimportLiteralclassA:
def__bool__(self) ->Literal[True]:
returnTrue@propertydefis_ok(self) ->Literal[True]:
returnTruedefok(self) ->Literal[True]:
returnTrueclassB:
def__bool__(self) ->Literal[False]:
returnFalse@propertydefis_ok(self) ->Literal[False]:
returnFalsedefok(self) ->Literal[False]:
returnFalsedefget_a_or_b() ->Union[A, B]: ...
thing=get_a_or_b()
ifthing:
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'else:
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'ifbool(thing):
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'else:
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'ifthing.is_ok:
reveal_type(thing) # Revealed type is 'main.A'else:
reveal_type(thing) # Revealed type is 'main.B'ifthing.ok():
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'else:
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'
I would expect that all examples will give the same result as the one with is_ok property. Maybe the bool() example would require some additional thought but it would seem wise to make it also work. Also, walrus operator makes it so that even the is_ok property example does not work. Other examples behave the same as before:
ifthing:=get_a_or_b():
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'else:
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'ifbool(thing:=get_a_or_b()):
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'else:
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'if (thing:=get_a_or_b()).is_ok:
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'else:
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'if (thing:=get_a_or_b()).ok():
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'else:
reveal_type(thing) # Revealed type is 'Union[main.A, main.B]'
I opened PR #9288 that at least fixes the walrus operator usage for the property case. I would be grateful for any kind of feedback :)
I will try to also work on the rest of examples but it will probably take some time since I'm not that much familiar with the code base. And the rest of cases seems like a bit of work.
The bool() case is not so obvious so this probably would need to be discussed a bit more. I will probably try to fix the other examples first and then it can be decided whether it is reasonable to handle this bool() case.
Activity
Akuli commentedon Jul 29, 2020
i discovered similar
:=operator problems in #9229JukkaL commentedon Jul 31, 2020
Yeah, the behavior seems inconsistent. I'm not sure about the
bool()case, though.kprzybyla commentedon Aug 11, 2020
I opened PR #9288 that at least fixes the walrus operator usage for the property case. I would be grateful for any kind of feedback :)
I will try to also work on the rest of examples but it will probably take some time since I'm not that much familiar with the code base. And the rest of cases seems like a bit of work.
The
bool()case is not so obvious so this probably would need to be discussed a bit more. I will probably try to fix the other examples first and then it can be decided whether it is reasonable to handle thisbool()case.Add support for using __bool__ method literal value in union narrowin…