Skip to content

Commit 9323b88

Browse files
authored
Fix overlap check for ParamSpec types (#18040)
ParamSpec types can match arbitrary parameter types, so treat them as having 'object' as the upper bound. This also fixes issues with filtering of overload items based on self type. Fixes #18036.
1 parent 1cb8cc4 commit 9323b88

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

mypy/meet.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,11 @@ def get_possible_variants(typ: Type) -> list[Type]:
223223
else:
224224
return [typ.upper_bound]
225225
elif isinstance(typ, ParamSpecType):
226-
return [typ.upper_bound]
226+
# Extract 'object' from the final mro item
227+
upper_bound = get_proper_type(typ.upper_bound)
228+
if isinstance(upper_bound, Instance):
229+
return [Instance(upper_bound.type.mro[-1], [])]
230+
return [AnyType(TypeOfAny.implementation_artifact)]
227231
elif isinstance(typ, TypeVarTupleType):
228232
return [typ.upper_bound]
229233
elif isinstance(typ, UnionType):

test-data/unit/check-selftype.test

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,3 +2176,41 @@ class count:
21762176
def foo(x: Union[range[int], count]) -> None:
21772177
for item in x:
21782178
reveal_type(item) # N: Revealed type is "builtins.int"
2179+
2180+
[case testGenericDescriptorWithSelfTypeAnnotationsAndOverloads]
2181+
from __future__ import annotations
2182+
from typing import Any, overload, Callable, TypeVar, Generic, ParamSpec
2183+
from typing_extensions import Concatenate
2184+
2185+
C = TypeVar("C", bound=Callable[..., Any])
2186+
S = TypeVar("S")
2187+
P = ParamSpec("P")
2188+
R = TypeVar("R")
2189+
2190+
class Descriptor(Generic[C]):
2191+
def __init__(self, impl: C) -> None: ...
2192+
2193+
@overload
2194+
def __get__(
2195+
self: Descriptor[C], instance: None, owner: type | None
2196+
) -> Descriptor[C]: ...
2197+
2198+
@overload
2199+
def __get__(
2200+
self: Descriptor[Callable[Concatenate[S, P], R]], instance: S, owner: type | None,
2201+
) -> Callable[P, R]: ...
2202+
2203+
def __get__(self, *args, **kwargs): ...
2204+
2205+
class Test:
2206+
@Descriptor
2207+
def method(self, foo: int, bar: str) -> bytes: ...
2208+
2209+
reveal_type(Test().method) # N: Revealed type is "def (foo: builtins.int, bar: builtins.str) -> builtins.bytes"
2210+
2211+
class Test2:
2212+
@Descriptor
2213+
def method(self, foo: int, *, bar: str) -> bytes: ...
2214+
2215+
reveal_type(Test2().method) # N: Revealed type is "def (foo: builtins.int, *, bar: builtins.str) -> builtins.bytes"
2216+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)