-
Notifications
You must be signed in to change notification settings - Fork 134
Open
Labels
narrowingrelated to flow-sensitive type narrowingrelated to flow-sensitive type narrowing
Description
Summary
We just closed #456, but there's one special case that needs more attention: isinstance(x, dict). The tricky part is that TypedDicts are instances of dict at runtime, but are not (generally) assignable to any materialization of dict[Any, Any]. (See the proposed spec change in python/typing#2072 for the details.)
Current behavior is as follows (playground):
from typing import TypedDict
class X(TypedDict):
a: int
def _(x: list | X):
if isinstance(x, dict):
reveal_type(x) # X & Top[dict[Unknown, Unknown]]
else:
reveal_type(x) # list[Unknown] | (X & ~Top[dict[Unknown, Unknown]])Mypy and pyright both infer X in the positive branch and list[Any] in the negative branch, which is what we'd want.
I know TypedDict support is still missing a lot of functionality, so things will change, but I see a few options:
- Make TypedDict types into subtypes of
Top[dict[Unknown, Unknown]]. That would make this sample work correctly, but it's technically wrong in that TypedDicts aren't materializations ofdict[Any, Any]. As such, it may cause issues with other possible use cases forTop[]. It would also allow some unsafe operations (https://github.com/JelleZijlstra/unsoundness/blob/main/examples/narrowing/isinstance_dict.py). - Change the spec so that TypedDict types are assignable to
dict[str, Any]. I think that's a defensible change, but it's not what the current spec says and I don't know if such a change would see a positive reception. - Add a new special form
ty_extensions.AnyTypedDict, with the semantics that any TypedDict type is a subtype ofAnyTypedDict. The only allowed operations onAnyTypedDictare those that are allowed on any TypedDict (so no.clear();.keys()returns an iterable ofstr;.values()an iterable ofobject; etc.).isinstance(x, dict)would narrow toAnyTypedDict | Top[dict[Unknown, Unknown]]. This is technically correct and would fix the soundness hole in https://github.com/JelleZijlstra/unsoundness/blob/main/examples/narrowing/isinstance_dict.py, but it would introduce a new user-visible concept.
Version
No response
Metadata
Metadata
Assignees
Labels
narrowingrelated to flow-sensitive type narrowingrelated to flow-sensitive type narrowing