Skip to content
107 changes: 88 additions & 19 deletions pep-0677.rst
Original file line number Diff line number Diff line change
Expand Up @@ -635,24 +635,92 @@ callable types and ``=>`` for lambdas.
Runtime Behavior
----------------

Our tentative plan is that:
The new AST nodes need to evaluate to runtime types, and we have two goals for the
behavior of these runtime types:

- The ``__repr__`` will show an arrow syntax literal.
- We will provide a new API where the runtime data structure can be
accessed in the same manner as the AST data structure.
- We will ensure that we provide an API that is backward-compatible
with ``typing.Callable`` and ``typing.Concatenate``, specifically
the behavior of ``__args__`` and ``__parameters__``.
- They should expose a structured API as similar as possible to the AST where
the parameter and return types have descriptive names.
- They should also expose an API that is fully backward-compatible with
``typing.Callable``

Because these details are still under debate we are currently
maintaining `a separate doc
<https://docs.google.com/document/d/15nmTDA_39Lo-EULQQwdwYx_Q1IYX4dD5WPnHbFG71Lk/edit>`_
with details about the new builtins, the evaluation model, how to
provide both a backward-compatible and more structured API, and
possible alternatives to the current plan.
Evaluation and Structured API
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

We intend to create new builtin types to which the new AST nodes will
evaluate, exposing them in the ``types`` module.

The ``CallableType`` and ``AsyncCallableType`` AST nodes should evaluate
to ``types.CallableType`` and ``types.AsyncCallableType``. Each of these
should have fields:

- ``args`` containing an evaluated arguments list (see below)
- ``returns`` containing the evaluated return type

The arguments list AST nodes should evaluate as follows:
- ``AnyArguments`` evaluates to ``types.CallableAnyArguments``

- This type has no fields

- ``ArgumentsList`` evaluates to ``types.CallableARgumentsList``, having

- A field ``posonlyargs`` which will be a tuple of all parameter types.

- ``Concatenation`` evaluates to ``types.CallableConcatenation``, having

- A field ``posonlyargs`` which will be a tuple of the normal parameter types.
- A field ``param_spec`` which will be the final ``ParamSpec`` argument.

Backward-Compatible API
~~~~~~~~~~~~~~~~~~~~~~~

To get backward compatibility with the existing ``types.Callable`` API,
which relies on fields ``__args__`` and ``__parameters__``, we define them
as follows:

- For ``types.CallableType``:

- ``__args__`` should be the tuple result of appending the return type to the
result of fetching ``__args__`` on ``args`` (see below).
- ``__parameters__`` should be the result of concatenating ``__parameters__``
of the arguments list with ``__parameters__`` of the return type.

- ``types.AsyncCallableType`` should work the same, except that its return
value should automatically be wrapped in a ``typing.Awaitable`` when
evaluating ``__args__``.
- For ``types.CallableAnyAguments``:

- ``__args__`` should evaluate to ``(Ellipses,)``.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That seems inconsistent -- shouldn't it be (Ellipsis, <return type>)? (Also, it's spelled "Ellipsis".)

- ``__parameters__`` should evaluate to ``()``.

- For ``types.CallableArgumentsList``:

- ``__args__`` should evaluate to ``posonlyargs``.
- ``__parameters__`` should be the result of concatenating the
``__parameters__`` of each type in ``posonlyargs``.

- For ``types.CallableConcatenation``:

- ``__args__`` should be the tuple result of appending ``param_spec`` to
``posonlyargs``.
- ``__parameters__`` should be the result of concatinating the
``__parameters__`` of each type in ``posonlyargs``, and also.



Behavior of other methods
~~~~~~~~~~~~~~~~~~~~~~~~~

- The ``__eq__`` method should treat equivalent ``typing.Callable``
values as equal to values constructed using the builtin syntax.
- The ``__repr__`` method of ``types.CallableType`` and
``types.AsyncCallableType`` should produce a representation in arrow syntax.

- The argument list types should produce a placeholder for ``__repr__``
rather than a pretty tuple-like value because they cannot be evaluated
except inside of a full arrow type literal.
- But we can pretty-print them in their ``__str__`` method and use that
in the ``__repr__`` method of ``types.CallableType``.

Once the plan is finalized we will include a full specification of
runtime behavior in this section of the PEP.

Rejected Alternatives
=====================
Expand Down Expand Up @@ -1033,10 +1101,11 @@ Open Issues
Details of the Runtime API
--------------------------

Once we have finalized all details of the runtime behavior, we
will need to add a full specification of the behavior to the
`Runtime Behavior`_ section of this PEP as well as include that
behavior in our reference implementation.
We have attempted to provide a complete behavior specification in
the `Runtime Behavior`_ section of this PEP.

But there are probably more details that we will not realize we
need to define until we build a full reference implementation.

Optimizing ``SyntaxError`` messages
-----------------------------------
Expand Down