Skip to content

False positive when using Self as the return type with multiple base classes #17704

Closed

Description

@Cnoor0171

Bug Report

If you try to derive from multiple base classes that both define the same function returning Self, mypy incorrectly warns that the definitions are incompatible.

To Reproduce

# https://mypy-play.net/?mypy=latest&python=3.12&gist=e5d3734df862e8f3ada5c11c076cae57
# main.py
from typing import Self

class MyBase1:
    def foo(self) -> Self:
        return self

class MyBase2:
    def foo(self) -> Self:
        return self

class MyDerived(MyBase1, MyBase2):
    pass


MyBase1().foo()  # Should be Valid. Has type MyBase1
MyBase1().foo()  # Should be Valid. Has type MyBase2
MyDerived().foo()  # Should be Valid. Has type MyDerived

Expected Behavior

Shouldn't report any errors. In the context of the line class MyDerived(MyBase1, MyBase2): both MyBase1 and MyBase2 returns Self aka MyDerived

Actual Behavior

$ mypy main.py
main.py:13: error: Definition of "foo" in base class "MyBase1" is incompatible with definition in base class "MyBase2"  [misc]
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: mypy 1.11.1 (compiled: yes)
  • Mypy command-line flags:
  • Mypy configuration options from mypy.ini (and other config files):
  • Python version used: 3.12

Activity

  1. Cnoor0171 commented on Aug 22, 2024

    @Cnoor0171
    Author

    A similar problem if the methods are classmethods

    from typing import Self
    
    class MyBase1:
        @classmethod
        def foo(cls) -> Self:
            return cls()
    
    class MyBase2:
        @classmethod
        def foo(cls) -> Self:
            return cls()
    
    class MyDerived(MyBase1, MyBase2):
        pass
    
    
    MyBase1.foo()  # Should be Valid. Has type MyBase1
    MyBase1.foo()  # Should be Valid. Has type MyBase2
    MyDerived.foo()  # Should be Valid. Has type MyDerived

    Interestingly, mypy is also able to derive the correct type of MyDerived.foo() or MyDerived().foo() if you do reveal_type on them.

  2. sterliakov commented on Jan 15, 2025

    @sterliakov
    Collaborator

    Missed this ticket - also resolved by #18465 and passes on current master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions