Bug Report
self: Self (unwrapped) is accepted with no error. The same Self, wrapped in
Annotated — e.g. self: Annotated[Self, "tag"] — raises Method cannot have explicit self annotation and Self type [misc].
Per [PEP 593](https://peps.python.org/pep-0593/), Annotated[T, x] is specified to be
treated identically to T by any tool that doesn't specifically interpret the
metadata:
If a tool or library does not support annotating an object with Annotated, it
should ignore it and treat the underlying type as the type of the object.
Since mypy doesn't itself interpret arbitrary Annotated metadata, wrapping Self
this way shouldn't change whether the explicit self-annotation is accepted — but it
does.
To Reproduce
from typing import Self, Annotated
class Foo:
# OK -- no error
def works(self: Self, x: int) -> None:
pass
# error: Method cannot have explicit self annotation and Self type [misc]
def fails(self: Annotated[Self, "tag"], x: int) -> None:
pass
Expected Behavior
Both methods should be treated the same — either both accepted, or both rejected with
the same diagnostic. Annotated[Self, ...] should not behave differently from bare
Self in this position.
Actual Behavior
example.py:9: error: Method cannot have explicit self annotation and Self type [misc]
The error appears only on the Annotated-wrapped version; the identical unwrapped
self: Self on the method directly above is accepted with no diagnostic at all.
Your Environment
- Mypy version used: 2.3.1 (compiled: yes)
- Mypy command-line flags: none (default settings)
- Mypy configuration options: none (no
mypy.ini/pyproject.toml config in the
reproduction environment)
- Python version used: 3.13.4
- Operating system and version: openSUSE Tumbleweed v.20260829. Kernel: 7.2.0-1-default
Behavior in other type checkers
For comparison, the identical self: Annotated[Self, "tag"] construct was tested against two other checkers on the same file:
ty (Astral) accepts it with no error, and correctly treats self as generically Self-typed — reveal_type(Foo.fails) shows def fails[Self](self: Self, x: int) -> None, identical genericity to the accepted bare-Self case.
pyright does not raise an error either, but is a weaker counterexample: it doesn't just omit the metadata, it discards the annotation's type entirely — reveal_type shows self: Foo (the concrete class), not self: Self, i.e. it silently reverts to ordinary implicit self-typing as if the explicit annotation were never written.
Additional notes
This report was drafted with the assistance of an LLM (Claude). All claims in it — the reproduction, the exact error text, the version numbers, and the cross-checker comparison — were independently verified by running mypy, ty, and pyright directly against the code shown above; none of it is unverified model output. Happy to answer follow-up questions or run further variations on request.
This was noticed while trying to attach custom static-analysis metadata to a method's receiver type via Annotated[Self, MyCustomTag()], specifically because Annotated is documented as the mechanism for doing exactly this without affecting how standard type checkers see the underlying type. The current behavior means that use case isn't available for self specifically, even though it works normally for every other parameter position.
Bug Report
self: Self(unwrapped) is accepted with no error. The sameSelf, wrapped inAnnotated— e.g.self: Annotated[Self, "tag"]— raisesMethod cannot have explicit self annotation and Self type [misc].Per [PEP 593](https://peps.python.org/pep-0593/),
Annotated[T, x]is specified to betreated identically to
Tby any tool that doesn't specifically interpret themetadata:
Since mypy doesn't itself interpret arbitrary
Annotatedmetadata, wrappingSelfthis way shouldn't change whether the explicit self-annotation is accepted — but it
does.
To Reproduce
Expected Behavior
Both methods should be treated the same — either both accepted, or both rejected with
the same diagnostic.
Annotated[Self, ...]should not behave differently from bareSelfin this position.Actual Behavior
The error appears only on the
Annotated-wrapped version; the identical unwrappedself: Selfon the method directly above is accepted with no diagnostic at all.Your Environment
mypy.ini/pyproject.tomlconfig in thereproduction environment)
Behavior in other type checkers
For comparison, the identical self: Annotated[Self, "tag"] construct was tested against two other checkers on the same file:
ty (Astral) accepts it with no error, and correctly treats self as generically Self-typed — reveal_type(Foo.fails) shows def fails[Self](self: Self, x: int) -> None, identical genericity to the accepted bare-Self case.
pyright does not raise an error either, but is a weaker counterexample: it doesn't just omit the metadata, it discards the annotation's type entirely — reveal_type shows self: Foo (the concrete class), not self: Self, i.e. it silently reverts to ordinary implicit self-typing as if the explicit annotation were never written.
Additional notes
This report was drafted with the assistance of an LLM (Claude). All claims in it — the reproduction, the exact error text, the version numbers, and the cross-checker comparison — were independently verified by running mypy, ty, and pyright directly against the code shown above; none of it is unverified model output. Happy to answer follow-up questions or run further variations on request.
This was noticed while trying to attach custom static-analysis metadata to a method's receiver type via Annotated[Self, MyCustomTag()], specifically because Annotated is documented as the mechanism for doing exactly this without affecting how standard type checkers see the underlying type. The current behavior means that use case isn't available for self specifically, even though it works normally for every other parameter position.