Skip to content

[ty] Preserve uncertain reflected operator dispatch#26474

Open
charliermarsh wants to merge 1 commit into
charlie/reflected-operator-runtime-classesfrom
charlie/reflected-operator-dispatch-soundness
Open

[ty] Preserve uncertain reflected operator dispatch#26474
charliermarsh wants to merge 1 commit into
charlie/reflected-operator-runtime-classesfrom
charlie/reflected-operator-dispatch-soundness

Conversation

@charliermarsh

Copy link
Copy Markdown
Member

Summary

This is a follow-up to #26434 that preserves both binary-operation dispatch results when static operand types do not determine their exact runtime classes.

For left: Base and right: Child, the runtime operands may be Base + Child, where Child.__radd__ has priority, or Child + Child, where Base.__add__ is called. We previously selected only the reflected result from the static subtype relationship.

This change classifies reflected priority as never, possible, or definite. Possible priority unions the normal and reflected call bindings; definite priority remains precise for exact left runtime classes such as the integer literal in 0 | Permission.READ. Bounded TypeVars and NewTypes use the same conservative distinction.

from typing import Literal

class Base:
    def __add__(self, other: object) -> Literal["base"]:
        return "base"

class Child(Base):
    def __radd__(self, other: object) -> Literal["child"]:
        return "child"

def add(left: Base, right: Child) -> Literal["base", "child"]:
    return left + right

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

astral-sh-bot Bot commented Jun 30, 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 94.47%. The percentage of expected errors that received a diagnostic held steady at 89.19%. The number of fully passing files held steady at 95/134.

@astral-sh-bot

astral-sh-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown

Memory usage report

Summary

Project Old New Diff Outcome
prefect 449.39MB 449.42MB +0.01% (27.69kB)
sphinx 167.03MB 167.05MB +0.01% (17.44kB)
trio 70.44MB 70.46MB +0.02% (16.73kB)
flake8 29.02MB 29.02MB +0.01% (2.21kB)

Significant changes

Click to expand detailed breakdown

prefect

Name Old New Diff Outcome
try_call_bin_op_return_type_impl 98.32kB 110.15kB +12.03% (11.83kB)
member_lookup_with_policy_inner 10.23MB 10.23MB +0.02% (2.37kB)
Type<'db>::class_member_with_policy_ 7.92MB 7.92MB +0.03% (2.36kB)
member_lookup_with_policy_inner::interned_arguments 6.74MB 6.74MB +0.03% (1.88kB)
is_redundant_with_impl::interned_arguments 2.35MB 2.36MB +0.07% (1.72kB)
Type<'db>::class_member_with_policy_::interned_arguments 5.74MB 5.74MB +0.03% (1.62kB)
UnionType 1.07MB 1.07MB +0.10% (1.09kB)
is_redundant_with_impl 1.31MB 1.31MB +0.07% (944.00B)
UnionType<'db>::from_two_elements_::interned_arguments 270.62kB 271.48kB +0.32% (880.00B)
infer_definition_types 50.03MB 50.04MB +0.00% (608.00B)
UnionType<'db>::from_two_elements_ 162.98kB 163.52kB +0.33% (552.00B)
IntersectionType 985.54kB 986.03kB +0.05% (504.00B)
OverloadLiteral 3.93MB 3.93MB +0.01% (448.00B)
place_by_id 4.78MB 4.78MB +0.01% (352.00B)
FunctionType 4.60MB 4.60MB +0.01% (320.00B)
... 4 more

sphinx

Name Old New Diff Outcome
try_call_bin_op_return_type_impl 79.13kB 84.37kB +6.61% (5.23kB)
Type<'db>::class_member_with_policy_ 3.60MB 3.60MB +0.05% (1.80kB)
member_lookup_with_policy_inner 4.29MB 4.29MB +0.04% (1.62kB)
is_redundant_with_impl::interned_arguments 1.14MB 1.14MB +0.13% (1.55kB)
member_lookup_with_policy_inner::interned_arguments 2.71MB 2.71MB +0.05% (1.52kB)
Type<'db>::class_member_with_policy_::interned_arguments 2.36MB 2.36MB +0.05% (1.32kB)
UnionType 583.61kB 584.59kB +0.17% (1008.00B)
is_redundant_with_impl 631.71kB 632.55kB +0.13% (864.00B)
UnionType<'db>::from_two_elements_::interned_arguments 174.80kB 175.57kB +0.44% (792.00B)
IntersectionType 534.62kB 535.28kB +0.12% (672.00B)
UnionType<'db>::from_two_elements_ 101.38kB 101.88kB +0.49% (504.00B)
place_by_id 1.33MB 1.33MB +0.03% (352.00B)
place_by_id::interned_arguments 1.03MB 1.03MB +0.03% (288.00B)
infer_scope_types_impl 8.10MB 8.10MB +0.00% (16.00B)

trio

Name Old New Diff Outcome
member_lookup_with_policy_inner 1.02MB 1.03MB +0.27% (2.81kB)
Type<'db>::class_member_with_policy_ 887.43kB 890.16kB +0.31% (2.73kB)
member_lookup_with_policy_inner::interned_arguments 764.77kB 766.99kB +0.29% (2.23kB)
Type<'db>::class_member_with_policy_::interned_arguments 625.62kB 627.55kB +0.31% (1.93kB)
try_call_bin_op_return_type_impl 17.91kB 19.08kB +6.54% (1.17kB)
StaticClassLiteral<'db>::try_mro_ 531.83kB 532.94kB +0.21% (1.11kB)
is_redundant_with_impl::interned_arguments 237.02kB 237.96kB +0.40% (968.00B)
UnionType 144.64kB 145.19kB +0.38% (560.00B)
is_redundant_with_impl 129.38kB 129.89kB +0.39% (520.00B)
IntersectionType 141.20kB 141.70kB +0.35% (504.00B)
Specialization 464.61kB 465.05kB +0.09% (448.00B)
UnionType<'db>::from_two_elements_::interned_arguments 29.48kB 29.91kB +1.46% (440.00B)
StaticClassLiteral<'db>::try_mro_::interned_arguments 182.11kB 182.46kB +0.19% (360.00B)
place_by_id 544.81kB 545.16kB +0.06% (352.00B)
place_by_id::interned_arguments 413.09kB 413.37kB +0.07% (288.00B)
... 7 more

flake8

Name Old New Diff Outcome
Type<'db>::class_member_with_policy_ 236.45kB 236.86kB +0.18% (424.00B)
member_lookup_with_policy_inner::interned_arguments 206.72kB 207.07kB +0.17% (360.00B)
member_lookup_with_policy_inner 292.78kB 293.11kB +0.11% (336.00B)
Type<'db>::class_member_with_policy_::interned_arguments 170.12kB 170.42kB +0.18% (312.00B)
is_redundant_with_impl::interned_arguments 89.63kB 89.80kB +0.19% (176.00B)
all_narrowing_constraints_for_expression 74.68kB 74.54kB -0.19% (144.00B)
try_call_bin_op_return_type_impl 2.45kB 2.57kB +4.78% (120.00B)
UnionType 57.66kB 57.77kB +0.19% (112.00B)
OverloadLiteral 120.72kB 120.83kB +0.09% (112.00B)
is_redundant_with_impl 51.77kB 51.86kB +0.18% (96.00B)
infer_definition_types 1001.91kB 1001.99kB +0.01% (88.00B)
UnionType<'db>::from_two_elements_::interned_arguments 10.23kB 10.31kB +0.84% (88.00B)
place_by_id 135.58kB 135.66kB +0.06% (88.00B)
infer_expression_types_impl 651.36kB 651.28kB -0.01% (80.00B)
FunctionType 228.81kB 228.89kB +0.03% (80.00B)
... 4 more

@charliermarsh charliermarsh force-pushed the charlie/reflected-operator-runtime-classes branch from 5def2ee to 6764cb1 Compare June 30, 2026 15:54
@charliermarsh charliermarsh force-pushed the charlie/reflected-operator-dispatch-soundness branch from 6f58caf to 1716dd9 Compare June 30, 2026 15:54
@charliermarsh charliermarsh requested a review from sharkdp June 30, 2026 16:11
@charliermarsh charliermarsh marked this pull request as ready for review June 30, 2026 16:11
@charliermarsh charliermarsh requested a review from a team as a code owner June 30, 2026 16:11
@AlexWaygood

Copy link
Copy Markdown
Member

Not sure why the bot hasn't posted here, but note that there is an ecosystem diff here https://github.com/astral-sh/ruff/actions/runs/28457717664/attempts/1#summary-84337686112

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants