From a33030f405b130706371358e5b5825c5626d80e7 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Wed, 8 Oct 2025 16:08:37 +0100 Subject: [PATCH 1/4] hopefully final round of changes --- peps/pep-0718.rst | 72 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/peps/pep-0718.rst b/peps/pep-0718.rst index 13b4ccc1f9c..1d661f0122d 100644 --- a/peps/pep-0718.rst +++ b/peps/pep-0718.rst @@ -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 ----------------------- From 475bd8ee430c19d0f989870b23974ae0a6077877 Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Wed, 8 Oct 2025 16:22:39 +0100 Subject: [PATCH 2/4] I think fix the build issues? Sorry I can't test I can't get make installed --- peps/pep-0718.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/peps/pep-0718.rst b/peps/pep-0718.rst index 1d661f0122d..d75bdb6ecc8 100644 --- a/peps/pep-0718.rst +++ b/peps/pep-0718.rst @@ -234,10 +234,10 @@ Explicit specialisation will restrict the set of available overloads 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 +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 From bd36a628253920ab7892f2bedccab512ba43ba22 Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Wed, 8 Oct 2025 16:52:39 +0100 Subject: [PATCH 3/4] Fix title too short --- peps/pep-0718.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0718.rst b/peps/pep-0718.rst index d75bdb6ecc8..6d09ebdc5dc 100644 --- a/peps/pep-0718.rst +++ b/peps/pep-0718.rst @@ -235,7 +235,7 @@ Explicit specialisation will restrict the set of available overloads 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 From 1ba67e9605ebbdfa5793497e1d9c51eb911ee741 Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Wed, 8 Oct 2025 21:14:08 +0100 Subject: [PATCH 4/4] fix some grammar typos and build --- peps/pep-0718.rst | 44 ++++++++++++-------------------------------- 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/peps/pep-0718.rst b/peps/pep-0718.rst index 6d09ebdc5dc..2fef8a22397 100644 --- a/peps/pep-0718.rst +++ b/peps/pep-0718.rst @@ -201,28 +201,9 @@ 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. 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 +Overloaded functions should work much the same as they already do, since they do not +affect the runtime type. Explicit specialisation will restrict the set of available +overloads. .. code-block:: python @@ -232,33 +213,32 @@ Explicit specialisation will restrict the set of available overloads 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 + 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 +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 similar functions to be subscripted, for the same reason as -defined in :pep:`PEP 646<646#multiple-type-variable-tuples-not-allowed>`. +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 ^^^^^^^^^^^^^ -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. +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