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

Skip to content

[ty] Normalize recursive protocol growth during cycle recovery#26246

Merged
charliermarsh merged 2 commits into
mainfrom
charlie/fix-nested-iterable-hang
Jun 23, 2026
Merged

[ty] Normalize recursive protocol growth during cycle recovery#26246
charliermarsh merged 2 commits into
mainfrom
charlie/fix-nested-iterable-hang

Conversation

@charliermarsh

Copy link
Copy Markdown
Member

Summary

A loop-carried value can grow through a protocol specialization on every fixed-point iteration:

while 1:
    x = iter([[None] + [x]])

Prior to this change, we repeatedly inferred a deeper Iterator[...] specialization. The existing recursive-growth recovery only recognized NominalInstance, while iter returns a class-backed ProtocolInstance, so inference never converged.

This converts class-backed protocol instances to their nominal representation when comparing cycle iterations, allowing the existing wrapper replacement and Divergent normalization to converge. Synthesized protocols remain excluded from this path.

Closes astral-sh/ty#3827.

@astral-sh-bot astral-sh-bot Bot added the ty Multi-file analysis & type inference label Jun 22, 2026
@charliermarsh charliermarsh added the bug Something isn't working label Jun 22, 2026
@charliermarsh charliermarsh marked this pull request as ready for review June 22, 2026 20:19
@charliermarsh charliermarsh requested a review from a team as a code owner June 22, 2026 20:19
@astral-sh-bot astral-sh-bot Bot requested a review from carljm June 22, 2026 20:19
@astral-sh-bot

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

@astral-sh-bot

astral-sh-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown

Memory usage report

Memory usage unchanged ✅

@astral-sh-bot

astral-sh-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown

ecosystem-analyzer results

No diagnostic changes detected ✅

Flaky changes detected. This PR summary excludes flaky changes; see the HTML report for details.

Full report with detailed diff (timing results)

@carljm carljm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks!

Comment thread crates/ty_python_semantic/src/types.rs Outdated
Comment on lines +1301 to +1302
current.to_nominal_instance()?,
previous.to_nominal_instance()?,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it's somewhat subtle here that we unwrap to nominal instance types for the normalization, but then the normalization (if it occurs) reconstructs the type with Type::instance(...), which will recognize a protocol type. Might be worth a comment to explain what's going on here?

Comment on lines 1219 to 1225
/// Normalizes nominal growth that wraps the previous cycle result in one or more
/// specializations, either directly or beneath an unambiguous union wrapper.
///
/// For example, an inference cycle can otherwise grow indefinitely as
/// `C[int]`, `C[C[int]]`, `C[C[C[int]]]`, and so on. Once fixed-point iteration has passed its
/// tainted cycles, replace the recursive type argument with the cycle's `Divergent` marker so
/// that the existing recursive-type normalization can converge on `C[Divergent]`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This docstring should probably mention the behavior with class-backed protocol types?


```py
while 1:
x = iter([[None] + [x]]) # error: [possibly-unresolved-reference]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A reveal_type(x) here showing Iterator[Divergent] wouldn't hurt.

@charliermarsh charliermarsh force-pushed the charlie/fix-nested-iterable-hang branch from d694fd2 to db6ed39 Compare June 22, 2026 23:55
@charliermarsh charliermarsh enabled auto-merge (squash) June 22, 2026 23:55
@charliermarsh charliermarsh merged commit 06cb4ee into main Jun 23, 2026
60 checks passed
@charliermarsh charliermarsh deleted the charlie/fix-nested-iterable-hang branch June 23, 2026 00:00
charliermarsh added a commit that referenced this pull request Jun 24, 2026
Revert #26163 and the follow-up recovery and fallout fixes in #26230, #26246, #26274, #26275, and #26316.
charliermarsh added a commit that referenced this pull request Jun 24, 2026
Revert #26163 and the follow-up recovery and fallout fixes in #26230, #26246, #26274, #26275, and #26316.
charliermarsh added a commit that referenced this pull request Jun 24, 2026
## Summary

This reverts #26163 and its follow-up changes in #26230, #26246, #26274,
#26275, and #26316.

The recursive nominal-growth recovery replaces a previous cycle result
nested inside a specialization with `Divergent`. The follow-up
regressions show that this local replacement is not structurally safe:
multi-arm union recovery can lose stable arms, and variadic tuple growth
can continue after replacement. Addressing those cases required
increasingly shape-specific alignment and guards without a general way
to establish correspondence between fixed-point iterations.

This restores the cycle-recovery behavior from before #26163. The direct
self-referential `TypeOf` case and the regression coverage for
astral-sh/ty#3835 and astral-sh/ty#3838 continue to pass without the
heuristic and are retained. We remove only the cases that no longer
converge: `TypeOf` references nested in nominal specializations and the
nested-iterable case from astral-sh/ty#3827. The independent `Divergent`
constraint fixes from #26288 and #26334, including the regression
coverage for astral-sh/ty#3836, are also retained.
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.

hang on nested iterable types

2 participants