Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect handling of Concatenate when used with generics and decorators #9742

Open
mkzeender opened this issue Jan 23, 2025 · 2 comments
Open
Labels
addressed in next version Issue is fixed and will appear in next published version bug Something isn't working

Comments

@mkzeender
Copy link

Describe the bug
A clear and concise description of the behavior you are seeing and the expected behavior along with steps to reproduce it.

In the following example, we define a generic decorator that turns a (higher order) function into a MyGeneric (which could be, i.e. a descriptor).

We use that decorator on dumb_thingy, a function that takes a function and injects an int argument into it. The type checker should therefore assume that the ParamSpec **Args has a single mandatory int argument. However, pyright incorrectly infers that there are TWO mandatory int arguments.

Interestingly, this bug does NOT apply to the Callable generic, only user-defined generics. I.e. replacing MyGeneric[Args] with Callable[Args, Any] exhibits the correct behavior. It also does NOT apply unless Concatenate is used. I.e. replacing Concatenate[int, P] with [int] exhibits the correct behavior.

from typing import Any, Concatenate, Callable

class MyGeneric[**Args]: ...

def my_decorator[
    **Args,
](dec_func: Callable[[Callable[Args, Any]], Any]) -> MyGeneric[Args]: ...

@my_decorator
def dumb_thingy[**P](func: Callable[Concatenate[int, P], Any]): ...

_v: MyGeneric[[int]] = dumb_thingy  # false positive type error

_v2: MyGeneric[[int, int]] = dumb_thingy  # passes type check.

Tested on pyright command line version 1.1.392
Also occurs on latest pylance VSCode extension.
mypy has the correct behavior.

@mkzeender mkzeender added the bug Something isn't working label Jan 23, 2025
@erictraut
Copy link
Collaborator

Thanks for the bug report.

On first inspection, there are actually two bugs here. The first bug is a type evaluation bug that results in the int parameter being duplicated (there should be only one). The second is a false negative condition. Both _v and _v2 should result in errors, but _v2 currently does not result in an error. Mypy correctly reports errors in both cases.

@mkzeender
Copy link
Author

@erictraut

Sorry for the poor example; I'll take your word that they should both be errors. I don't know enough type theory to have an opinion on whether MyGeneric[[int, ...]] should be assignable to MyGeneric[[int]] (where the ... represents an unknown amount of parameters).

But the duplicated int parameter is definitely a problem.

erictraut added a commit that referenced this issue Jan 26, 2025
…function with a callable parameter that uses Concatenate plus ParamSpec to a function that accepts a callable with just a ParamSpec. This addresses #9742.
erictraut added a commit that referenced this issue Jan 26, 2025
…function with a callable parameter that uses Concatenate plus ParamSpec to a function that accepts a callable with just a ParamSpec. This addresses #9742. (#9765)
@erictraut erictraut added as designed Not a bug, working as intended addressed in next version Issue is fixed and will appear in next published version and removed as designed Not a bug, working as intended labels Jan 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addressed in next version Issue is fixed and will appear in next published version bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants