@@ -2599,3 +2599,97 @@ def run3(predicate: Callable[Concatenate[int, str, _P], None], *args: _P.args, *
25992599 # E: Argument 1 has incompatible type "*tuple[Union[int, str], ...]"; expected "str" \
26002600 # E: Argument 1 has incompatible type "*tuple[Union[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 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+ def f1() -> int:
2617+ return 0
2618+ def f2(x: int) -> int:
2619+ return 0
2620+ def f3(x: int, /) -> int:
2621+ return 0
2622+ def f4(*, x: int) -> int:
2623+ return 0
2624+ def f5(x: int, y: int = 0) -> int:
2625+ return 0
2626+ def f6(x: int, *args: int) -> int:
2627+ return 0
2628+ def f7(x: int, *args: Unpack[Ts]) -> int:
2629+ return 0
2630+ def f8(x: int, *args: Unpack[tuple[str, ...]]) -> int:
2631+ return 0
2632+ def f9(x: int, *args: Unpack[tuple[str, int]]) -> int:
2633+ return 0
2634+
2635+ reveal_type(Sneaky(f1).args) # N: Revealed type is "tuple[()]"
2636+ reveal_type(Sneaky(f2, 1).args) # N: Revealed type is "Union[tuple[()], tuple[builtins.int]]"
2637+ reveal_type(Sneaky(f3, 1).args) # N: Revealed type is "tuple[builtins.int]"
2638+ reveal_type(Sneaky(f4, x=1).args) # N: Revealed type is "tuple[()]"
2639+ reveal_type(Sneaky(f5, 1).args) # N: Revealed type is "Union[tuple[()], tuple[builtins.int], tuple[builtins.int, builtins.int]]"
2640+ reveal_type(Sneaky(f5, 1, 2).args) # N: Revealed type is "Union[tuple[()], tuple[builtins.int], tuple[builtins.int, builtins.int]]"
2641+ reveal_type(Sneaky(f6, 1).args) # N: Revealed type is "Union[tuple[()], tuple[builtins.int], tuple[builtins.int, Unpack[builtins.tuple[builtins.int, ...]]]]"
2642+ reveal_type(Sneaky(f6, 1, 2).args) # N: Revealed type is "Union[tuple[()], tuple[builtins.int], tuple[builtins.int, Unpack[builtins.tuple[builtins.int, ...]]]]"
2643+ reveal_type(Sneaky(f7, 1, 2).args) # N: Revealed type is "tuple[Literal[1]?, Literal[2]?]"
2644+ reveal_type(Sneaky(f8, 1, '').args) # N: Revealed type is "Union[tuple[()], tuple[builtins.int], tuple[builtins.int, Unpack[builtins.tuple[builtins.str, ...]]]]"
2645+ reveal_type(Sneaky(f9, 1, '', 0).args) # N: Revealed type is "tuple[builtins.int, builtins.str, builtins.int]"
2646+ [builtins fixtures/paramspec.pyi]
2647+
2648+ [case testRevealBoundParamSpecKwargs]
2649+ from typing import Callable, Generic, ParamSpec
2650+ from typing_extensions import Unpack, NotRequired, TypedDict
2651+
2652+ P = ParamSpec("P")
2653+
2654+ class Sneaky(Generic[P]):
2655+ def __init__(self, fn: Callable[P, object], *args: P.args, **kwargs: P.kwargs) -> None:
2656+ self.fn = fn
2657+ self.args = args
2658+ self.kwargs = kwargs
2659+
2660+ class Opt(TypedDict):
2661+ y: int
2662+ z: NotRequired[str]
2663+
2664+ def f1() -> int:
2665+ return 0
2666+ def f2(x: int) -> int:
2667+ return 0
2668+ def f3(x: int, /) -> int:
2669+ return 0
2670+ def f4(*, x: int) -> int:
2671+ return 0
2672+ def f5(x: int, y: int = 0) -> int:
2673+ return 0
2674+ def f6(**kwargs: int) -> int:
2675+ return 0
2676+ def f7(x: int, **kwargs: str) -> int:
2677+ return 0
2678+ def f8(x: int, /, **kwargs: str) -> int:
2679+ return 0
2680+ def f9(x: int, **kwargs: Unpack[Opt]) -> int:
2681+ return 0
2682+
2683+ reveal_type(Sneaky(f1).kwargs) # N: Revealed type is "builtins.dict[builtins.str, Never]"
2684+ reveal_type(Sneaky(f2, 1).kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int})"
2685+ reveal_type(Sneaky(f3, 1).kwargs) # N: Revealed type is "builtins.dict[builtins.str, Never]"
2686+ reveal_type(Sneaky(f4, x=1).kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x': builtins.int})"
2687+ reveal_type(Sneaky(f5, 1).kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int, 'y'?: builtins.int})"
2688+ reveal_type(Sneaky(f5, 1, 2).kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int, 'y'?: builtins.int})"
2689+ reveal_type(Sneaky(f6, x=1).kwargs) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]"
2690+ reveal_type(Sneaky(f6, x=1, y=2).kwargs) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]"
2691+ reveal_type(Sneaky(f7, 1, y='').kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int})"
2692+ reveal_type(Sneaky(f8, 1, y='').kwargs) # N: Revealed type is "builtins.dict[builtins.str, builtins.str]"
2693+ reveal_type(Sneaky(f9, 1, y=0).kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int, 'y': builtins.int, 'z'?: builtins.str})"
2694+ 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})"
2695+ [builtins fixtures/paramspec.pyi]
0 commit comments