Skip to content

Incremental mode bug for nested ParamSpecs #14322

Open
@ringohoffman

Description

@ringohoffman

Bug Report

This bug only occurs on the second run when using incremental mode. When using nested ParamSpecs, the outer ParamSpec (M below) is erroneously equal to the inner ParamSpec (P below).

Notably, pyright handles this correctly.

To Reproduce

from __future__ import annotations

from typing import Callable, Concatenate, Generic, ParamSpec, TypeVar


class ABase:
    ...


class ADerived(ABase):
    def __init__(self, a_param_1: float) -> None:
        super().__init__()
        self.a_1 = a_param_1


M = ParamSpec("M")
P = ParamSpec("P")
R = TypeVar("R", bound=ABase)


class B(Generic[P, R]):
    def __init__(
        self,
        a_class: Callable[P, R],
        b_param_1: str,
        *args: P.args,
        **kwargs: P.kwargs,
    ) -> None:
        self.a = a_class(*args, **kwargs)
        self.b_1 = b_param_1

    @classmethod
    def build(
        cls: Callable[Concatenate[Callable[P, R], M], B[P, R]], 
        a_class: Callable[P, R]
    ) -> Callable[M, B[P, R]]:

        def new_constructor(
            *args: M.args,
            **kwargs: M.kwargs,
        ) -> B[P, R]:
            return cls(a_class, *args, **kwargs)

        return new_constructor


BADerived = B.build(ADerived)

reveal_type(BADerived)  # note): Revealed type is "def (a_param_1: builtins.float) -> B[[a_param_1: builtins.float], ADerived]"

b_a_derived_1 = B(ADerived, "my_str", 1.0)  # OK
b_a_derived_2 = BADerived(  # [call-arg] error: Too many arguments
    "my_str", 1.0  # [arg-type] error: Argument 1 has incompatible type "str"; expected "float"
)

Expected Behavior

I expect the signature of BADerived to include b_param_1, like this:

mypy_nested_paramspec.py:49: note: Revealed type is "def (b_param_1: builtins.str, a_param_1: builtins.float) -> mypy_nested_paramspec.B[[a_param_1: builtins.float], ADerived]"

I also expect that calls to BADerived with the correct parameter count and types do not raise any errors.

Actual Behavior

mypy_nested_paramspec.py:49: note: Revealed type is "def (a_param_1: builtins.float) -> mypy_nested_paramspec.B[[a_param_1: builtins.float], mypy_nested_paramspec.ADerived]"
mypy_nested_paramspec.py:52: error: Too many arguments  [call-arg]
mypy_nested_paramspec.py:53: error: Argument 1 has incompatible type "str"; expected "float"  [arg-type]

Your Environment

  • Mypy version used: mypy 0.991 (compiled: yes)
  • Python version used: 3.10.6

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions