From my recent efforts to clean up incorrect TypeVar usages in the Google codebase, I've discovered that users already find many creative ways to misunderstand and misuse TypeVar. Echoing Sebastian's earlier point, I think it would be a bad idea to reuse TypeVar to also mean AnyOf, since that would contradict the current state of a TypeVar being meaningful only when it appears multiple times in a definition and likely cause even more confusion.

Re: Richard's observation about pytype and unsafe unions: yes, we had them for practical reasons, and yes, we've been making things stricter ever since because of reports of missed bugs and surprising behavior.

Best,
Rebecca

On Tue, Sep 22, 2020 at 12:30 AM Eric Traut <eric@traut.com> wrote:
I see some value in adding an "AnyOf" construct for return types, but a type checker won't be able to do much with this information because (as others have pointed out), it would be unsafe to make many assumptions about the type. The most significant benefit is that language servers could provide completion suggestions — something developers would definitely appreciate.

That said, I don't think we need to introduce a new "AnyOf" type. As Zac pointed out, there's already a construct in the Python type system that has the desired properties of "AnyOf". Rather than invent a new construct, I'd prefer to leverage the constrained TypeVar.

Adding support for a new "AnyOf" type would likely be a lot of work in Pyright, but leveraging constrained TypeVars would be nearly free. In fact, it mostly works already, and I was able to implement completion suggestions and type narrowing with just a few additional lines of code. I'm guessing this it would be easy for most existing type checkers to add this support.

Mypy might require some small changes because it appears to use the first type in a constrained TypeVar rather than retaining the full list of constraints. I'm assuming that's not the intended behavior and is just a bug.

Zac said:
> I don't believe you can currently have a return typevar without an argument typevar...

I don't see anything in PEP 484 that states that a TypeVar used within a return type annotation must also appear in a parameter type annotation. Mypy doesn't appear to enforce this either, nor does the "stubtest" CI test for typeshed. There are legitimate uses for this. Here's an example:

```python
def my_decorator(timeout: float) -> Callable[[_T], _T]: ...
```

Building on Zac's example, here's how this could work:

```python
from typing import TypeVar
from ipaddress import IPv4Address, IPv6Address

IPAddress = TypeVar("IPAddress", IPv4Address, IPv6Address)

def ip_address(s: str) -> IPAddress:
    if len(s.split('.')) == 4:
        return IPv4Address(s)
    else:
        return IPv6Address(s)

a = ip_address("1.2.3.4")
reveal_type(a)

if isinstance(a, IPv4Address):
    print("IPv4!")
    reveal_type(a)
else:
    print("IPv6!")
    reveal_type(a)
```

Pyright's output is:
```
Found 1 source file
  15:13 - info: Type of "a" is "IPAddress"
  19:17 - info: Type of "a" is "IPv4Address"
  22:17 - info: Type of "a" is "IPv6Address"
0 errors, 0 warnings, 3 infos
```

Mypy's output is:
```
test.py:9: error: Incompatible return value type (got "IPv4Address", expected "IPv6Address")
test.py:11: error: Incompatible return value type (got "IPv6Address", expected "IPv4Address")
test.py:15: note: Revealed type is 'ipaddress.IPv4Address*'
test.py:19: note: Revealed type is 'ipaddress.IPv4Address*'
Found 2 errors in 1 file (checked 1 source file)
```
(This looks like a bug. Perhaps someone from the mypy team could speak to how difficult a fix would be.)


(@Zac — You might be interested in the fact that I recently added support for recursive types in Pyright. https://devblogs.microsoft.com/python/pylance-introduces-five-new-features-that-enable-type-magic-for-python-developers/#1-support-for-recursive-type-aliases)

 -Eric

--
Eric Traut
Microsoft
_______________________________________________
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