What does "set of potential runtime values" mean in the context of fully static types. #2112
-
|
According to the official python typing documentation "A fully static type denotes a set of potential runtime values.", which reads like being a definition or at least explanation. But what is meant by "potential runtime values"? Consider the following snippet: class A: pass
class B(A): pass
def list_consumer(list_of_a: list[A]) -> None:
list_of_a.append(A())
b = B()
l_a: list[A] = [b]
l_b: list[B] = [b]
l_inf = [b]
list_consumer(l_a)
list_consumer(l_b) # type error (pyright 1.1.406)
list_consumer(l_inf) # type error (pyright 1.1.406)(Note: I fully agree with the type checker. My question is: The tree variables As far as I understand, the static type information Do we consider the static type information associated to a variable to be part of the runtime value it holds even though the object that constitutes this value has no connection at all to the static type? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
|
Yes, this is a place where the "set of runtime values" definition becomes problematic. The way I think of it is that a generic conceptually carries around not only its value, but a "tag" representing its type argument, which is erased at runtime ("type erasure" is a well-known concept in some other languages). We might represent it with It follows that it is impossible to tell at runtime what the static type of a list object is, so any type narrowing (e.g., TypeIs) that purports to narrow the type of a list is inherently unsound. |
Beta Was this translation helpful? Give feedback.
Yes, this is a place where the "set of runtime values" definition becomes problematic. The way I think of it is that a generic conceptually carries around not only its value, but a "tag" representing its type argument, which is erased at runtime ("type erasure" is a well-known concept in some other languages). We might represent it with
<T>before the value. So your different[b]lists are to the type checker<A>[b](of typelist[A]) and<B>[b](of typelist[B]).It follows that it is impossible to tell at runtime what the static type of a list object is, so any type narrowing (e.g., TypeIs) that purports to narrow the type of a list is inherently unsound.