To follow up on Pyre's behavior across these examples: 

I was actually surprised to see that Pyre throws an error on the first example, `x: Union[int, str] = 42`. I believe this is a bug and we'd like to change this to be consistent with the second example. 

Like Jake was saying about Pyright’s behavior, Pyre is keeping around both types and erroring against `Union[int, str]` when an assignment happens, but using the provably narrower type when evaluating things like returns.

 

Pyre is consistent about this with `Any`, but I think the suggestion is reasonable that we special-case and stop this behavior here. Intention would be to support use of  `Any` as an escape hatch like type-ignore, to deliberately fudge over even a provably bad type when it’s assigned/annotated, and when it’s used.

 

 

From: Rebecca Chen via Typing-sig <typing-sig@python.org>
Reply-To: Rebecca Chen <rechen@google.com>
Date: Wednesday, September 2, 2020 at 11:55 AM
To: Guido van Rossum <guido@python.org>, "typing-sig@python.org" <typing-sig@python.org>
Subject: [Typing-sig] Re: Unions and initialization across type checkers

 

For the last case,

 

x: Any

x = 42

 

pytype isn't narrowing; it's ignoring the `x: Any` annotation due to a bug. (Inside functions, pytype ignores variable annotations without initial values...) pytype's current, non-buggy behavior is to treat `x: Any = 42` and `x: Any; x = 42` the same. We actually special-cased Any to prevent narrowing, so that users could annotate variables as Any to essentially disable inference in cases in which pytype was doing something questionable.

 

The first two recommendations seem reasonable to me.

 

Best,

Rebecca

 

On Wed, Sep 2, 2020 at 11:27 AM Guido van Rossum <guido@python.org> wrote:

Consider these two similar functions:

```

from typing import Union

def f() -> int:
    x: Union[int, str] = 42
    return x  # Error here

def g() -> int:
    x: Union[int, str]
    x = 42
    return x  # But not here

```

Quite a while ago (2016-2017) there was a long discussion about this in the mypy tracker: https://github.com/python/mypy/issues/2008

 

Not only is it surprising that these two functions are type-checked differently, there are differences across type checkers. I tried mypy, pytype, pyre and pyright. All of them consider the second function correct. But all except pyright produce a type error on the first function, something along the lines of

```

t.py:5: error: Incompatible return value type (got "Union[int, str]", expected "int")

```

(It's possible that there are configuration settings to change the behavior; I didn't look into this.)

 

I think it would be in everybody's interest if all type checkers agreed on this. I also think it's surprising to users that the two functions are treated differently. (But as the old mypy issue shows, not everybody agrees they should be treated the same either. :-)

 

There's another twist (note the return type is str here):

```

from typing import Any

 

def h() -> str:
    x: Any = 42
    return x

```

This is an error in pyre but not in mypy, pytype or pyright. And for good measure the other variant:

```

def i() -> str:
    x: Any
    x = 42
    return x

```

This is accepted by mypy and pyright, but an error to pyre and pytype.

 

To summarize, it seems the type of x will be as follows:

```

x: Union[int, str] = 42

# mypy: Union; pytype: Union; pyre: Union; pyright: int

# majority doesn't narrow

 

x: Union[int, str]

x = 42

# mypy: int; pytype: int; pyre: int; pyright: int

# everybody narrows

 

x: Any = 42

# mypy: Any; pytype: Any; pyre: int; pyright: Any

# majority doesn't narrow

 

x: Any

x = 42

# mypy: Any; pytype: int; pyre: int; pyright: Any

# even split

```

 

Looking at this, I'd say if we follow the majority, we would have to make the following changes:

 

- pyright should stop narrowing for `x: Union[..] = value`

- pyre should stop narrowing for `x: Any = value`

- mypy and pyright should start narrowing for `x: Any; x = value`

 

(The latter recommendation is debatable, since it's an even split, but I like it better if Union and Any are treated similarly in this case.)

 

Let the debate begin.

 

--

--Guido van Rossum (python.org/~guido)

Pronouns: he/him (why is my pronoun here?)

_______________________________________________
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