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
mypy doesn't type-check membership equality, for example: 'foo' in bar_list #1749
I'm not sure if this is a bug or a feature request, but given mypy will enforce types on the append operator, it feels incomplete it doesn't also support checking if an element is present in a list of a different type.
For example:
from typing import List
def is_it_in(things):
# type: (List[int]) -> bool
if "foo" in things: # this will not fail, but it should
return True
else:
return False
def add_a_thing(things):
# type: (List[int]) -> None
things.append("foo") # this will fail expectedly
t = [1, 2, 3]
add_a_thing(t)
assert is_it_in(t)
Running it gives the following on master, mypy-lang-0.4.3.dev0:
mypy --py2 test.py
test.py: note: In function "add_a_thing":
test.py:14: error: Argument 1 to "append" of "list" has incompatible type "str"; expected "int"
I know that there isn't anything wrong with going "foo" in things since the list could have anything in it, but mypy yells at append("foo"), so if adding things to a list are checked, maybe inspecting that list could be type-checked too?
It's not symmetric though. You could have a value whose type is a supertype of the list item type (or a union that includes the list item type), and while it's a definite violation to append that to the list, it's not necessarily wrong to check whether that's in the list. But if mypy believes that the membership test will always return False it would be okay to report that IMO.
Yeah, something similar was discussed a while ago. Note that there's no syntax in PEP 484 that lets us specify the desired behavior for __contains__ in a stub file. Mypy could special case a few of the more common operations like this, and this would likely give pretty good coverage.
Yep, it was discussed in #1472, though that discussion went in other directions as well.
I've had two confusing debugging experiences while working on mypy itself which would have been caught immediately by such a check, so I'm personally quite in favor of seeing something done here.
I guess what I'm saying is that I don't like the idea of requiring is_subtype(X, Y) when checking X in Container[Y]. I do agree that we could require that the intersection of X and Y is not object, but I'm not sure how to express that.
I can see how the membership check doesn't necessarily violate the List[int] annotation, since you can still ask if anything is in a list, but how strict or non strict do we want to be here? I can see the value in enforcing it on the append method but I'm struggling to come up with a use case when we wouldn't want to enforce it for checking for an element in a list. if a list sometimes could have a different type then they could just annotate it with a Union, right?
Activity
gvanrossum commentedon Jun 26, 2016
It's not symmetric though. You could have a value whose type is a supertype of the list item type (or a union that includes the list item type), and while it's a definite violation to append that to the list, it's not necessarily wrong to check whether that's in the list. But if mypy believes that the membership test will always return False it would be okay to report that IMO.
I think we may already have an issue about this?
JukkaL commentedon Jun 26, 2016
Yeah, something similar was discussed a while ago. Note that there's no syntax in PEP 484 that lets us specify the desired behavior for
__contains__in a stub file. Mypy could special case a few of the more common operations like this, and this would likely give pretty good coverage.rwbarton commentedon Jun 26, 2016
Yep, it was discussed in #1472, though that discussion went in other directions as well.
I've had two confusing debugging experiences while working on mypy itself which would have been caught immediately by such a check, so I'm personally quite in favor of seeing something done here.
gvanrossum commentedon Jun 27, 2016
I guess what I'm saying is that I don't like the idea of requiring
is_subtype(X, Y)when checkingX in Container[Y]. I do agree that we could require that the intersection of X and Y is not object, but I'm not sure how to express that.cpdean commentedon Jun 27, 2016
I can see how the membership check doesn't necessarily violate the List[int] annotation, since you can still ask if anything is in a list, but how strict or non strict do we want to be here? I can see the value in enforcing it on the append method but I'm struggling to come up with a use case when we wouldn't want to enforce it for checking for an element in a list. if a list sometimes could have a different type then they could just annotate it with a Union, right?
gvanrossum commentedon Jun 27, 2016
So if I have
y: List[int]then'' in yshould be an error.But here's a case using an overlap:
I don't think the check in foo() should trigger an error; having to make it "type-safe" by writing
doesn't help anybody.
cpdean commentedon Jun 27, 2016
That's a good point, I agree with you.
But what about the case where they're totally different types?Sorry, went right for the code example and skipped over what you had said @gvanrossum .
JukkaL commentedon Jul 15, 2016
There's a similar issue with equality. Maybe mypy should warn about
2 == 'x', for example. (This was asked by Stefan Kraus).ilevkivskyi commentedon Aug 9, 2019
We now have a flag
--strict-equalityto opt-in to strict equality and membership checks, so I think this can now be closed.