Skip to content

Base class function signature compatibility checks overly strict #2619

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ambv opened this issue Dec 28, 2016 · 2 comments · Fixed by #6585
Closed

Base class function signature compatibility checks overly strict #2619

ambv opened this issue Dec 28, 2016 · 2 comments · Fixed by #6585
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal

Comments

@ambv
Copy link
Contributor

ambv commented Dec 28, 2016

Actual example of this code can be found in Python 3.6's enum with Flag and IntFlag.

Minimal repro::

from typing import TypeVar

_T = TypeVar('_T')


class Base:
    def __or__(self: _T, other: _T) -> _T: ...
    def __and__(self: _T, other: _T) -> _T: ...
    def __xor__(self: _T, other: _T) -> _T: ...


class Other(int, Base):  # <-- errors here
    def __or__(self: _T, other: Union[int, _T]) -> _T: ...  # type: ignore
    def __and__(self: _T, other: Union[int, _T]) -> _T: ...  # type: ignore
    def __xor__(self: _T, other: Union[int, _T]) -> _T: ...  # type: ignore

Expected behavior: no errors.
Actual behavior:

f:11: error: Definition of "__and__" in base class "int" is incompatible with definition in base class "Base"
f:11: error: Definition of "__or__" in base class "int" is incompatible with definition in base class "Base"
f:11: error: Definition of "__xor__" in base class "int" is incompatible with definition in base class "Base"

The errors would be fine if Other didn't redefine the methods itself. In this case the incompatibility in base classes is irrelevant.

@gvanrossum gvanrossum added the bug mypy got something wrong label Jan 14, 2017
@JukkaL
Copy link
Collaborator

JukkaL commented Jan 16, 2017

Keywords to help searching: self type, union type

@JukkaL JukkaL added the false-positive mypy gave an error on correct code label May 19, 2018
@jingw
Copy link
Contributor

jingw commented Jun 26, 2018

Just ran into this at Dropbox.

Slightly more distilled repro:

class A(object):
    def x(self):
        # type: () -> A
        return self

class B(object):
    def x(self):
        # type: () -> B
        return self

class C(A, B):
    def x(self):
        # type: () -> C
        return self

test.py:11: error: Definition of "x" in base class "A" is incompatible with definition in base class "B"

And equivalent compilable Java code:

interface A {
    A x();
}
interface B {
    B x();
}
class C implements A, B {
    public C x() {
        return this;
    }
}

I presume mypy already has checks that C.x is compatible with A.x and B.x. Is it possible to resolve this issue by doing something along the lines of removing the check that A.x and B.x are compatible in the case where x is overridden? (Note, I don't really know what I'm talking about.)

syastrov added a commit to syastrov/mypy that referenced this issue Mar 24, 2019
…defined

- In the case of multiple inheritance, don't give errors about definitions of an
  attribute in base classes being incompatible when the attribute is redefined.
  The redefinition must itself be compatible with all (non-type-ignored)
  definitions of the attribute in all base classes.
  This is achieved by making the following change to checking of incompatible
  types in assignments.
- Don't stop checking after the first base where the attribute is defined
  when checking for incompatible types in assignments.
  There is still a maximum of one "Incompatible type in assignment" error
  per assignment.

Resolves python#2619
ilevkivskyi pushed a commit that referenced this issue Apr 12, 2019
…defined (#6585)

This eliminates the error `Definition of "Nested" in base class "Base1" is incompatible with definition in base class "Base2"` in the following code, where `Nested` is redefined in `A`:
```
from typing import TypeVar, Generic
T = TypeVar('T', covariant=True)
class GenericBase(Generic[T]):
    pass
class Base1:
    Nested: GenericBase['Base1']
class Base2:
    Nested: GenericBase['Base2']
class A(Base1, Base2):
    Nested: GenericBase['A']
```

- In the case of multiple inheritance, don't give errors about definitions of an
  attribute in base classes being incompatible when the attribute is redefined.
  The redefinition must itself be compatible with all (non-type-ignored)
  definitions of the attribute in all base classes.
  This is achieved by making the following change to checking of incompatible
  types in assignments.
- Don't stop checking after the first base where the attribute is defined
  when checking for incompatible types in assignments.
  There is still a maximum of one "Incompatible type in assignment" error
  per assignment.

Resolves #2619
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants