Generic Type Narrowing Consistency/Scope Question #2719
-
When helping debug some attempts to use generics by a friend (they really wanted sum types), i came across some behaviors I can't quite explain, but I'm also not really sure are bugs and I've mostly exhausted trying to connect the dots with documentation and examples. Mypy behavior here isn't any less confusing. Hopefully you can help elucidate what's intended behavior (and why) or just a bug. In the following code sample, why aren't we be allowed to assign I'll admit the code is a bit weird, but I can imagine some contrived case where you want the type consistency between from typing import Any, Generic, TypeGuard, TypeVar
class A:
def bar(self): ...
class B:
def foo(self): ...
T = TypeVar('T')
class M(Generic[T]): ...
def is_A_M(p: M[Any]) -> TypeGuard[M[A]]: ...
# error (??)
def func(x: T, y: T) -> None:
if isinstance(x, A) and isinstance(y, A):
reveal_type(x) # A
reveal_type(y) # A
x.bar() # no error
x = A() # error
x = y # no error
# error
def func2(x: T, y: T) -> None:
if isinstance(x, A):
reveal_type(x) # A
reveal_type(y) # T@func3
y.bar() # error
y = x
y.bar()
# error (??)
def func3(x: M[T], y: M[T]) -> None:
if is_A_M(x) and is_A_M(y):
reveal_type(x) # M[A]
reveal_type(y) # M[A]
x = y # error |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 7 replies
-
When you're using a TypeVar, the type must be consistent throughout the scope. The In In Incidentally, mypy emits the same errors as pyright. |
Beta Was this translation helpful? Give feedback.
When you're using a TypeVar, the type must be consistent throughout the scope. The
isinstance
check infunc
is checking to see ifx
andy
are subclasses ofA
, but that doesn't mean they are typeA
. They could be a class that is derived fromA
. For that reasonx = A()
is not allowed.In
func2
, theisinstance
check is applying type narrowing to the expressionx
. A type guard narrows only the type of the expression found within the conditional statement. In this case, that expression isx
, so only the type ofx
is narrowed. If you want to narrow the type ofy
, you would need to include it in the type guard conditional expression. That's just how type guards work.In
func3
, the declared type of