Skip to content

[ty] Improve type context support for __setitem__ dunder calls#23800

Merged
ibraheemdev merged 1 commit intomainfrom
ibraheem/setitem-dunder-tcx
Mar 10, 2026
Merged

[ty] Improve type context support for __setitem__ dunder calls#23800
ibraheemdev merged 1 commit intomainfrom
ibraheem/setitem-dunder-tcx

Conversation

@ibraheemdev
Copy link
Member

@ibraheemdev ibraheemdev commented Mar 8, 2026

Resolves astral-sh/ty#2986. I also ended up refactoring some things here, see astral-sh/ty#3001 for details.

@ibraheemdev ibraheemdev added the ty Multi-file analysis & type inference label Mar 8, 2026
@astral-sh-bot astral-sh-bot bot requested a review from oconnor663 March 8, 2026 00:59
@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 8, 2026

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 85.05%. The percentage of expected errors that received a diagnostic held steady at 78.05%. The number of fully passing files held steady at 63/132.

@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 8, 2026

mypy_primer results

Changes were detected when running on open source projects
pytest-robotframework (https://github.com/detachhead/pytest-robotframework)
- tests/fixtures/test_python/test_robot_modify_options_hook_listener_instance/conftest.py:29:27: error[invalid-assignment] Invalid assignment to key "listener" with declared type `list[str | Unknown]` on TypedDict `RobotOptions`: value of type `list[Foo]`
- Found 175 diagnostics
+ Found 174 diagnostics

discord.py (https://github.com/Rapptz/discord.py)
- discord/components.py:488:40: error[invalid-assignment] Invalid assignment to key "channel_types" with declared type `list[Literal[0, 1, 2, 3, 4, ... omitted 8 literals]]` on TypedDict `SelectMenu`: value of type `list[int]`
- Found 558 diagnostics
+ Found 557 diagnostics

meson (https://github.com/mesonbuild/meson)
- mesonbuild/interpreter/interpreter.py:3501:33: error[invalid-assignment] Invalid assignment to key "extra_files" with declared type `list[File | str]` on TypedDict `Executable`: value of type `list[File]`
- mesonbuild/interpreter/interpreter.py:3501:33: error[invalid-assignment] Invalid assignment to key "extra_files" with declared type `list[File | str]` on TypedDict `StaticLibrary`: value of type `list[File]`
- mesonbuild/interpreter/interpreter.py:3501:33: error[invalid-assignment] Invalid assignment to key "extra_files" with declared type `list[File | str]` on TypedDict `SharedLibrary`: value of type `list[File]`
- mesonbuild/interpreter/interpreter.py:3501:33: error[invalid-assignment] Invalid assignment to key "extra_files" with declared type `list[File | str]` on TypedDict `Jar`: value of type `list[File]`
- mesonbuild/modules/rust.py:385:31: error[invalid-assignment] Invalid assignment to key "args" with declared type `list[str | File | Target | ExternalProgram]` on TypedDict `FuncTest`: value of type `list[str]`
- Found 2363 diagnostics
+ Found 2358 diagnostics

scikit-learn (https://github.com/scikit-learn/scikit-learn)
- sklearn/utils/tests/test_estimator_checks.py:1590:5: error[invalid-assignment] Invalid subscript assignment with key of type `Literal["contamination"]` and value of type `list[Interval]` on object of type `dict[str, list[StrOptions]]`
+ sklearn/utils/tests/test_estimator_checks.py:1590:5: error[invalid-assignment] Invalid subscript assignment with key of type `Literal["contamination"]` and value of type `list[StrOptions | Interval]` on object of type `dict[str, list[StrOptions]]`
- sklearn/utils/tests/test_estimator_checks.py:1605:9: error[invalid-assignment] Invalid subscript assignment with key of type `Literal["contamination"]` and value of type `list[Interval]` on object of type `dict[str, list[StrOptions]]`
+ sklearn/utils/tests/test_estimator_checks.py:1605:9: error[invalid-assignment] Invalid subscript assignment with key of type `Literal["contamination"]` and value of type `list[StrOptions | Interval]` on object of type `dict[str, list[StrOptions]]`

core (https://github.com/home-assistant/core)
- homeassistant/components/mqtt/debug_info.py:64:13: error[invalid-assignment] Invalid subscript assignment with key of type `str` and value of type `dict[str, int | deque[Unknown]]` on object of type `dict[str, SubscriptionDebugInfo]`
- homeassistant/components/mqtt/debug_info.py:120:5: error[invalid-assignment] Invalid subscript assignment with key of type `tuple[str, str]` and value of type `dict[str, str | dict[str, Any]]` on object of type `dict[tuple[str, str], TriggerDebugInfo]`
- homeassistant/components/mqtt/discovery.py:544:13: error[invalid-assignment] Invalid subscript assignment with key of type `tuple[str, str]` and value of type `dict[str, (() -> None) | deque[Unknown]]` on object of type `dict[tuple[str, str], PendingDiscovered]`
- Found 12073 diagnostics
+ Found 12070 diagnostics

@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 8, 2026

Memory usage report

Summary

Project Old New Diff Outcome
flake8 47.91MB 47.92MB +0.02% (10.40kB)
sphinx 265.37MB 265.36MB -0.00% (5.28kB) ⬇️
trio 117.86MB 117.85MB -0.01% (14.37kB) ⬇️
prefect 700.82MB 700.81MB -0.00% (16.23kB) ⬇️

Significant changes

Click to expand detailed breakdown

flake8

Name Old New Diff Outcome
infer_expression_types_impl 1.06MB 1.07MB +1.00% (10.88kB)
ExpressionWithContext 14.84kB 15.47kB +4.21% (640.00B)
infer_definition_types 1.87MB 1.87MB -0.02% (480.00B)
IntersectionType<'db>::from_two_elements_::interned_arguments 21.23kB 20.88kB -1.62% (352.00B)
IntersectionType<'db>::from_two_elements_ 19.81kB 19.57kB -1.22% (248.00B)
infer_scope_types_impl 1004.35kB 1004.30kB -0.00% (48.00B)

sphinx

Name Old New Diff Outcome
infer_expression_types_impl 21.50MB 21.54MB +0.17% (37.15kB) ⬇️
infer_definition_types 24.05MB 24.03MB -0.07% (18.21kB) ⬇️
ExpressionWithContext 179.84kB 184.92kB +2.82% (5.08kB) ⬇️
IntersectionType<'db>::from_two_elements_ 210.29kB 205.75kB -2.16% (4.54kB) ⬇️
infer_expression_type_impl 3.25MB 3.24MB -0.12% (4.01kB) ⬇️
IntersectionType<'db>::from_two_elements_::interned_arguments 179.09kB 175.23kB -2.16% (3.87kB) ⬇️
IntersectionType 895.45kB 893.14kB -0.26% (2.30kB) ⬇️
loop_header_reachability 391.20kB 389.52kB -0.43% (1.69kB) ⬇️
all_narrowing_constraints_for_expression 2.36MB 2.36MB -0.07% (1.64kB) ⬇️
Type<'db>::apply_specialization_ 1.65MB 1.65MB -0.08% (1.39kB) ⬇️
Type<'db>::apply_specialization_::interned_arguments 1.45MB 1.44MB -0.09% (1.33kB) ⬇️
all_negative_narrowing_constraints_for_expression 1.02MB 1.02MB -0.11% (1.10kB) ⬇️
infer_scope_types_impl 15.59MB 15.59MB -0.01% (1.08kB) ⬇️
is_redundant_with_impl::interned_arguments 2.07MB 2.07MB -0.05% (1.03kB) ⬇️
FunctionType 3.12MB 3.12MB -0.03% (1016.00B) ⬇️
... 14 more

trio

Name Old New Diff Outcome
infer_definition_types 7.59MB 7.58MB -0.09% (7.27kB) ⬇️
infer_expression_type_impl 1.44MB 1.43MB -0.15% (2.25kB) ⬇️
IntersectionType<'db>::from_two_elements_ 67.32kB 65.16kB -3.21% (2.16kB) ⬇️
IntersectionType<'db>::from_two_elements_::interned_arguments 62.05kB 60.59kB -2.35% (1.46kB) ⬇️
loop_header_reachability 140.25kB 138.86kB -0.99% (1.38kB) ⬇️
infer_expression_types_impl 7.06MB 7.06MB +0.02% (1.23kB) ⬇️
all_narrowing_constraints_for_expression 605.86kB 604.97kB -0.15% (912.00B) ⬇️
ExpressionWithContext 36.17kB 37.03kB +2.38% (880.00B) ⬇️
IntersectionType 231.30kB 230.88kB -0.18% (432.00B) ⬇️
is_redundant_with_impl::interned_arguments 544.59kB 544.41kB -0.03% (176.00B) ⬇️
all_negative_narrowing_constraints_for_expression 186.14kB 185.98kB -0.09% (168.00B) ⬇️
is_redundant_with_impl 481.92kB 481.83kB -0.02% (96.00B) ⬇️
Type<'db>::apply_specialization_::interned_arguments 645.55kB 645.47kB -0.01% (80.00B) ⬇️
Type<'db>::apply_specialization_ 737.50kB 737.43kB -0.01% (80.00B) ⬇️
infer_unpack_types 148.08kB 148.04kB -0.03% (48.00B) ⬇️

prefect

Name Old New Diff Outcome
infer_expression_types_impl 60.32MB 60.34MB +0.03% (19.89kB) ⬇️
infer_definition_types 88.32MB 88.31MB -0.02% (14.20kB) ⬇️
ExpressionWithContext 319.92kB 330.08kB +3.17% (10.16kB) ⬇️
infer_expression_type_impl 14.33MB 14.32MB -0.07% (9.73kB) ⬇️
all_narrowing_constraints_for_expression 6.95MB 6.95MB -0.04% (2.88kB) ⬇️
Type<'db>::apply_specialization_::interned_arguments 2.85MB 2.85MB -0.09% (2.73kB) ⬇️
loop_header_reachability 443.03kB 440.43kB -0.59% (2.60kB) ⬇️
Type<'db>::apply_specialization_ 3.56MB 3.56MB -0.06% (2.09kB) ⬇️
all_negative_narrowing_constraints_for_expression 2.59MB 2.59MB -0.06% (1.64kB) ⬇️
FunctionType 8.43MB 8.43MB -0.02% (1.63kB) ⬇️
IntersectionType<'db>::from_two_elements_::interned_arguments 348.82kB 347.19kB -0.47% (1.63kB) ⬇️
IntersectionType<'db>::from_two_elements_ 343.66kB 342.59kB -0.31% (1.07kB) ⬇️
Type<'db>::class_member_with_policy_ 17.18MB 17.18MB -0.01% (1.04kB) ⬇️
Type<'db>::try_call_dunder_get_ 10.41MB 10.41MB -0.01% (1.04kB) ⬇️
FunctionType<'db>::signature_ 3.86MB 3.86MB -0.03% (1.02kB) ⬇️
... 11 more

@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 8, 2026

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-await 40 0 0
invalid-assignment 0 10 2
invalid-return-type 1 0 0
Total 41 10 2

Full report with detailed diff (timing results)

@charliermarsh
Copy link
Member

I'm happy to review this one.


// Perform the first attempt without type context, ignoring the inferred type.
infer_slice_ty(self, TypeContext::default());
infer_rhs_value(self, TypeContext::default());
Copy link
Member

Choose a reason for hiding this comment

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

Can you explain this piece?

Copy link
Member Author

Choose a reason for hiding this comment

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

I cleaned this up a bit, the basic idea is that we should only ever produce diagnostics for a given expression once, and so later multi-inference attempts silence diagnostics, and are only used for assignability checks.

@ibraheemdev ibraheemdev force-pushed the ibraheem/setitem-dunder-tcx branch from f58444a to b1bbf63 Compare March 9, 2026 18:13
@carljm carljm assigned charliermarsh and unassigned oconnor663 Mar 9, 2026
@carljm carljm removed their request for review March 9, 2026 18:14
@ibraheemdev ibraheemdev force-pushed the ibraheem/setitem-dunder-tcx branch from b1bbf63 to 9754f6a Compare March 9, 2026 18:21
);

if !valid && emit_diagnostic_and_short_circuit {
if valid || emit_diagnostic_and_short_circuit {
Copy link
Member Author

Choose a reason for hiding this comment

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

We previously weren't short-circuiting here if we found an assignable element, not sure why.

@ibraheemdev ibraheemdev merged commit 8d5d41c into main Mar 10, 2026
51 checks passed
@ibraheemdev ibraheemdev deleted the ibraheem/setitem-dunder-tcx branch March 10, 2026 01:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ecosystem-analyzer ty Multi-file analysis & type inference

Projects

None yet

3 participants