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

How should structural subtyping work for objects with slots but no variable declarations? #1367

Closed
AlexWaygood opened this issue Mar 9, 2023 · 3 comments
Labels
topic: other Other topics not covered

Comments

@AlexWaygood
Copy link
Member

AlexWaygood commented Mar 9, 2023

Consider the snippet below:

from typing import runtime_checkable, Protocol

@runtime_checkable
class HasX(Protocol):
    x: int

class HasNothingButSlots:
    __slots__ = ("x",)

def requires_object_with_x(obj: HasX) -> None:
    print(obj.x)

requires_object_with_x(HasNothingButSlots())

Mypy does not see HasNothingButSlots as a valid subtype of of HasX, so complains about this code. Pyright, however, does see HasNothingButSlots as a valid subtype of HasX, so has no complaints.

Currently, the runtime agrees with mypy: calling isinstance(HasNothingButSlots(), HasX) evaluates to False (due to the fact that the x variable has not been initialised on the instance). If we implement any of the patches discussed in #1363, this will change, and the runtime will agree with pyright: isinstance(HasNothingButSlots(), HasX) will evaluate to True even if the x variable has not been initialised on the instance.

Who is correct: mypy or pyright?

@AlexWaygood AlexWaygood added the topic: other Other topics not covered label Mar 9, 2023
@AlexWaygood AlexWaygood changed the title How should structural subtyping work for objects with slots? How should structural subtyping work for objects with slots but no variable declarations? Mar 9, 2023
@TeamSpen210
Copy link

Perhaps it would be reasonable for mypy to treat this as x: Any, but also produce a "x needs a type definition" or "Any type inferred" warning?

@gvanrossum
Copy link
Member

I tend to agree with pyright -- surely any realistic class with slots does initialize the slots in __init__ or some other method?

@AlexWaygood
Copy link
Member Author

The points made here makes sense to me. Seems like the consensus is that pyright's behaviour is preferable — closing as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: other Other topics not covered
Projects
None yet
Development

No branches or pull requests

3 participants