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
Unable to remove Optional wrapper when using Mapping[str, str] instead of dict #11618
demo.py:23: error: Incompatible types in assignment (expression has type "object", variable has type "Optional[Mapping[str, str]]")
demo.py:25: error: Unsupported right operand type for in ("Optional[Mapping[str, str]]")
I tried putting reveal_type(mapping) before and after the call to assign_if_none in both functions. Here are the results:
func_1:
demo.py:13: note: Revealed type is "Union[builtins.dict[Any, Any], None]"
demo.py:15: note: Revealed type is "builtins.dict[Any, Any]"
func_2:
demo.py:25: note: Revealed type is "Union[typing.Mapping[builtins.str, builtins.str], None]"
demo.py:27: note: Revealed type is "Union[typing.Mapping[builtins.str, builtins.str], None]"
So in func_1, mypy correctly infers that the call to assign_if_none removes the Optional wrapper. But this doesn't happen in func_2.
If this isn't a bug with mypy, is there a better way to annotate the function assign_if_none so it works in func_2?
My guess would be that mypy infers {} as a dict[bottom, bottom], but dict is invariant in its key type (a common surprise for users) and so mypy joins Mapping[str, str] and dict[bottom, bottom] to object. Evidence in favour of this guess is that mapping = assign_if_none(mapping, cast(dict[str, str], {})) works as well.
Activity
erictraut commentedon Nov 25, 2021
This does look like a bug in mypy, probably in the TypeVar constraint solver logic. This type checks fine in pyright.
Interestingly, if you add a
castor an explicit type annotation for{}, the errors go away.or
JelleZijlstra commentedon Nov 26, 2021
Does
--allow-redefinitionhelp here?hauntsaninja commentedon Nov 26, 2021
My guess would be that mypy infers
{}as adict[bottom, bottom], but dict is invariant in its key type (a common surprise for users) and so mypy joinsMapping[str, str]anddict[bottom, bottom]toobject. Evidence in favour of this guess is thatmapping = assign_if_none(mapping, cast(dict[str, str], {}))works as well.hauntsaninja commentedon Nov 26, 2021
Yeah, looks like that's it. A similar thing happens with List, but not with Sequence
hauntsaninja commentedon Jun 21, 2024
This example got fixed in #16994