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
Type context not working for second argument of dict.get #2703
The new signature for dict.get introduced in python/typeshed@6008b9d causes wrong types to be inferred for some arguments. Here is an example that demonstrates the issue and doesn't rely on the typeshed commit:
The reason for the behavior is that mypy doesn't realize that type context should propagate from the return type to the argument somehow. Actually, it's unclear whether type context should generally work like this -- perhaps we should modify the signature of get instead.
The first example doesn't even need the 1-arg overload. The covariance of the value type also seems unrelated.
But I'm not sure I understand what you think the behavior should be. The type of default is intentionally a different type variable than D's value type. So what is the type of D() passed as the default? Why should it conform to the value type?
I tried to rewrite the example using a separate assignment:
d=D()
a=y.get(x, d)
but this says Need type annotation for variable on the d = D() line. But somehow when I change to
d=D() # type: Da=y.get(x, d)
all is well. So it looks like there's something half-hearted being done to the D() call in your original version, where it is not quite given the type D[Any, Any]?
If you think there's simply a bug I'm happy to sit back and look at your fix to see if I can understand the issue that way. :-) (But your last sentence made it sound like you're not sure yourself?)
The explicit annotation works because D is a shorthand for D[Any, Any], so the None types get never inferred.
There are at least two ways in which we could fix this:
Somehow propagate information back from the union return type to the type context, with the goal of simplifying away the union in the return type. The rationale here is that it's preferable to have a non-union return than a union return type if we are free to choose either by substituting type variables suitably.
Update the second argument to get to have type Union[_VT_co, _T] and pick up the _VT_co context from there. I checked that this doesn't work yet, so this will also require a mypy change.
The first option sounds pretty complicated, so I'm planning to try the second option first.
OK, now I see. It looks like the current state of Mapping.get() etc. causes lots of issues with real-world code, so I agree on the priority. Solution (2) sounds fine.
Activity
gvanrossum commentedon Jan 17, 2017
The first example doesn't even need the 1-arg overload. The covariance of the value type also seems unrelated.
But I'm not sure I understand what you think the behavior should be. The type of
defaultis intentionally a different type variable than D's value type. So what is the type ofD()passed as the default? Why should it conform to the value type?I tried to rewrite the example using a separate assignment:
but this says
Need type annotation for variableon thed = D()line. But somehow when I change toall is well. So it looks like there's something half-hearted being done to the
D()call in your original version, where it is not quite given the typeD[Any, Any]?If you think there's simply a bug I'm happy to sit back and look at your fix to see if I can understand the issue that way. :-) (But your last sentence made it sound like you're not sure yourself?)
JukkaL commentedon Jan 17, 2017
The explicit annotation works because
Dis a shorthand forD[Any, Any], so theNonetypes get never inferred.There are at least two ways in which we could fix this:
getto have typeUnion[_VT_co, _T]and pick up the_VT_cocontext from there. I checked that this doesn't work yet, so this will also require a mypy change.The first option sounds pretty complicated, so I'm planning to try the second option first.
gvanrossum commentedon Jan 17, 2017
OK, now I see. It looks like the current state of
Mapping.get()etc. causes lots of issues with real-world code, so I agree on the priority. Solution (2) sounds fine.Fix special cases where type context is a union
Fix special cases where type context is a union (#2715)