Skip to content

Commit

Permalink
Fix overlap check for ParamSpec types (#18040)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
JukkaL authored Oct 25, 2024
1 parent 1cb8cc4 commit 9323b88
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
6 changes: 5 additions & 1 deletion mypy/meet.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,11 @@ def get_possible_variants(typ: Type) -> list[Type]:
else:
return [typ.upper_bound]
elif isinstance(typ, ParamSpecType):
return [typ.upper_bound]
# Extract 'object' from the final mro item
upper_bound = get_proper_type(typ.upper_bound)
if isinstance(upper_bound, Instance):
return [Instance(upper_bound.type.mro[-1], [])]
return [AnyType(TypeOfAny.implementation_artifact)]
elif isinstance(typ, TypeVarTupleType):
return [typ.upper_bound]
elif isinstance(typ, UnionType):
Expand Down
38 changes: 38 additions & 0 deletions test-data/unit/check-selftype.test
Original file line number Diff line number Diff line change
Expand Up @@ -2176,3 +2176,41 @@ class count:
def foo(x: Union[range[int], count]) -> None:
for item in x:
reveal_type(item) # N: Revealed type is "builtins.int"

[case testGenericDescriptorWithSelfTypeAnnotationsAndOverloads]
from __future__ import annotations
from typing import Any, overload, Callable, TypeVar, Generic, ParamSpec
from typing_extensions import Concatenate

C = TypeVar("C", bound=Callable[..., Any])
S = TypeVar("S")
P = ParamSpec("P")
R = TypeVar("R")

class Descriptor(Generic[C]):
def __init__(self, impl: C) -> None: ...

@overload
def __get__(
self: Descriptor[C], instance: None, owner: type | None
) -> Descriptor[C]: ...

@overload
def __get__(
self: Descriptor[Callable[Concatenate[S, P], R]], instance: S, owner: type | None,
) -> Callable[P, R]: ...

def __get__(self, *args, **kwargs): ...

class Test:
@Descriptor
def method(self, foo: int, bar: str) -> bytes: ...

reveal_type(Test().method) # N: Revealed type is "def (foo: builtins.int, bar: builtins.str) -> builtins.bytes"

class Test2:
@Descriptor
def method(self, foo: int, *, bar: str) -> bytes: ...

reveal_type(Test2().method) # N: Revealed type is "def (foo: builtins.int, *, bar: builtins.str) -> builtins.bytes"
[builtins fixtures/tuple.pyi]

0 comments on commit 9323b88

Please sign in to comment.