On Thu, Mar 21, 2019 at 12:22 PM Michael Sullivan <sully@msully.net> wrote:
I was asked to write up some notes on what was discussed regarding aliases at the meetup the other week. Here is my best recollection of the salient points:

---

The pyre team wants a more syntatically distinguished way to declare type aliases, for typechecker performance reasons.


Was this only for pyre typechecker performance reasons or also for runtime Python module load time reasons, similar to from pep 563 __future__ import annotations delayed expression evaluation reasoning?

Łukasz Langa will be proposing (in a draft pep), syntax like `Foo: Alias[Bar]`. This has the advantages that (when using from __future__ import annotations) it needn't be executed and the names don't need to be imported at runtime. It has the disadvantage that such an alias can't be used in situations where a runtime type is actually required, such as using it as a base class (including as a type argument).
It is also (in my opinion, at least) uglier.

Another option brought up is `Foo = Alias[Bar]`. This can be implemented to allow using it as a base type, etc.

One hiccup in this planning is that the current type alias syntax is in PEP 484 and widely used. It could be deprecated, but I think it is unlikely that mypy will drop support it?

Indeed same for pytype, the = syntax is natural Python so it isn't going to go away.  All annotated code, including 2.7 code, is using natural = assignment today in lieu of any other option.

I think adopting a special syntax such as giving meaning to a PEP 526 Foo: Alias[Bar] format otherwise no-op-ish expression is likely to lead to confusion for readers of the code.  Today such an expression is declaring that Foo is _of_ type Alias[Bar].  Is it just the new term Alias that leads to a special interpretation?

If the goal is avoid the alias assignment hit on module load time (which I thought came in in that conversation?), the existing way to do this is easily understood by anyone reading the code, even if they haven't learned why it was done:

from __future__ import annotations
from typing import Alias, TYPE_CHECKING

if TYPE_CHECKING:
    Foo = Alias[Bar]

Another potential idea along those lines for checker performance would be to define an analyzer restriction that once a TYPE_CHECKING conditional is used in a file, all type alias assignments must happen within such a conditional in the remainder of the file. I _suspect_ that is already the case in code that has bothered to use the conditional today - some codebase analysis is warranted. When analyzing and such a conditional is found, it could avoid interpreting any assignments as types form then on.

One thing that adding an explicit syntax for declaring aliases will allow us to do is create syntax for declaring a generic type alias that does not use all its type variables, or that uses them in a different order than they appear in the aliased type.

mypy currently supports an undocumented version of this, "FlexibleAlias".
`Foo = FlexibleAlias[T, U, V, Bar]` creates a type alias Foo with type parameters T, U, and V and type Bar, regardless of which of those variables occur in Bar or in what order.

Currently we use this in mypy to allow changing certain types to Any under certain configuration flags:
T = TypeVar('T')
if MYPYC:
    Bogus = FlexibleAlias[T, Any]
else:
    Bogus = FlexibleAlias[T, T]

Could you expand on what you mean by this, it's not clear to me from this description what is going on here.

-gps