Skip to content

incorrect annotations for builtins.reversed #11645

Description

@jorenham

The builtins.reversed.__new__ signature is currently annotated like (Reversible[T] | SupportsLenAndGetItem[T]) -> Iterator[T]:

typeshed/stdlib/builtins.pyi

Lines 1639 to 1646 in 3d26992

class reversed(Iterator[_T]):
@overload
def __new__(cls, sequence: Reversible[_T], /) -> Iterator[_T]: ... # type: ignore[misc]
@overload
def __new__(cls, sequence: SupportsLenAndGetItem[_T], /) -> Iterator[_T]: ... # type: ignore[misc]
def __iter__(self) -> Self: ...
def __next__(self) -> _T: ...
def __length_hint__(self) -> int: ...

It has two problems:

argument of type SupportsLenAndGetItem[T]

This should return a reversed[T] instance (i.e. Self), instead of "just" an Iterable[T], which is unnecessarily loose.

argument with type that implement __reversed__

This is only handled if the argument's __reversed__ returns an Iterator[T], i.e. arguments that are Reversible[T]. But in reality, reversed(x) is equivalent to x.__reversed__() (if __reversed__ exists). To illustrate:

>>> class Revver[X]:
...     x: X
...     def __init__(self, x: X):
...         self.x = x
...     def __reversed__(self) -> X:
...         return self.x
... 
>>> reversed(Revver(42))
42

However, this case isn't handled because Revver[X] cannot be expressed as a Reversible[?].


So instead, it should look something like this:

class SupportsReversed[T]:
    def __reversed__(self) -> T: ...

class reversed[T](Iterator[T]):
    @overload
    def __new__[R](cls, sequence: SupportsReversed[R], /) -> R: ...
    @overload
    def __new__(cls, sequence: SupportsLenAndGetItem[T], /) -> Self: ...
    def __length_hint__(self) -> int: ...
    # btw, this is why protocols shouldn't be mixed with abstract classes:
    def __iter__(self) -> Self: ...
    def __next__(self) -> T: ...

Let me know if I should make this into PR :)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions