Skip to content
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

Missing Liskov error for subclass with subclass field #11720

Closed
NoamNol opened this issue Dec 12, 2021 · 3 comments
Closed

Missing Liskov error for subclass with subclass field #11720

NoamNol opened this issue Dec 12, 2021 · 3 comments
Labels
bug mypy got something wrong topic-inheritance Inheritance and incompatible overrides

Comments

@NoamNol
Copy link

NoamNol commented Dec 12, 2021

Mypy is ok with the following code. why?

class Animal():
    pass

class Bird(Animal):
    def fly(self):
        print("fly")

class Farm():
    animal = Animal()

class FarmWithBirds(Farm):
    animal = Bird() # why mypy is ok?

def func(f: Farm):
    f.animal = Animal() # the magic

f = FarmWithBirds()
f.animal.fly() # print "fly"
func(f)
f.animal.fly() # AttributeError: 'Animal' object has no attribute 'fly'

Related: #2984, Incompatible overrides

@intgr
Copy link
Contributor

intgr commented Dec 12, 2021

Note that this works the way I expected when assigning the animal attribute in __init__:

class Animal():
    pass

class Bird(Animal):
    def fly(self):
        print("fly")

class Farm():
    def __init__(self):   # <-- added
        self.animal = Animal()

class FarmWithBirds(Farm):
    def __init__(self):   # <-- added
        self.animal = Bird()

def func(f: Farm):
    f.animal = Animal() # the magic

f = FarmWithBirds()
reveal_type(f.animal) # note: Revealed type is "issue11720.Animal"
f.animal.fly() # error: "Animal" has no attribute "fly"

Not sure why class variables are handled differently in this case.

@AlexWaygood AlexWaygood added the topic-inheritance Inheritance and incompatible overrides label Mar 26, 2022
@AlexWaygood
Copy link
Member

Mypy also does not emit any errors for this variation:

from typing import ClassVar

class Animal:
    pass

class Bird(Animal):
    def fly(self) -> None:
        print("fly")

class Farm:
    animal: ClassVar[Animal] = Animal()

class FarmWithBirds(Farm):
    animal: ClassVar[Bird] = Bird() # why mypy is ok?

def func(f: type[Farm]) -> None:
    f.animal = Animal() # the magic

f = FarmWithBirds
f.animal.fly() # print "fly"
func(f)
f.animal.fly() # AttributeError: 'Animal' object has no attribute 'fly'

I think this is a bug.

@AlexWaygood AlexWaygood added bug mypy got something wrong and removed question labels Apr 2, 2022
@hauntsaninja
Copy link
Collaborator

Duplicate of #3208

@hauntsaninja hauntsaninja marked this as a duplicate of #3208 Aug 13, 2023
@hauntsaninja hauntsaninja closed this as not planned Won't fix, can't repro, duplicate, stale Aug 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-inheritance Inheritance and incompatible overrides
Projects
None yet
Development

No branches or pull requests

4 participants