mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-90345 Count a type variable once across value and class-object positions in a type alias
A type variable used both as a value (`T`) and as a class object (`type[T]`) was collected twice — in instance and definition form — so a parameterized generic type alias such as `Union[Role[T], type[T]]` appeared to have two type parameters. Subscripting it with a single argument mapped the surplus parameter to Any, which collapsed the `type[T]` arm and left the type variable unbound: e.g. `select(Model)` was inferred as `Select[tuple[Any]]` instead of `Select[tuple[Model]]`, losing element types (and completion) on query results. Normalize type variables to their instance form when counting a generic type's parameters in PyTypeChecker.parameterizeType, so the same variable is counted once. (cherry picked from commit 5ae8e727eef7168caafa269dc5fd64c0a38f36f8) GitOrigin-RevId: f7c58e89e561d1cbc70bee22821b7e62272fd545
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ca8fc24822
commit
e5b8e52e8d
@@ -733,6 +733,65 @@ class PyGenericTypeTest : PyCodeInsightTestCase() {
|
||||
expr: TypeAlias[int]
|
||||
#└ TYPE type[int]
|
||||
""")
|
||||
|
||||
@Test
|
||||
@TestFor(issues = ["PY-90345"])
|
||||
fun `call inference via union TypeAlias with class-object arm`() = test("""
|
||||
from typing import Generic, TypeVar
|
||||
T = TypeVar('T')
|
||||
class Role(Generic[T]): ...
|
||||
Alias = Role[T] | type[T]
|
||||
def f(x: Alias[T]) -> T: ...
|
||||
expr = f(int)
|
||||
#└ TYPE int
|
||||
""")
|
||||
|
||||
@Test
|
||||
@TestFor(issues = ["PY-90345"])
|
||||
fun `call inference via union TypeAlias with class-object arm first`() = test("""
|
||||
from typing import Generic, TypeVar
|
||||
T = TypeVar('T')
|
||||
class Role(Generic[T]): ...
|
||||
Alias = type[T] | Role[T]
|
||||
def f(x: Alias[T]) -> T: ...
|
||||
expr = f(int)
|
||||
#└ TYPE int
|
||||
""")
|
||||
|
||||
@Test
|
||||
@TestFor(issues = ["PY-90345"])
|
||||
fun `call inference via three-arm union TypeAlias with class-object`() = test("""
|
||||
from typing import Generic, TypeVar
|
||||
T = TypeVar('T')
|
||||
class A(Generic[T]): ...
|
||||
class B(Generic[T]): ...
|
||||
Alias = A[T] | B[T] | type[T]
|
||||
def f(x: Alias[T]) -> T: ...
|
||||
expr = f(int)
|
||||
#└ TYPE int
|
||||
""")
|
||||
|
||||
@Test
|
||||
@TestFor(issues = ["PY-90345"])
|
||||
fun `parameterized union TypeAlias with class-object arm`() = test("""
|
||||
from typing import Generic, TypeVar
|
||||
T = TypeVar('T')
|
||||
class Role(Generic[T]): ...
|
||||
Alias = Role[T] | type[T]
|
||||
expr: Alias[int]
|
||||
#└ TYPE Role[int] | type[int]
|
||||
""")
|
||||
|
||||
@Test
|
||||
@TestFor(issues = ["PY-90345"])
|
||||
fun `parameterized union TypeAlias with class-object arm PEP695`() = test("""
|
||||
from typing import Generic, TypeVar
|
||||
T = TypeVar('T')
|
||||
class Role(Generic[T]): ...
|
||||
type Alias[T] = Role[T] | type[T]
|
||||
expr: Alias[int]
|
||||
#└ TYPE Role[int] | type[int]
|
||||
""")
|
||||
}
|
||||
|
||||
@Nested
|
||||
@@ -1758,4 +1817,5 @@ class PyGenericTypeTest : PyCodeInsightTestCase() {
|
||||
# FIXME PY-37876: an error is expected here but is not produced; documents current behavior.
|
||||
func(42, accepts_anything)
|
||||
""")
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user