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
Using Generic and __new__ in class def, mypy misses incorrect parameter if parameter created inline #14009
If you have a stub that defines a Generic class with __new__(), with overloads, and the final overload doesn't specify the type of the generic, then a function call that creates an object of the generic class in the function call is not picked up as an error, but it is picked up if stored in another variable.
Actual Behavior
mypy does not pick up that the first call to fun is incorrect. It does pick up that the second call is incorrect.
pyright picks up both as being incorrect.
Output from mypy:
genparam.py:10: error: Argument 1 to "fun" has incompatible type "Foo[str]"; expected "Foo[int]"
Your Environment
Mypy version used: 0.971
Mypy command-line flags: --no-incremental
Mypy configuration options from mypy.ini (and other config files): None
I believe it's due to type context (Eric calls the equivalent technique in pyright 'bidirectional inference'). When a particular type is expected, type checkers try to infer that type to minimize errors. However, when the value is assigned to a variable, that assignment is type checked independently and sets the type.
When a particular type is expected, type checkers try to infer that type to minimize errors. However, when the value is assigned to a variable, that assignment is type checked independently and sets the type.
I don't think your example fits in this case, because object is more of a supertype.
When you call fun(param=Foo(str)) (or the equivalent fun(Foo(str))), a type checker needs to determine whether there a way for the expression Foo(str) to be evaluated such that it can satisfy the call to fun. In this case, there is a way because there is an overload that returns a Foo[Any], and Foo[Any] is compatible with Foo[int].
By contrast, if you construct a Foo[str] independent of the call to fun, there is no way to transform that Fun[str] into a Fun[int] such that it's compatible with parameter param.
It's similar to this:
a1= [1, 2, 3]
x1: list[float] =a# Type errorx2: list[float] = [1, 2, 3] # No type error
Activity
erictraut commentedon Aug 14, 2023
I think mypy is correct here. The behavior you cited for pyright was due to a bug which was fixed a while ago. Pyright and mypy now agree.
Dr-Irv commentedon Aug 15, 2023
Why do you think that both pyright and mypy are correct?
Why should the 2 calls
to the function
fun()be interpreted differently?JelleZijlstra commentedon Aug 15, 2023
I believe it's due to type context (Eric calls the equivalent technique in pyright 'bidirectional inference'). When a particular type is expected, type checkers try to infer that type to minimize errors. However, when the value is assigned to a variable, that assignment is type checked independently and sets the type.
Consider code like this:
Here mypy shows an error for the first call, but not the second.
Dr-Irv commentedon Aug 15, 2023
I don't think your example fits in this case, because
objectis more of a supertype.In my example, you have
So I don't see how
Foo(str), which has typeFoo[str]could ever matchFoo[int]in the first call tofun()erictraut commentedon Aug 15, 2023
When you call
fun(param=Foo(str))(or the equivalentfun(Foo(str))), a type checker needs to determine whether there a way for the expressionFoo(str)to be evaluated such that it can satisfy the call tofun. In this case, there is a way because there is an overload that returns aFoo[Any], andFoo[Any]is compatible withFoo[int].By contrast, if you construct a
Foo[str]independent of the call tofun, there is no way to transform thatFun[str]into aFun[int]such that it's compatible with parameterparam.It's similar to this:
Dr-Irv commentedon Aug 15, 2023
@erictraut thanks for the example. It's very subtle, and difficult for people using type checkers to understand.