mirror of
https://github.com/astral-sh/ruff
synced 2026-01-21 21:40:51 -05:00
[ty] Add documentation for ty_extensions.Top and ty_extensions.Bottom (#22245)
Co-authored-by: Carl Meyer <carl@astral.sh>
This commit is contained in:
@@ -6924,6 +6924,86 @@ mod tests {
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hover_narrowed_type_with_top_materialization() {
|
||||
let mut test = inlay_hint_test(
|
||||
r#"
|
||||
def f(xyxy: object):
|
||||
if isinstance(xyxy, list):
|
||||
x = xyxy
|
||||
"#,
|
||||
);
|
||||
|
||||
assert_snapshot!(test.inlay_hints(), @r#"
|
||||
def f(xyxy: object):
|
||||
if isinstance(xyxy, list):
|
||||
x[: Top[list[Unknown]]] = xyxy
|
||||
|
||||
---------------------------------------------
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/ty_extensions.pyi:24:1
|
||||
|
|
||||
22 | CallableTypeOf: _SpecialForm
|
||||
23 |
|
||||
24 | Top: _SpecialForm
|
||||
| ^^^
|
||||
25 | """
|
||||
26 | `Top[T]` represents the "top materialization" of `T`.
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:4:13
|
||||
|
|
||||
2 | def f(xyxy: object):
|
||||
3 | if isinstance(xyxy, list):
|
||||
4 | x[: Top[list[Unknown]]] = xyxy
|
||||
| ^^^
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/builtins.pyi:2829:7
|
||||
|
|
||||
2828 | @disjoint_base
|
||||
2829 | class list(MutableSequence[_T]):
|
||||
| ^^^^
|
||||
2830 | """Built-in mutable sequence.
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:4:17
|
||||
|
|
||||
2 | def f(xyxy: object):
|
||||
3 | if isinstance(xyxy, list):
|
||||
4 | x[: Top[list[Unknown]]] = xyxy
|
||||
| ^^^^
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/ty_extensions.pyi:14:1
|
||||
|
|
||||
13 | # Types
|
||||
14 | Unknown = object()
|
||||
| ^^^^^^^
|
||||
15 | AlwaysTruthy = object()
|
||||
16 | AlwaysFalsy = object()
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:4:22
|
||||
|
|
||||
2 | def f(xyxy: object):
|
||||
3 | if isinstance(xyxy, list):
|
||||
4 | x[: Top[list[Unknown]]] = xyxy
|
||||
| ^^^^^^^
|
||||
|
|
||||
|
||||
---------------------------------------------
|
||||
info[inlay-hint-edit]: File after edits
|
||||
info: Source
|
||||
|
||||
def f(xyxy: object):
|
||||
if isinstance(xyxy, list):
|
||||
x: Top[list[Unknown]] = xyxy
|
||||
"#);
|
||||
}
|
||||
|
||||
struct InlayHintLocationDiagnostic {
|
||||
source: FileRange,
|
||||
target: FileRange,
|
||||
|
||||
@@ -20,12 +20,67 @@ Not: _SpecialForm
|
||||
Intersection: _SpecialForm
|
||||
TypeOf: _SpecialForm
|
||||
CallableTypeOf: _SpecialForm
|
||||
# Top[T] evaluates to the top materialization of T, a type that is a supertype
|
||||
# of every materialization of T.
|
||||
|
||||
Top: _SpecialForm
|
||||
# Bottom[T] evaluates to the bottom materialization of T, a type that is a subtype
|
||||
# of every materialization of T.
|
||||
"""
|
||||
`Top[T]` represents the "top materialization" of `T`.
|
||||
|
||||
For any type `T`, the top [materialization] of `T` is a type that is
|
||||
a supertype of all materializations of `T`.
|
||||
|
||||
For a [fully static] type `T`, `Top[T]` is always exactly the same type
|
||||
as `T` itself. For example, the top materialization of `Sequence[int]`
|
||||
is simply `Sequence[int]`.
|
||||
|
||||
For a [gradual type] `T` that contains [`Any`][Any] or `Unknown` inside
|
||||
it, however, `Top[T]` will not be equivalent to `T`. `Top[Sequence[Any]]`
|
||||
evaluates to `Sequence[object]`: since `Sequence` is covariant, no
|
||||
possible materialization of `Any` exists such that a fully static
|
||||
materialization of `Sequence[Any]` would not be a subtype of
|
||||
`Sequence[object]`.
|
||||
|
||||
`Top[T]` cannot be simplified further for invariant gradual types.
|
||||
`Top[list[Any]]` cannot be simplified to any other type: because `list`
|
||||
is invariant, `list[object]` is not a supertype of `list[int]`. The
|
||||
top materialization of `list[Any]` is simply `Top[list[Any]]`: the
|
||||
infinite union of `list[T]` for every possible fully static type `T`.
|
||||
|
||||
[materialization]: https://typing.python.org/en/latest/spec/concepts.html#materialization
|
||||
[fully static]: https://typing.python.org/en/latest/spec/concepts.html#fully-static-types
|
||||
[gradual type]: https://typing.python.org/en/latest/spec/concepts.html#gradual-types
|
||||
[Any]: https://typing.python.org/en/latest/spec/special-types.html#any
|
||||
"""
|
||||
|
||||
Bottom: _SpecialForm
|
||||
"""
|
||||
`Bottom[T]` represents the "bottom materialization" of `T`.
|
||||
|
||||
For any type `T`, the bottom [materialization] of `T` is a type that is
|
||||
a subtype of all materializations of `T`.
|
||||
|
||||
For a [fully static] type `T`, `Bottom[T]` is always exactly the same type
|
||||
as `T` itself. For example, the bottom materialization of `Sequence[int]`
|
||||
is simply `Sequence[int]`.
|
||||
|
||||
For a [gradual type] `T` that contains [`Any`][Any] or `Unknown` inside it,
|
||||
however, `Bottom[T]` will not be equivalent to `T`. `Bottom[Sequence[Any]]`
|
||||
evaluates to `Sequence[Never]`: since `Sequence` is covariant, no
|
||||
possible materialization of `Any` exists such that a fully static
|
||||
materialization of `Sequence[Any]` would not be a supertype of
|
||||
`Sequence[Never]`. (`Sequence[Never]` is not the same type as the
|
||||
uninhabited type `Never`: for example, it is inhabited by the empty tuple,
|
||||
`()`.)
|
||||
|
||||
For many invariant gradual types `T`, `Bottom[T]` is equivalent to
|
||||
[`Never`][Never], although ty will not necessarily apply this simplification
|
||||
eagerly.
|
||||
|
||||
[materialization]: https://typing.python.org/en/latest/spec/concepts.html#materialization
|
||||
[fully static]: https://typing.python.org/en/latest/spec/concepts.html#fully-static-types
|
||||
[gradual type]: https://typing.python.org/en/latest/spec/concepts.html#gradual-types
|
||||
[Never]: https://typing.python.org/en/latest/spec/special-types.html#never
|
||||
[Any]: https://typing.python.org/en/latest/spec/special-types.html#any
|
||||
"""
|
||||
|
||||
# ty treats annotations of `float` to mean `float | int`, and annotations of `complex`
|
||||
# to mean `complex | float | int`. This is to support a typing-system special case [1].
|
||||
|
||||
Reference in New Issue
Block a user