Skip to content

Self type with multiple inheritance #18458

Closed
@jeremander

Description

@jeremander

Not sure whether this is actually a bug or not, but I'm getting a base class incompatibility error when inheriting from two classes defining a method with the same signature containing the typing.Self type.

To Reproduce

from typing import Self

class A:
    def a_method(self) -> None:
        pass
    def method(self: Self, other: Self) -> None:
        self.a_method()
        other.a_method()

class B:
    def b_method(self) -> None:
        pass
    def method(self: Self, other: Self) -> None:
        self.b_method()
        other.b_method()

class C(A, B):
    pass

Running mypy gives this error:

test.py:17: error: Definition of "method" in base class "A" is incompatible with definition in base class "B"  [misc]

I expected Self to mean "whatever this type happens to be" (base class or subclass) but the error would suggest that it's interpreting Self as the specific class containing that method definition.

Next I tried the following variation:

from typing import TypeVar

T = TypeVar('T')

class A:
    def a_method(self) -> None:
        pass
    def method(self: T, other: T) -> None:
        self.a_method()

class B:
    def b_method(self) -> None:
        pass
    def method(self: T, other: T) -> None:
        self.b_method()

class C(A, B):
    pass

This fixes the incompatibility error but results in new errors:

test.py:9: error: "T" has no attribute "a_method"  [attr-defined]
test.py:15: error: "T" has no attribute "b_method"  [attr-defined]

I also tried using two separate TypeVars, one with bound='A' and the other with bound='B', but this brought back the "incompatible definition" error from before.

Finally (after reverting the types back to Self), I updated C's definition to the following:

class C(A, B):
    def method(self: Self, other: Self) -> None:
        A.method(self, other)

This ended up type-checking, but I'm wondering if mypy ought to be clever enough to figure it out without having to explicitly override method, or if there's some other alternative?

And if not, perhaps the error message about the incompatible definition could elaborate a bit more in the case where the type signatures "appear" to match due to the use of Self?

Environment

  • Python 3.11.11
  • mypy 1.14.1 (no flags or config file)

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