Skip to content

False Positives in Protocol Assignability Check Where Self Is a Parameter of a Decorated Method (1.17.0) #19482

@nhusung

Description

@nhusung

Bug Report

This bug appears to be a regression in mypy 1.17.0, version 1.16.1 works as expected.

To Reproduce

Consider the following code snippet:

from typing import Protocol, Self


class Proto(Protocol):
    def foo(self, x: Self) -> None: ...


class Impl:
    def foo(self, x: Self) -> None:
        pass


x: Proto = Impl()

This is fine on both mypy 1.17.0 and 1.16.1. When we decorate foo in Proto (e.g., with @abstractmethod, @deprecated, or @classmethod), then the assignability check fails in mypy 1.17.0 only. Here are some snippets revealing the bug (the links use the master branch version because 1.17.0 is not available on mypy-play.net yet):

I played around with some other variants:

  • The bug only shows if Self is used as the type of an argument. Using Self as a return type only is fine in 1.17.0.
  • When Impl declares compatibility with Proto explicitly (i.e., class Impl(Proto)), the bug does not show.
  • Whether foo in Impl is decorated or not does not appear to matter (only tested with @deprecated).
  • Whether foo in Impl has x: Self or x: Impl does not matter

Expected Behavior

There should not be an error for all playground links above, as with mypy 1.16.1 or pyright.

Actual Behavior

mypy 1.17.0 shows errors like these (here for the example with @abstractmethod):

main.py:18: error: Incompatible types in assignment (expression has type "Impl", variable has type "Proto")  [assignment]
main.py:18: note: Following member(s) of "Impl" have conflicts:
main.py:18: note:     Expected:
main.py:18: note:         def [Self: Proto] foo(self, x: Proto) -> None
main.py:18: note:     Got:
main.py:18: note:         def foo(self, x: Impl) -> None
Found 1 error in 1 file (checked 1 source file)

mypy 1.16.1 and pyright do not print any diagnostics.

Your Environment

  • Mypy version used: 1.17.0 (bug) / 1.16.1 (expected behavior)
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.13.5

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions