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

__slots__ and protocols don't work right for issubclass and typevar bounds #11884

Closed
A5rocks opened this issue Jan 2, 2022 · 6 comments · Fixed by #15490
Closed

__slots__ and protocols don't work right for issubclass and typevar bounds #11884

A5rocks opened this issue Jan 2, 2022 · 6 comments · Fixed by #15490
Labels
bug mypy got something wrong

Comments

@A5rocks
Copy link
Contributor

A5rocks commented Jan 2, 2022

cc @sobolevn since you've been doing stuff here

Bug Report

Slots become part of a interface with protocols, they shouldn't be.

To Reproduce

import typing

@typing.runtime_checkable
class Foo(typing.Protocol):
    __slots__ = ()


class Bar:
    pass

_T = typing.TypeVar("_T", bound="Foo")


def foo(f: _T) -> _T:
    return f

print(issubclass(Bar, Foo))
print(isinstance(Bar(), Foo))
foo(Bar())

Expected Behavior

At runtime this prints:

True
True

So issubclass is allowed, and I don't see why the TypeVar bounds shouldn't be.

Actual Behavior

main.py:17: error: Only protocols that don't have non-method members can be used with issubclass()
main.py:17: note: Protocol "Foo" has non-method member(s): __slots__
main.py:19: error: Value of type variable "_T" of "foo" cannot be "Bar"
Found 2 errors in 1 file (checked 1 source file)

Your Environment

mypy playground

@A5rocks A5rocks added the bug mypy got something wrong label Jan 2, 2022
@sobolevn
Copy link
Member

sobolevn commented Jan 2, 2022

Thanks, added to my backlog. We can treat this one as a regression, so the priority is high 🙂

@sobolevn
Copy link
Member

sobolevn commented Jan 2, 2022

Simplier repro:

import typing

@typing.runtime_checkable
class Foo(typing.Protocol):
    __slots__ = ()


class Bar:
    pass

def foo(f: Foo) -> Foo:
    return f

foo(Bar())
# out/ex.py:14: error: Argument 1 to "foo" has incompatible type "Bar"; expected "Foo"
# out/ex.py:14: note: Following member(s) of "Bar" have conflicts:
# out/ex.py:14: note:     __slots__: expected "Tuple[]", got "Union[str, Iterable[str]]"

@sobolevn
Copy link
Member

sobolevn commented Jan 2, 2022

Related #9314

@sobolevn
Copy link
Member

sobolevn commented Jan 2, 2022

Important question: should we treat __slots__ as a part of the protocol?

Let's see how other type checkers do that 🤔

@sobolevn
Copy link
Member

sobolevn commented Jan 2, 2022

Pyright ignores __slots__ definition from protocol members. Probably, we should too.

@sobolevn
Copy link
Member

sobolevn commented Jan 2, 2022

@A5rocks reviews are welcome! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
2 participants