Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion design-qs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Big (open?) questions

1.
Can we actually implement IsSubtype at runtime in a satisfactory way?
(PROBABLE DECISION: external library *and* restricted checking.)
(PROBABLE DECISION: external library *and* "full" best effort checking.)

- There is a lot that needs to happen, like protocols and variance
inference and callable subtyping (which might require matching
Expand Down
60 changes: 42 additions & 18 deletions pep.rst
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,14 @@ typing. The situation was substantially improved by the introducing of
``ParamSpec`` in :pep:`PEP 612 <612>`, but a number of patterns remain
unsupported:

* Adding/removing/modifying a keyword parameter
* Modifying a variable number of parameters -- XXX: check how well TypeVarTuple does this
* Adding/removing/modifying a keyword parameter
* Adding/removing/modifying a variable number of parameters. (Though
``TypeVarTuple`` is close to being able to support adding and
removing, if multiple unpackings were to be allowed, and Pyre
implemented a ``Map`` operator that allowed modifying multiple.)

This proposal will cover those cases.

XXX: Ehhhhhh the generic situation could be bad for some of it? For
partial certainly, I think, which otherwise we can almost do.

NumPy-style broadcasting
------------------------

Expand Down Expand Up @@ -534,11 +534,11 @@ proposing to add that as a notion, but we could.
Boolean operators
'''''''''''''''''

* ``IsSub[T, S]``: What we would **want** is that it returns a boolean
literal type indicating whether ``T`` is a subtype of ``S``.
To support runtime checking, we probably need something weaker.
* ``IsSub[T, S]``: Returns a boolean literal type indicating whether
``T`` is a subtype of ``S``.

TODO: Discuss this in detail.
(Actually, I suppose, whether ``S`` is "assignable to" ``T``. We can
certainly bikeshed on this name.)

* ``Matches[T, S]``:
Equivalent to ``IsSub[T, S] and IsSub[S, T]``.
Expand All @@ -560,10 +560,13 @@ Basic operators

Negative indexes work in the usual way.

N.B: *Unfortunately* ``Base`` must be a proper class, *not* a
protocol. So, for example, ``GetArg[Ty, Iterable, 0]]`` to get the
type of something iterable *won't* work. This is because we can't do
protocol checks at runtime in general. Special forms unfortunately
N.B: Runtime evaluation will only be able to support proper classes
as ``Base``, *not* protocols. So, for example, ``GetArg[Ty,
Iterable, 0]]`` to get the type of something iterable will need to
fail in a runtime evaluator. We should be able to allow it
statically though.

Special forms unfortunately
require some special handling: the arguments list of a ``Callable``
will be packed in a tuple, and a ``...`` will become
``SpecialFormEllipsis``.
Expand Down Expand Up @@ -1121,18 +1124,39 @@ Renounce all cares of runtime evaluation

This would have a lot of simplifying features.

We wouldn't need to worry about making ``IsSub`` be checkable at
runtime,

XXX

TODO: Expand

Support TypeScript style pattern matching in subtype checking
-------------------------------------------------------------

This would almost certainly only be possible if we also decide not to
care about runtime evaluation, as above.

Replace ``IsSub`` with something weaker than "assignable to" checking
---------------------------------------------------------------------

Full python typing assignability checking is not fully implementable
at runtime (in particular, even if all the typeshed types for the
stdlib were made available, checking against protocols will often not
be possible, because class attributes may be inferred and have no visible
presence at runtime).

As proposed, a runtime evaluator will need to be "best effort",
ideally with the contours of that effort well-documented.

An alternative approach would be to have a weaker predicate as the
core primitive.

One possibility would be a "sub-similarity" check: ``IsSubSimilar``
would do *simple* checking of the *head* of types, essentially,
without looking at type parameters. It would not work with protocols.
It would still lift over unions and would check literals.

We decided it probably was not a good idea to introduce a new notion
that is similar to but not the same as subtyping, and that would need
to either have a long and weird name like ``IsSubSimilar`` or a
misleading short one like ``IsSub``.

.. _less_syntax:


Expand Down