Pylance infers wrong return type for overloaded function with Unknown arguments #2660
Replies: 10 comments 1 reply
-
This is intended behavior. Pyright (the type checker that pylance is built upon) uses the first overload that matches. I recommend that you provide type annotations for |
Beta Was this translation helpful? Give feedback.
-
Why is this the intended behavior? |
Beta Was this translation helpful? Give feedback.
-
First, it's the behavior indicated in PEP 484 for overloads. Second, returning an unknown or union of all possible return types would have significant downsides for those who are interested in type checking, especially if they're using strict type checking modes. A union of all possible return types will tend to generate a bunch of downstream false positive type errors. An unknown will generate "type is partially unknown" errors in strict mode. Do you see any downside of adding type annotations as I've suggested above? |
Beta Was this translation helpful? Give feedback.
-
Thanks for the explanation. Where does PEP 484 specify this? I couldn't find it. IMO the downside of choosing the first overload's return type is that pyright is giving false information and also misses type errors. Consider this: import os
def some_func(path1, path2):
my_value = os.path.relpath(path1, path2)
my_value.decode("utf-8")
some_func("hi", "hello") Pyright allows it but it will raise on runtime ( Btw I am using strict mode with some errors disabled. |
Beta Was this translation helpful? Give feedback.
-
In other words, I prefer pyright to not make guesses for me, I prefer it to say "I don't know" |
Beta Was this translation helpful? Give feedback.
-
In strict mode, you should see errors about input parameters having unknown types. With unknown input types, there are many runtime errors that a type checker will not be able to catch statically. |
Beta Was this translation helpful? Give feedback.
-
I understand. Personally I have disabled these 'reportUnknownXXXType' errors because they are too verbose for me (I have a lot of unannotated code). For me the problem is pyright showing 'bytes' when I hover
In those cases the users should annotate their variables :) |
Beta Was this translation helpful? Give feedback.
-
Curiously, mypy says "Any" here. https://mypy-play.net/?mypy=latest&python=3.9&gist=62a2b917e1be277c0c59b13a9f59a376 |
Beta Was this translation helpful? Give feedback.
-
Came across this one as well. Although it might technically be correct, it's not that intuitive. Especially when adding type annotations to a codebase, it's sometimes unavoidable to have some |
Beta Was this translation helpful? Give feedback.
-
# pyright 1.1.343
# mypy 1.7.1
from typing import Any, overload
@overload
def foo(arg: list[int]) -> int:
...
@overload
def foo(arg: Any) -> Any:
...
def foo(arg):
return arg
x = []
y: list = []
reveal_type([]) # list[Unknown] (pyright), list[Never] (mypy)
reveal_type(x) # list[Unknown] (pyright), list[Any] (mypy)
reveal_type(y) # list[Unknown] (pyright), list[Any] (mypy)
reveal_type(foo([])) # int (pyright), int (mypy)
reveal_type(foo(x)) # int (pyright), int (mypy)
reveal_type(foo(y)) # int (pyright), Any (mypy)
|
Beta Was this translation helpful? Give feedback.
-
Environment data
Expected behaviour
When arguments have type Unknown and there are overloads with different return types, the inferred return type should be Unknown or probably a Union of the overload return types.
Actual behaviour
It seems that Pylance chooses the return type from the first overload, which is incorrect.
Code Snippet / Additional information
Note: here is the declaration from posixpath.pyi in typeshed-fallback:
Beta Was this translation helpful? Give feedback.
All reactions