Skip to content
Open
Changes from all commits
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
54 changes: 50 additions & 4 deletions peps/pep-0718.rst
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,56 @@ The following code snippet would fail at runtime without this change as
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.
Overloaded functions should work much the same as they already do, since they do not
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is about the runtime behavior of calling overloaded functions?

affect the runtime type. Explicit specialisation will restrict the set of available
overloads.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth spelling out in detail how this would work. What I'd expect is that if the function is subscripted, only those overloads are considered for which the subscription may succeed. So if you have an overload make[*Ts], one with make[T], and one with just make, then a call to make[int] will only consider the first and second, and a call to make[int, str] will only consider the first. This could be another step in the overload resolution spec before all the current steps.


.. 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 their
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 functions like ``foo`` 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
^^^^^^^^^^^^^
Method subscription (including ``classmethods``, ``staticmethods``, etc.) should only
have access tos their function's type parameter and not the enclosing class's.
Subscription should follow the rules specified in :pep:`PEP 696<696#binding-rules>`;
methods should bind type parameters 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