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
False positive when mixing Mapping and Union #6001
Mutability is not a root cause, the root cause is invariance. Mutable collections are typically invariant, but an immutable collection can be invariant as well.
Imagine, we had a UserMapping class that is a Mapping[UserString, Any] type that used UserString keys, a subclass of str with an additional method transliterate. Furthermore, assume UserMapping made use of that UserString.transliterate method in the UserMapping.__getitem__ call. (Imagine for example that the Mapping transliterates Greek to Latin characters before attempting a lookup.)
Then, if we pass an instance of this UserMapping to g, g might attempt to perform a lookup with a regular string that lacks the .transliterate method. Thus it is not type safe.
In essence, because Mapping has both methods where the keys appear as input and output, Mapping needs to be invariant in the keys.
Using a TypeVar kind of acts as an @overload for every possible str class.
Of course, in the particular case of str as a subtype of Union[str, int] it would be nice if the type-checker were a bit smarter. Because here really str is kind of stronger than just a subtype.
Activity
JelleZijlstra commentedon Dec 4, 2018
This is because Mapping is invariant in its key type. See https://mypy.readthedocs.io/en/latest/common_issues.html#invariance-vs-covariance.
wkschwartz commentedon Dec 4, 2018
I'm having a hard time understanding how this isn't a bug:
strshould satisfyUnion[str, int]:stris not a subclass ofUnion[str, int]so variance shouldn't matter.g({'b': 'c'})should be equivalent tod = {'b': 'c'}; g(d).Mappingis an immutable type.ilevkivskyi commentedon Dec 4, 2018
Mutability is not a root cause, the root cause is invariance. Mutable collections are typically invariant, but an immutable collection can be invariant as well.
JelleZijlstra commentedon Dec 4, 2018
python/typing#273 discusses why Mapping's key type is invariant.
wkschwartz commentedon Dec 4, 2018
What about items 1 and 2? How can invariance prevent
strfrom satisfyingUnion[str, int]? Why would it affect variables but not literals?JelleZijlstra commentedon Dec 4, 2018
is due to type context, where mypy infers a different type if you're accessing something in a context where a particular type is expected.
My understanding is that
stris a subtype (though not subclass) ofUnion[str, int].bluenote10 commentedon Jun 20, 2022
FYI related discussion python/typing#445 and feature request python/typing_extensions#5
randolf-scholz commentedon Nov 30, 2022
This is not type safe for the following reason:
gmay be using thearg.__getitem__function.UserMappingclass that is aMapping[UserString, Any]type that usedUserStringkeys, a subclass ofstrwith an additional methodtransliterate. Furthermore, assumeUserMappingmade use of thatUserString.transliteratemethod in theUserMapping.__getitem__call. (Imagine for example that the Mapping transliterates Greek to Latin characters before attempting a lookup.)g,gmight attempt to perform a lookup with a regular string that lacks the.transliteratemethod. Thus it is not type safe.In essence, because
Mappinghas both methods where the keys appear as input and output,Mappingneeds to be invariant in the keys.A way around this is:
Using a
TypeVarkind of acts as an@overloadfor every possiblestrclass.Of course, in the particular case of
stras a subtype ofUnion[str, int]it would be nice if the type-checker were a bit smarter. Because here reallystris kind of stronger than just a subtype.