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

Recent change to tuple constructor breaks subclasses of tuples #8275

Closed
erictraut opened this issue Jul 12, 2022 · 3 comments · Fixed by #8278
Closed

Recent change to tuple constructor breaks subclasses of tuples #8275

erictraut opened this issue Jul 12, 2022 · 3 comments · Fixed by #8278

Comments

@erictraut
Copy link
Contributor

A recent change to the tuple.__new__ method in builtins.pyi introduced an overload:

    @overload
    def __new__(cls) -> tuple[()]: ...

This overload is problematic for classes that derive from specialized tuples.

class MyTuple(tuple[int, str, str]):
    ...

x = MyTuple()
reveal_type(x) # tuple[()] !!!!

Because of this overload, the wrong type is evaluated.

I think this overload should return Self, not tuple[()]. Admittedly, that doesn't produce the ideal type evaluation for tuple(). It produces tuple[Any, ...] rather than tuple[()].

@AlexWaygood
Copy link
Member

class MyTuple(tuple[int, str, str]):
    ...

x = MyTuple()
reveal_type(x) # tuple[()] !!!!

I feel like maybe a type checker should disallow this snippet. This is what happens at runtime:

>>> class MyTuple(tuple[int, str, str]): ...
...
>>> MyTuple()
()

Perhaps type checkers should disallow calls to subclasses of specialised tuples unless __new__ has been overridden?

@JelleZijlstra
Copy link
Member

@AlexWaygood the runtime type of MyTuple() is in fact MyTuple. I don't see why type checkers should disallow that.

This change is from #7454. I already brought up this possible issue, but for whatever reason mypy doesn't infer the wrong type for subclasses in this case. Given that it causes a regression for pyright, I'm fine with reverting it.

@AlexWaygood
Copy link
Member

AlexWaygood commented Jul 12, 2022

@AlexWaygood the runtime type of MyTuple() is in fact MyTuple. I don't see why type checkers should disallow that.

The runtime type is MyTuple, yes, but it's not a subtype of tuple[int, str, str]. My concern is about situations like this:

class MyTuple(tuple[int, str, str]):
    ...

x = MyTuple()  # type checker is happy with this, infers type of x as MyTuple

# type checker is happy with this due to x having inferred type of MyTuple,
# and due to MyTuple being a subtype of tuple[int, str, str].
# However, this fails at runtime.
a, b, c = x

That feels pretty unsafe to me.

But I'm fine with reverting #7454 for now; I agree that it doesn't bring much benefit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants