-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Bounded generic type parameter not narrowed past its upper bound, regardless of argument value #19285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This boils down to def foo[T](*x: T) -> T: ...
reveal_type(foo(1, "a")) # N: Revealed type is "builtins.object" |
@brianschubert Hmm but interestingly if I add an upper bound there, mypy is suddenly able to narrow: def foo[T: int | str | bool](*x: T) -> T: ...
reveal_type(foo(1, "a")) # Revealed type is "Union[builtins.int, builtins.str]"Mypy |
Yeah, specifics matter for the inference rules. Closer to this case would be def foo[T: BaseException](*x: T) -> T: ...
reveal_type(foo(ValueError(), TypeError())) # N: Revealed type is "builtins.Exception" In your case the joined type ( Note by the way that there isn't actually any narrowing happening in your case. def foo[T: int | str | bytes](*x: T) -> T: ...
reveal_type(foo(1, "a")) # N: Revealed type is "builtins.int | builtins.str | builtins.bytes" |
Ah right yea. Equivalently this def foo[B: BaseException](*x: type[B]) -> B:
return x[0]()
reveal_type(foo(ValueError, TypeError)) # N: Revealed type is "builtins.Exception" and confirming that things are narrowed correctly if there's just a single parameter, although mypy has a different weird issue here with the implementation if the upper bound is a union: def bar[B: ValueError | TypeError](x: type[B]) -> B:
return x() # Incompatible return value type (got "ValueError | TypeError", expected "B")Mypyreturn-value
reveal_type(bar(ValueError)) # Revealed type is "builtins.ValueError"Mypy
reveal_type(bar(TypeError)) # Revealed type is "builtins.TypeError"Mypy And oh right lol good point on |
Bug Report
If a generic type variable
_E
has an upper boundB
, the upper boundB
seems to be used as the inferred type of_E
when inferring other type variables that depend on_E
, even if there is a more specific type that_E
could be narrowed to.This becomes an issue when trying to infer error types returned by poltergeist (a simple library that provides a generic
Result = Ok[_T] | Err[_E]
utility type).To Reproduce
The implementation of
catch
can be found here:Source code for the `catch` decorator
Expected Behavior
mypy should be able to accurately use the value of
errors
to narrow the inferred type of_E
withincatch
, and thus infer thatvalidated_number_result
is of typeResult[int, TypeError | ValueError]
.Actual Behavior
Mypy keeps
_E
inferred to its upper boundBaseException
, thus inferringvalidated_number_result
asResult[int, BaseException]
.By contrast,
pylance
's type checker is able to narrowvalidated_number_result
as expected:Your Environment
mypy.ini
(and other config files):mypy.ini
Unsure if related to #19081 , but it's possible, given that both these issues are related to retaining information via generic type parameters.
The text was updated successfully, but these errors were encountered: