Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[ty] Respect dict-compatible fallbacks in TypedDict unions#25242

Merged
charliermarsh merged 3 commits into
mainfrom
charlie/ty-3488-dict-compatible-fallback
May 20, 2026
Merged

[ty] Respect dict-compatible fallbacks in TypedDict unions#25242
charliermarsh merged 3 commits into
mainfrom
charlie/ty-3488-dict-compatible-fallback

Conversation

@charliermarsh

@charliermarsh charliermarsh commented May 19, 2026

Copy link
Copy Markdown
Member

Summary

Prior to this change, this snippet would produce a TypedDict-based missing-key diagnostic, because the RHS wasn't viewed as assignable to the Mapping[int, float] (since we were only gating on dict):

from typing import TypedDict, Mapping

class Foo(TypedDict):
    some: str
    name: str

mapping: Foo | Mapping[int, float] = {1: 5.2}

We now use speculative inference to determine whether the non-TypedDict union member T is a viable fallback type.

Closes astral-sh/ty#3488.

@astral-sh-bot astral-sh-bot Bot added the ty Multi-file analysis & type inference label May 19, 2026
@astral-sh-bot

astral-sh-bot Bot commented May 19, 2026

Copy link
Copy Markdown

Memory usage report

Memory usage unchanged ✅

@astral-sh-bot

astral-sh-bot Bot commented May 19, 2026

Copy link
Copy Markdown

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 89.36%. The percentage of expected errors that received a diagnostic held steady at 85.49%. The number of fully passing files held steady at 88/134.

@astral-sh-bot

astral-sh-bot Bot commented May 19, 2026

Copy link
Copy Markdown

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-key 0 4 0
missing-typed-dict-key 0 2 0
unused-type-ignore-comment 1 0 0
Total 1 6 0

Raw diff:

hydra-zen (https://github.com/mit-ll-responsible-ai/hydra-zen)
- tests/annotations/declarations.py:366:59 error[invalid-key] Unknown key "a" for TypedDict `EmptyDict`
- tests/annotations/declarations.py:366:72 error[invalid-key] Unknown key "a" for TypedDict `EmptyDict`
+ tests/annotations/declarations.py:405:32 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive

pandas-stubs (https://github.com/pandas-dev/pandas-stubs)
- tests/frame/test_frame.py:3293:34 error[missing-typed-dict-key] Missing required key 'formats' in TypedDict `_DTypeDict` constructor
- tests/frame/test_frame.py:3293:34 error[missing-typed-dict-key] Missing required key 'names' in TypedDict `_DTypeDict` constructor
- tests/frame/test_frame.py:3293:35 error[invalid-key] Unknown key "col1" for TypedDict `_DTypeDict`
- tests/frame/test_frame.py:3293:52 error[invalid-key] Unknown key "col2" for TypedDict `_DTypeDict`

Full report with detailed diff (timing results)

@charliermarsh charliermarsh force-pushed the charlie/ty-3488-dict-compatible-fallback branch from 6f2963f to 180889c Compare May 19, 2026 15:19
Base automatically changed from charlie/ty-3488-aliased-dict-fallback to main May 19, 2026 18:58
@charliermarsh charliermarsh changed the title [ty] Recognize dict-compatible TypedDict union fallbacks [ty] Respect dict-compatible fallbacks in TypedDict unions May 20, 2026
@charliermarsh charliermarsh force-pushed the charlie/ty-3488-dict-compatible-fallback branch from 180889c to 0920b3a Compare May 20, 2026 13:38
@charliermarsh charliermarsh added the bug Something isn't working label May 20, 2026
@charliermarsh charliermarsh marked this pull request as ready for review May 20, 2026 13:46
has_dict_compatible_fallback = true;
} else if !has_dict_compatible_fallback
&& dict_fallback.is_assignable_to(self.db(), element)
&& element.is_assignable_to(self.db(), mapping_fallback)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not clear to me why we're imposing the restriction here that the element needs to be assignable to Mapping[Unknown, Unknown] in order for it to be a valid dict-compatible fallback. On your branch, we still emit a false-positive error here (it's a false positive because dict[int, int] is a subtype of Iterable[int]):

from typing import TypedDict, Iterable

class Foo(TypedDict):
    x: int

def f(obj: Foo | Iterable[int]): ...

f({42: 42})

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm good catch.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is clearly an improvement but not sufficiently general, lemme think.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok, I think the speculative inference piece on its own is sufficient now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup!

@charliermarsh charliermarsh marked this pull request as draft May 20, 2026 14:44
@charliermarsh charliermarsh force-pushed the charlie/ty-3488-dict-compatible-fallback branch from 70ec716 to f9f3ae3 Compare May 20, 2026 14:45
@charliermarsh charliermarsh marked this pull request as ready for review May 20, 2026 14:58
@astral-sh-bot astral-sh-bot Bot requested a review from AlexWaygood May 20, 2026 14:58

@AlexWaygood AlexWaygood left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sweet

@charliermarsh charliermarsh merged commit 6b742aa into main May 20, 2026
60 checks passed
@charliermarsh charliermarsh deleted the charlie/ty-3488-dict-compatible-fallback branch May 20, 2026 15:51
thejchap pushed a commit to thejchap/ruff that referenced this pull request May 23, 2026
…sh#25242)

## Summary

Prior to this change, this snippet would produce a TypedDict-based
`missing-key` diagnostic, because the RHS wasn't viewed as assignable to
the `Mapping[int, float]` (since we were only gating on `dict`):

```py
from typing import TypedDict, Mapping

class Foo(TypedDict):
    some: str
    name: str

mapping: Foo | Mapping[int, float] = {1: 5.2}
```

We now use speculative inference to determine whether the non-TypedDict
union member `T` is a viable fallback type.

Closes astral-sh/ty#3488.
anishgirianish pushed a commit to anishgirianish/ruff that referenced this pull request May 28, 2026
…sh#25242)

## Summary

Prior to this change, this snippet would produce a TypedDict-based
`missing-key` diagnostic, because the RHS wasn't viewed as assignable to
the `Mapping[int, float]` (since we were only gating on `dict`):

```py
from typing import TypedDict, Mapping

class Foo(TypedDict):
    some: str
    name: str

mapping: Foo | Mapping[int, float] = {1: 5.2}
```

We now use speculative inference to determine whether the non-TypedDict
union member `T` is a viable fallback type.

Closes astral-sh/ty#3488.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect assignability with union involving TypedDict

3 participants