@@ -2599,3 +2599,160 @@ def run3(predicate: Callable[Concatenate[int, str, _P], None], *args: _P.args, *
25992599 # E: Argument 1 has incompatible type "*tuple[int | str, ...]"; expected "str" \
26002600 # E: Argument 1 has incompatible type "*tuple[int | str, ...]"; expected "_P.args"
26012601[builtins fixtures/paramspec.pyi]
2602+
2603+ [case testRevealBoundParamSpecArgs]
2604+ from typing import Callable, Generic, ParamSpec
2605+ from typing_extensions import Concatenate, TypeVarTuple, Unpack
2606+
2607+ P = ParamSpec("P")
2608+ Ts = TypeVarTuple("Ts")
2609+
2610+ class Sneaky(Generic[P]):
2611+ def __init__(self, fn: Callable[P, object], *args: P.args, **kwargs: P.kwargs) -> None:
2612+ self.fn = fn
2613+ self.args = args
2614+ self.kwargs = kwargs
2615+
2616+ class SneakyPrefix(Generic[P]):
2617+ def __init__(self, fn: Callable[Concatenate[int, P], object], _: int, *args: P.args, **kwargs: P.kwargs) -> None:
2618+ self.fn = fn
2619+ self.args = args
2620+ self.kwargs = kwargs
2621+
2622+ def f1() -> int:
2623+ return 0
2624+ def f2(x: int) -> int:
2625+ return 0
2626+ def f3(x: int, /) -> int:
2627+ return 0
2628+ def f4(*, x: int) -> int:
2629+ return 0
2630+ def f5(x: int, y: int = 0) -> int:
2631+ return 0
2632+ def f6(x: int, *args: int) -> int:
2633+ return 0
2634+ def f7(x: int, *args: Unpack[Ts]) -> int:
2635+ return 0
2636+ def f8(x: int, *args: Unpack[tuple[str, ...]]) -> int:
2637+ return 0
2638+ def f9(x: int, *args: Unpack[tuple[str, int]]) -> int:
2639+ return 0
2640+ def f10(x: int=0, *args: Unpack[tuple[str, ...]]) -> int:
2641+ return 0
2642+ def f11(x: int = 0, /) -> int:
2643+ return 0
2644+
2645+ reveal_type(Sneaky(f1).args) # N: Revealed type is "tuple[()]"
2646+ reveal_type(SneakyPrefix(f1).args) # E: Missing positional argument "_" in call to "SneakyPrefix" \
2647+ # N: Revealed type is "tuple[()]" \
2648+ # E: Argument 1 to "SneakyPrefix" has incompatible type "Callable[[], int]"; expected "Callable[[int], object]"
2649+
2650+ reveal_type(Sneaky(f2, 1).args) # N: Revealed type is "tuple[()] | tuple[builtins.int]"
2651+ reveal_type(SneakyPrefix(f2, 1).args) # N: Revealed type is "tuple[()]"
2652+
2653+ reveal_type(Sneaky(f3, 1).args) # N: Revealed type is "tuple[builtins.int]"
2654+ reveal_type(SneakyPrefix(f3, 1).args) # N: Revealed type is "tuple[()]"
2655+
2656+ reveal_type(Sneaky(f4, x=1).args) # N: Revealed type is "tuple[()]"
2657+
2658+ reveal_type(Sneaky(f5, 1).args) # N: Revealed type is "tuple[()] | tuple[builtins.int] | tuple[builtins.int, builtins.int]"
2659+ reveal_type(SneakyPrefix(f5, 1).args) # N: Revealed type is "tuple[()] | tuple[builtins.int]"
2660+ reveal_type(Sneaky(f5, 1, 2).args) # N: Revealed type is "tuple[()] | tuple[builtins.int] | tuple[builtins.int, builtins.int]"
2661+ reveal_type(SneakyPrefix(f5, 1, 2).args) # N: Revealed type is "tuple[()] | tuple[builtins.int]"
2662+
2663+ reveal_type(Sneaky(f6, 1).args) # N: Revealed type is "tuple[()] | tuple[builtins.int] | tuple[builtins.int, Unpack[builtins.tuple[builtins.int, ...]]]"
2664+ reveal_type(SneakyPrefix(f6, 1).args) # N: Revealed type is "tuple[()] | tuple[Unpack[builtins.tuple[builtins.int, ...]]]"
2665+ reveal_type(Sneaky(f6, 1, 2).args) # N: Revealed type is "tuple[()] | tuple[builtins.int] | tuple[builtins.int, Unpack[builtins.tuple[builtins.int, ...]]]"
2666+ reveal_type(SneakyPrefix(f6, 1, 2).args) # N: Revealed type is "tuple[()] | tuple[Unpack[builtins.tuple[builtins.int, ...]]]"
2667+
2668+ reveal_type(Sneaky(f7, 1, 2).args) # N: Revealed type is "tuple[Literal[1]?, Literal[2]?]"
2669+ reveal_type(SneakyPrefix(f7, 1, 2).args) # N: Revealed type is "tuple[Literal[2]?]"
2670+
2671+ reveal_type(Sneaky(f8, 1, '').args) # N: Revealed type is "tuple[()] | tuple[builtins.int] | tuple[builtins.int, Unpack[builtins.tuple[builtins.str, ...]]]"
2672+ reveal_type(SneakyPrefix(f8, 1, '').args) # N: Revealed type is "tuple[()] | tuple[Unpack[builtins.tuple[builtins.str, ...]]]"
2673+
2674+ reveal_type(Sneaky(f9, 1, '', 0).args) # N: Revealed type is "tuple[builtins.int, builtins.str, builtins.int]"
2675+ reveal_type(SneakyPrefix(f9, 1, '', 0).args) # N: Revealed type is "tuple[builtins.str, builtins.int]"
2676+
2677+ reveal_type(Sneaky(f10, 1, '', '').args) # N: Revealed type is "tuple[()] | tuple[builtins.int] | tuple[builtins.int, Unpack[builtins.tuple[builtins.str, ...]]]"
2678+ reveal_type(SneakyPrefix(f10, 1, '', '').args) # N: Revealed type is "tuple[()] | tuple[Unpack[builtins.tuple[builtins.str, ...]]]"
2679+
2680+ reveal_type(Sneaky(f11).args) # N: Revealed type is "tuple[()] | tuple[builtins.int]"
2681+ [builtins fixtures/paramspec.pyi]
2682+
2683+ [case testRevealBoundParamSpecGeneric]
2684+ from typing import Callable, Generic, ParamSpec, TypeVar
2685+ from typing_extensions import TypeVarTuple, Unpack
2686+
2687+ T = TypeVar("T")
2688+ P = ParamSpec("P")
2689+ Ts = TypeVarTuple("Ts")
2690+
2691+ class SplitSneaky(Generic[P]):
2692+ def __init__(self, target: Callable[P, None]) -> None:
2693+ ...
2694+
2695+ def run(self, *args: P.args, **kwargs: P.kwargs) -> None:
2696+ self.args = args
2697+ self.kwargs = kwargs
2698+
2699+ def f1(x: T) -> None: ...
2700+ def f2(*xs: Unpack[Ts]) -> None: ...
2701+ def f3(fn: Callable[P, None]) -> None: ...
2702+
2703+ reveal_type(SplitSneaky(f1).args) # N: Revealed type is "builtins.tuple[builtins.object, ...]"
2704+ reveal_type(SplitSneaky(f1).kwargs) # N: Revealed type is "builtins.dict[builtins.str, builtins.object]"
2705+ reveal_type(SplitSneaky(f2).args) # N: Revealed type is "builtins.tuple[builtins.object, ...]"
2706+ reveal_type(SplitSneaky(f2).kwargs) # N: Revealed type is "builtins.dict[builtins.str, builtins.object]"
2707+ reveal_type(SplitSneaky(f3).args) # N: Revealed type is "builtins.tuple[builtins.object, ...]"
2708+ reveal_type(SplitSneaky(f3).kwargs) # N: Revealed type is "builtins.dict[builtins.str, builtins.object]"
2709+ [builtins fixtures/paramspec.pyi]
2710+
2711+ [case testRevealBoundParamSpecKwargs]
2712+ from typing import Callable, Generic, ParamSpec
2713+ from typing_extensions import Unpack, NotRequired, TypedDict
2714+
2715+ P = ParamSpec("P")
2716+
2717+ class Sneaky(Generic[P]):
2718+ def __init__(self, fn: Callable[P, object], *args: P.args, **kwargs: P.kwargs) -> None:
2719+ self.fn = fn
2720+ self.args = args
2721+ self.kwargs = kwargs
2722+
2723+ class Opt(TypedDict):
2724+ y: int
2725+ z: NotRequired[str]
2726+
2727+ def f1() -> int:
2728+ return 0
2729+ def f2(x: int) -> int:
2730+ return 0
2731+ def f3(x: int, /) -> int:
2732+ return 0
2733+ def f4(*, x: int) -> int:
2734+ return 0
2735+ def f5(x: int, y: int = 0) -> int:
2736+ return 0
2737+ def f6(**kwargs: int) -> int:
2738+ return 0
2739+ def f7(x: int, **kwargs: str) -> int:
2740+ return 0
2741+ def f8(x: int, /, **kwargs: str) -> int:
2742+ return 0
2743+ def f9(x: int, **kwargs: Unpack[Opt]) -> int:
2744+ return 0
2745+
2746+ reveal_type(Sneaky(f1).kwargs) # N: Revealed type is "builtins.dict[builtins.str, Never]"
2747+ reveal_type(Sneaky(f2, 1).kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int})"
2748+ reveal_type(Sneaky(f3, 1).kwargs) # N: Revealed type is "builtins.dict[builtins.str, Never]"
2749+ reveal_type(Sneaky(f4, x=1).kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x': builtins.int})"
2750+ reveal_type(Sneaky(f5, 1).kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int, 'y'?: builtins.int})"
2751+ reveal_type(Sneaky(f5, 1, 2).kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int, 'y'?: builtins.int})"
2752+ reveal_type(Sneaky(f6, x=1).kwargs) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]"
2753+ reveal_type(Sneaky(f6, x=1, y=2).kwargs) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]"
2754+ reveal_type(Sneaky(f7, 1, y='').kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int})"
2755+ reveal_type(Sneaky(f8, 1, y='').kwargs) # N: Revealed type is "builtins.dict[builtins.str, builtins.str]"
2756+ reveal_type(Sneaky(f9, 1, y=0).kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int, 'y': builtins.int, 'z'?: builtins.str})"
2757+ reveal_type(Sneaky(f9, 1, y=0, z='').kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int, 'y': builtins.int, 'z'?: builtins.str})"
2758+ [builtins fixtures/paramspec.pyi]
0 commit comments