From 4f151e97773a0268d58491f9a73722e35d1a20ce Mon Sep 17 00:00:00 2001 From: Rebecca Chen Date: Wed, 7 Feb 2024 16:44:55 -0800 Subject: [PATCH] PEP 696: consolidate discussion of constraint solving in "Function Defaults" section, add new "Subtyping" section (#3648) * PEP 696: consolidate discussion of constraint solving. Consolidates discussion of usage of defaults in constraint solving in the "Function Defaults" section, to make it clear that this is experimental and unspecified. * PEP 696: Explicitly call out that defaults do not affect subtyping. --- peps/pep-0696.rst | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/peps/pep-0696.rst b/peps/pep-0696.rst index 4b0b22e1a..1b940562c 100644 --- a/peps/pep-0696.rst +++ b/peps/pep-0696.rst @@ -17,8 +17,7 @@ Abstract This PEP introduces the concept of type defaults for type parameters, including ``TypeVar``, ``ParamSpec``, and ``TypeVarTuple``, -which act as defaults for a type parameter when one is not specified or -the constraint solver isn't able to solve a type parameter to anything. +which act as defaults for type parameters for which no type is specified. Default type argument support is available in some popular languages such as C++, TypeScript, and Rust. A survey of type parameter syntax in @@ -182,8 +181,7 @@ or another in-scope ``TypeVarTuple`` (see `Scoping Rules`_). Using Another Type Parameter as ``default`` '''''''''''''''''''''''''''''''''''''''''''' -This allows for a value to be used again when the constraints solver -fails to solve a constraint for a type, or the type parameter to a +This allows for a value to be used again when the type parameter to a generic is missing but another type parameter is specified. To use another type parameter as a default the ``default`` and the @@ -373,11 +371,18 @@ subtype of one of the constraints. Function Defaults ''''''''''''''''' -We leave the semantics of type parameter defaults in generic functions -unspecified, as ensuring the ``default`` is returned in every code path -where the type parameter can go unsolved may be too hard to implement. -Type checkers are free to either disallow this case or experiment with -implementing support. +In generic functions, type checkers may use a type parameter's default when the +type parameter cannot be solved to anything. We leave the semantics of this +usage unspecified, as ensuring the ``default`` is returned in every code path +where the type parameter can go unsolved may be too hard to implement. Type +checkers are free to either disallow this case or experiment with implementing +support. + +:: + + T = TypeVar('T', default=int) + def func(x: int | set[T]) -> T: ... + reveal_type(func(0)) # a type checker may reveal T's default of int here Defaults following ``TypeVarTuple`` ''''''''''''''''''''''''''''''''''' @@ -413,6 +418,13 @@ for the ``ParamSpec`` and one for the ``TypeVarTuple``. Foo[int, str] # Ts = (int, str), P = [float, bool] Foo[int, str, [bytes]] # Ts = (int, str), P = [bytes] +Subtyping +''''''''' + +Type parameter defaults do not affect the subtyping rules for generic classes. +In particular, defaults can be ignored when considering whether a class is +compatible with a generic protocol. + ``TypeVarTuple``\ s as Defaults '''''''''''''''''''''''''''''''