Wait, your problem is that the static checkers aren't smart enough? I thought that you were complaining about the dynamic checkers. I think it's unavoidable that they produce different results (see Carl Meyer's explanation). I'm okay with that. In the long run, static type checkers should probably become smarter. E.g. after x: Literal[1] y = x+1 we could infer that y's type is Literal[2]. (Maybe pyright already does this?) On Sat, Sep 18, 2021 at 10:35 AM Paul Bryan <pbryan@anode.ca> wrote:
Thanks for the clarifications. So casting is the solution to avoid this problem with static type checkers?
Switching back to Literals...
def f(x: Literal["A", "B", "C", 1, 2, 3]) -> None: if isinstance(x, int): g(cast(Literal[1, 2, 3], x)) else: ...
def g(x: Literal[1, 2, 3]) -> None: ...
On Sat, 2021-09-18 at 09:27 -0600, Carl Meyer wrote:
On Sat, Sep 18, 2021 at 9:13 AM Carl Meyer <carl@oddbird.net> wrote:
It is true that a Literal type will generally only be statically known when it originates from a Python literal expression. But this is just a specific case of the general limitations of static analysis: that statically-known types are a wider approximation of the actual runtime types.
To clarify this point: there are many other situations where the same symptom you observe (static type checking may fail where runtime checking would pass) can occur without the involvement of Literal types. Consider this example:
``` def f(x: object) -> None: g(x)
def g(x: int) -> None ...
f(1) ```
This code must fail static type checking because the call to g(x) is invalid since it passes an `object` where an `int` is required. The statically known type of `x` within `f` is only `object`, since call-sites of `f` will be allowed to pass any object. And yet in the specific case of the call `f(1)`, where the argument happens to be an integer, runtime type checking will be fine.
This is exactly analogous to the case you are describing, if we had instead `g(x: Literal[1]) -> None` and `f(x: int) -> None` -- this is statically a type error, because the static type check must consider that `x` could take on any value that is part of the type `int`, even though any given specific runtime call might check out fine, if `x` happens to in fact be `1` for that call.
Carl
_______________________________________________ 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: guido@python.org
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>