diff --git a/peps/pep-0747.rst b/peps/pep-0747.rst index 08fd44ae52b..e4ce2a0ee65 100644 --- a/peps/pep-0747.rst +++ b/peps/pep-0747.rst @@ -243,10 +243,16 @@ be assignable to ``TypeForm``:: v5: TypeForm[set[str]] = "set[str]" # OK +The typing spec defines syntactic rules for type expressions in the form of a +:ref:`formal grammar `. Semantic rules are specified +as comments along with the grammar definition. Contextual requirements are detailed +throughout the typing spec in sections that discuss concepts that appear within +type expressions. For example, the special form ``Self`` can be used in a +type expression only within a class, and a type variable can be used within +a type expression only when it is associated with a valid scope. + Expressions that violate one or more of the syntactic, semantic, or contextual -rules for type expressions should not evaluate to a ``TypeForm`` type. The rules -for type expression validity are explained in detail within the typing spec, so -they are not repeated here:: +rules for type expressions should not evaluate to a ``TypeForm`` type.:: bad1: TypeForm = tuple() # Error: Call expression not allowed in type expression bad2: TypeForm = (1, 2) # Error: Tuple expression not allowed in type expression @@ -300,14 +306,6 @@ Assignability t1: TypeForm[int | str] = get_type_form() # OK t2: TypeForm[str] = get_type_form() # Error -``type[T]`` is a subtype of ``TypeForm[T]``, which means that ``type[B]`` is -assignable to ``TypeForm[A]`` if ``B`` is assignable to ``A``:: - - def get_type() -> type[int]: ... - - t3: TypeForm[int | str] = get_type() # OK - t4: TypeForm[str] = get_type() # Error - ``TypeForm`` is a subtype of ``object`` and is assumed to have all of the attributes and methods of ``object``. @@ -532,6 +530,35 @@ of ``type``. .. _designed: https://mail.python.org/archives/list/typing-sig@python.org/message/D5FHORQVPHX3BHUDGF3A3TBZURBXLPHD/ +Treat ``type[T]`` as a subtype of ``TypeForm[T]`` +------------------------------------------------- + +It was suggested that type ``type[T]`` should be considered a subtype +of ``TypeForm[T]``. This was ultimately rejected because there are ways to +create an object of type ``type[T]`` that does not encode a valid type expression. +For example, the expression ``type[1]`` is not a valid type expression. Likewise, +the expression ``type[S]`` is not a valid type expression if ``S`` is an +out-of-scope type variable. This same argument applies to other special forms +like objects of type ``UnionType``, which may or may not encode a valid type +expression. Rather than carving out a special case for ``type[T]`` that would +allow for potential unsoundness, it was decided to treat all type forms +consistently. Therefore, ``type[T]`` is not considered a subtype of ``TypeForm[T]``. + +It was also pointed out that the expression ``C | C`` (where ``C`` is a class +object) is a valid type expression - and therefore a valid ``TypeForm``, +but its runtime type form encoding is an instance of ``UnionType`` and +therefore is not compatible with ``type[C]``. + +If a function wishes to indicate that it accepts values of type ``TypeForm[T]`` +_and_ ``type[T]``, the parameter can simply be annotated with a union of these +two types. + +:: + + def func[T](t: TypeForm[T] | type[T]) -> None: ... + + + Accept arbitrary annotation expressions --------------------------------------- @@ -547,7 +574,7 @@ not as a parameter type or a return type: def foo(not_reassignable: Final[object]): ... # Error: Final not allowed here - def nonsense() -> Final[object]: ... # Error: Final not alowed here + def nonsense() -> Final[object]: ... # Error: Final not allowed here With the exception of ``Annotated``, type qualifiers are not allowed in type expressions. ``TypeForm`` is limited to type expressions because its