-
Notifications
You must be signed in to change notification settings - Fork 216
Description
The type type[Any] is exactly equivalent to type & Any (or type[object] & Any). Conceptually, these are all equivalent spellings of "a type of unknown size and bounds, but which is known to be no larger than the type type1". By the same token, type[Unknown] is equivalent to type & Unknown; type[@Todo("do the thing")] is equivalent to type & @Todo("do the thing").
We currently represent type[Any] and type & Any using different internal representations in red-knot. We should fix this: equivalent types should have the same internal representation in our model. This helps avoid unnecessary overhead, and also reduces the internal complexity in our model.
Of the two representations, the type & Any representation is the better one for us internally, because it's a more general way of representing the type and will allow us to get rid of more complexity in our internal model. However, when displaying the type to users (for example, in the output of reveal_type), we should continue to use the notation type[Any], or we'll end up with highly confusing outcomes like this:
from typing import Any
def f(x: type[Any]):
reveal_type(x) # type & Any. User is now very confused.Implementing this will require some special-casing in Type::display(). We'll want to make sure that the special-casing is also able to understand that type & Any & T should be represented as type[Any] & T when displayed to the user.
Footnotes
-
The type
type, of course, describes "All possible instances of the classtype". It is exactly equivalent to the typetype[object], which describes "All possible subclasses of the classobject". ↩