I like the `Callable[[T], T]` shorthand. pytype started supporting it because people were annotating decorator factories this way and getting confused when it didn't work, which matches my intuition that this is the "obvious" way of annotating such things, and it's a good user experience when the obvious things just work. I find the Protocol much less readable.

Best,
Rebecca

On Mon, Jun 1, 2020 at 7:39 PM Mark Mendoza <mendoza.mark.a@gmail.com> wrote:
I recently discovered that MyPy supports a generic callable type shorthand that Pyre does not, namely things of the form

```
from typing import Callable, TypeVar
T = TypeVar("T")
def produce_no_op_decorator() -> Callable[[T], T]:...
```

MyPy interprets this as being of type `Callable[[], Callable<T>[[T], T]]` (mod https://github.com/python/mypy/issues/3924), while Pyre interprets it as being of type `Callable<T>[[], Callable[[T], T]]`, which we reject as being invalid.

Pyre interprets all free type variables in a def or class as being in the scope of that define/class. MyPy also does this in most circumstances with Callable[[T], T], as both checkers have identical interpretations of

```
T = TypeVar("T")
def f(x: T) -> Callable[[T], T]: ... # def <T> (T) -> Callable[[T], T]
# and
def f(f: Callable[[T], T]) -> T: ... # def <T> (Callable[[T], T]) -> T
#and
def i() -> Tuple[Callable[[T], T], T]: ...  # def <T>  () -> Tuple[Callable[[T], T], T]: ...
# and
class Child(Base[Callable[[T], T]]): ... # class <T> Child(Base[Callable[[T], T]])
```

Pyre and MyPy only differ here in that MyPy introduces a unique special case that alters the behavior for free variables:
* inside a Callable type
* in the return type of a def
* not present in any parameter of the def
* not present anywhere else in the return type that isn't also inside of a Callable type.

I can definitely see how this special case is helpful in making definitions for decorator factories more compact, but for us the inconsistency of this behavior from a user's perspective outweighs the concision.

With all that being said, given that the semantics of this are unspecified in any PEPs, I think it's fine for there to be a divergence in interpretation here.  However, there are instances of this pattern in typeshed, which have been leading to strange behavior in Pyre.

Luckily, both MyPy and Pyre have a spelling of `produce_no_op_decorator` that they both agree on, and is mostly codified by a PEP:

```
from typing import Callable, TypeVar, Protocol
T = TypeVar("T")
class IdentityFunction(Protocol):
    def __call__(self, __x: T) -> T: ...
def produce_no_op_decorator() -> IdentityFunction...
```

What are people's thoughts on modifying typeshed (like in https://github.com/python/typeshed/pull/4045) to change these instances to the commonly accepted spelling?
_______________________________________________
Typing-sig mailing list -- typing-sig@python.org
To unsubscribe send an email to typing-sig-leave@python.org
https://mail.python.org/mailman3/lists/typing-sig.python.org/
Member address: rechen@google.com