Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
hopefully final round of changes
  • Loading branch information
Gobot1234 committed Oct 8, 2025
commit a33030f405b130706371358e5b5825c5626d80e7
72 changes: 69 additions & 3 deletions peps/pep-0718.rst
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,75 @@ Interactions with ``@typing.overload``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Overloaded functions should work much the same as already, since they have no effect on
the runtime type. The only change is that more situations will be decidable and the
behaviour/overload can be specified by the developer rather than leaving it to ordering
of overloads/unions.
the runtime type. This change will lead to more expressiveness with user's able to
decide and the behaviour/overload can be specified by the developer rather than leaving
it to ordering of overloads/unions.

.. code-block:: python

# N.B. `class bytes(Sequence[int]): ...` and `Foo` is a non-specified generic type
@overload
def seq_first[T: Sequence[int]](x: T) -> T: ...
@overload
def seq_first[T: bytes](x: T) -> Foo[T]: ...

@overload
def bytes_first[T: bytes](x: T) -> Foo[T]: ...
@overload
def bytes_first[T: Sequence[int]](x: T) -> T: ...

reveal_type(seq_first(b"")) # type is bytes
reveal_type(bytes_first(b"")) # type is Foo[bytes]

Explicit specialisation will restrict the set of available overloads

.. code-block:: python

@overload
def make[T](x: T) -> T: ...
@overload
def make(x: str, y: str) -> tuple[int, int]: ...

reveal_type(make[int](1)) # type is int
reveal_type(make[int]("foo", "bar")) # Invalid: no overload for `make[int](x:str, y: str)` found, a similar overload exists but explicit specialisation prevented its use

Functions Parameterized by ``TypeVarTuple``s
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Currently type checkers disallow the use of multiple ``TypeVarTuple``s in it's generic
parameters, however it is currently valid to have a function as such

.. code-block:: python

def foo[*T, *U](bar: Bar[*T], baz: Baz[*U]): ...
def spam[*T](bar: Bar[*T]): ...

This PEP does not allow similar functions to be subscripted, for the same reason as
defined in :pep:`PEP 646<646#multiple-type-variable-tuples-not-allowed>`.

.. code-block:: python

foo[int, str, bool, complex](Bar(), Baz()) # Invalid: cannot determine which parameters are passed to *T and *U. Explicitly parameterise the instances individually
spam[int, str, bool, complex](Bar()) # OK


Binding Rules
^^^^^^^^^^^^^
Subscriptions on methods (including classmethods, staticmethods etc.) should only have
access to their function's type parameters and not the enclosing class's. Subscription
should follow the rules specified in :pep:`PEP 696<696#binding-rules>` methods should
be bound on attribute access.

.. code-block:: python

class C[T]:
def method[U](self, x: T, y: U): ...
@classmethod
def cls[U](cls, x: T, y: U): ...

C[int].method[str](0, "") # OK
C[int].cls[str](0, "") # OK
C.cls[int, str](0, "") # Invalid: too many type parameters
C.cls[str](0, "") # OK, T is ideally bound to int here though this is open for type checkers to decide

Backwards Compatibility
-----------------------
Expand Down
Loading