microsoft / microsoft/pyright

Incorrect overload parameter mismatch when typing decorator

Open
#11,333 1 comment 0 reactions 0 assignees View on GitHub
bug
Dominant language
Python
Stars
15.6k
Forks
1.8k
Avg merge
12h 13m
Merged PRs (30d)
52

Description

**Describe the bug**
Trying to type a decorator, and I'm running into some seemingly spurious errors. I've tried to figure out what exactly causes this, to no avail.

The goal is to have the an optional `cls` parameter, and to have the return type vary based on whether it is present or absent. Mypy accepts the following code, but Pyright does not.

Apologies if this has already been reported, but I couldn't find any existing issue.

**Code **

[Pyright playground](https://pyright-play.net/?strict=true&code=GYJw9gtgBALgngBwJYDsDmUkQWEMpgBuApiADZgCGAJgDRQDClZZlARmcQFBcACRpCjS7ViwKKIDGuSjFwBtACoBdABSSyAZwBcsRMSXL6AenoAqesQAeMEJV2p8AXigAGAJRQAtAD49CAxVtLihQqAA6SJ5%2BEnIqahExCWJpOzkQQ3UtXQA5MBRiKBc8gpNzSxs7BxRnN09fRmZWDgN5eADDI39A5WVgsIioxPEpGXTMjR1uwygAHygSwuL84jKoCyhrW3tMGqK6-rCkcUnMTQWVw4HQ0XEAdzsEAJAsqfae%2Br93wyvrgZBiDAAK4gFDJVKyXCvCrbJxbOzuEJ-KAA4GgqAPShPUhI0K4qCaQGyWzQqAAIgA%2BhT4ZQqWSYQj8aiQWDJlwgA)

[Mypy playground](https://mypy-play.net/?mypy=latest&python=3.14&gist=41df62496abcd51282d3f8d5097ba4b1)

```py
from typing import overload, Callable

@overload
def decorator[T](cls: type[T], /, *, extra: int = 0) -> type[T]:
...

@overload
def decorator[T](cls: None = None, /, *, extra: int = 0) -> Callable[[type[T]], type[T]]:
...

def decorator[T](cls: type[T] | None = None, /, *, extra: int = 0):
if cls is None:
def wrapper(cls: type[T]) -> type[T]:
return decorator(cls, extra=extra)
return wrapper

setattr(cls, "__extra__", extra)
return cls
```

Pyright error message:
```py
Overloaded implementation is not consistent with signature of overload 2
Function return type "(type[T@decorator]) -> type[T@decorator]" is incompatible with type "((cls: type[T@decorator]) -> type[T@decorator]) | type[T@decorator]"
Type "(type[T@decorator]) -> type[T@decorator]" is not assignable to type "((cls: type[T@decorator]) -> type[T@decorator]) | type[T@decorator]"
Type "(type[T@decorator]) -> type[T@decorator]" is not assignable to type "type[T@decorator]"
Type "(type[T@decorator]) -> type[T@decorator]" is not assignable to type "(cls: type[T@decorator]) -> type[T@decorator]"
Missing keyword parameter "cls"
Position-only parameter mismatch; parameter "cls" is not position-only
Position-only parameter mismatch; expected 1 but received 0 (reportInconsistentOverload)
```

Contributor guide

Open the contributing guide

Research direction

Start with the linked Pyright playground and the reduced decorator example, then trace the overload-consistency diagnostic that reports the mismatch. Reproduce the error in strict mode and verify that the valid overload set no longer produces a spurious implementation error while inconsistent overloads remain diagnosed.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.