ruff
f584b3d6 - [ty] Do not top-materialize (user) `TypeIs` return types (#26864)

Commit
93 days ago
[ty] Do not top-materialize (user) `TypeIs` return types (#26864) ## Summary We currently top-materialize `TypeIs` types to work around the fact that typeshed annotates some standard library functions like `isawaitable` with a gradual `TypeIs[Awaitable[Any]]` return type. This is problematic when taken verbatim, since that instructs us to intersect with a gradual `Awaitable[Any]` type instead of truly selecting *all* awaitables (`Awaitable[object]`). For example, narrowing `Item | Awaitable[Item]` with a final `Item` class using `isawaitable` would result in `Awaitable[Item] & Awaitable[Any] = Awaitable[Item & Any]`, instead of just `Awaitable[Item]`. However, the current behavior is problematic for user-defined `TypeIs` functions, since we don't respect their declared return type. Here, we fix this by patching typeshed while dropping the top-materialization. This leads to an unchanged behavior for standard-library functions like `isawaitable`, `iscallable`, etc, but respects users annotations for custom `TypeIs` functions: ```py def is_list(arg: object) -> TypeIs[list[Any]]: return isinstance(arg, list) def _(x: object): if is_list(x): reveal_type(x) # list[Any], previously: Top[list[Any]] ``` relates to https://github.com/astral-sh/ty/issues/3375 ## Ecosystem report Looks mostly good: Removed false positives, new unused ignore comment diagnostics Some expected problems, e.g. with this user-defined function in beartype, leading to unfortunate types like `((...) -> Unknown) & ~((...) -> Unknown)`, which are technically correct (and could maybe be simplified), but certainly unintended: ```py def is_callable_like(value: Any) -> TypeIs[Callable]: return callable(value) ``` ## Conformance results - One false positive removed, which is expected. - One new false positive, which looks like it's due to a generic solver gap. ## Test Plan Adapted tests
Author
Parents
Loading