Skip to content

Commit a33030f

Browse files
committed
hopefully final round of changes
1 parent fa23881 commit a33030f

File tree

1 file changed

+69
-3
lines changed

1 file changed

+69
-3
lines changed

peps/pep-0718.rst

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,75 @@ Interactions with ``@typing.overload``
202202
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
203203

204204
Overloaded functions should work much the same as already, since they have no effect on
205-
the runtime type. The only change is that more situations will be decidable and the
206-
behaviour/overload can be specified by the developer rather than leaving it to ordering
207-
of overloads/unions.
205+
the runtime type. This change will lead to more expressiveness with user's able to
206+
decide and the behaviour/overload can be specified by the developer rather than leaving
207+
it to ordering of overloads/unions.
208+
209+
.. code-block:: python
210+
211+
# N.B. `class bytes(Sequence[int]): ...` and `Foo` is a non-specified generic type
212+
@overload
213+
def seq_first[T: Sequence[int]](x: T) -> T: ...
214+
@overload
215+
def seq_first[T: bytes](x: T) -> Foo[T]: ...
216+
217+
@overload
218+
def bytes_first[T: bytes](x: T) -> Foo[T]: ...
219+
@overload
220+
def bytes_first[T: Sequence[int]](x: T) -> T: ...
221+
222+
reveal_type(seq_first(b"")) # type is bytes
223+
reveal_type(bytes_first(b"")) # type is Foo[bytes]
224+
225+
Explicit specialisation will restrict the set of available overloads
226+
227+
.. code-block:: python
228+
229+
@overload
230+
def make[T](x: T) -> T: ...
231+
@overload
232+
def make(x: str, y: str) -> tuple[int, int]: ...
233+
234+
reveal_type(make[int](1)) # type is int
235+
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
236+
237+
Functions Parameterized by ``TypeVarTuple``s
238+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
239+
Currently type checkers disallow the use of multiple ``TypeVarTuple``s in it's generic
240+
parameters, however it is currently valid to have a function as such
241+
242+
.. code-block:: python
243+
244+
def foo[*T, *U](bar: Bar[*T], baz: Baz[*U]): ...
245+
def spam[*T](bar: Bar[*T]): ...
246+
247+
This PEP does not allow similar functions to be subscripted, for the same reason as
248+
defined in :pep:`PEP 646<646#multiple-type-variable-tuples-not-allowed>`.
249+
250+
.. code-block:: python
251+
252+
foo[int, str, bool, complex](Bar(), Baz()) # Invalid: cannot determine which parameters are passed to *T and *U. Explicitly parameterise the instances individually
253+
spam[int, str, bool, complex](Bar()) # OK
254+
255+
256+
Binding Rules
257+
^^^^^^^^^^^^^
258+
Subscriptions on methods (including classmethods, staticmethods etc.) should only have
259+
access to their function's type parameters and not the enclosing class's. Subscription
260+
should follow the rules specified in :pep:`PEP 696<696#binding-rules>` methods should
261+
be bound on attribute access.
262+
263+
.. code-block:: python
264+
265+
class C[T]:
266+
def method[U](self, x: T, y: U): ...
267+
@classmethod
268+
def cls[U](cls, x: T, y: U): ...
269+
270+
C[int].method[str](0, "") # OK
271+
C[int].cls[str](0, "") # OK
272+
C.cls[int, str](0, "") # Invalid: too many type parameters
273+
C.cls[str](0, "") # OK, T is ideally bound to int here though this is open for type checkers to decide
208274
209275
Backwards Compatibility
210276
-----------------------

0 commit comments

Comments
 (0)