Skip to content

[ty] Only treat recursive types with unbounded specializations as fallback cycles - #27538

Open
mtshiba wants to merge 11 commits into
mainfrom
recursive-type-may-diverge
Open

[ty] Only treat recursive types with unbounded specializations as fallback cycles#27538
mtshiba wants to merge 11 commits into
mainfrom
recursive-type-may-diverge

Conversation

@mtshiba

@mtshiba mtshiba commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes #26503 (comment)

Approach #26989 didn't work. This would be a more legitimate approach.

In #26503, regardless of what the recursive type was, if it appeared again with a different specialization during the visit of CycleDetector, there was a risk that the visit would not stop, so a Cycle state was returned immediately.

This is OK for the growing pattern, but misses the saturating pattern, as shown below.

type Growing[T] = T | Growing[list[T]]

type Saturating1[T, U] = T | Saturating1[U, T]
type Saturating2[T] = tuple[T] | tuple[T, Saturating2[int]]
type Saturating3[T] = tuple[T, Saturating3Helper[list[T]]]
type Saturating3Helper[U] = tuple[U, Saturating3[int]]

Think of this as a graph problem. The type parameter of each definition is used as a node, and the following edges are created from the type parameter of the recursive reference.

  • Direct: Type parameters are passed as is.
  • Nested: A type parameter is passed inside another type.
  • Edgeless if no type parameters appear

If there is even one nested edge in the directed cycle containing the root formal type argument, it is determined that the specialization can increase infinitely.

e.g.

type A[X, Y] = A[list[Y], X]
# A.Y -> A.X  Nested
# A.X -> A.Y  Direct
# => growing
type Left[A, B, C, D] = Left[B, C, D, None]
# Left.B -> Left.A  Direct
# Left.C -> Left.B  Direct
# Left.D -> Left.C  Direct
# => saturating
type A[X, Y] = A[list[Y], None]
# A.Y -> A.X  Nested
# => saturating (no cycle)

Test Plan

mdtest updated

@mtshiba mtshiba added the ty Multi-file analysis & type inference label Aug 6, 2026
@astral-sh-bot

astral-sh-bot Bot commented Aug 6, 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 96.96%. The percentage of expected errors that received a diagnostic held steady at 92.96%. The number of fully passing files held steady at 106/133.

@astral-sh-bot

astral-sh-bot Bot commented Aug 6, 2026

Copy link
Copy Markdown

Memory usage report

Summary

Project Old New Diff Outcome
sphinx 168.71MB 168.72MB +0.01% (11.16kB)
prefect 451.60MB 451.60MB +0.00% (456.00B)
flake8 40.31MB 40.31MB -
trio 93.47MB 93.47MB -0.00% (928.00B) ⬇️

Significant changes

Click to expand detailed breakdown

sphinx

Name Old New Diff Outcome
Type<'db>::cached_materialization_ 247.39kB 250.33kB +1.19% (2.94kB)
may_have_unbounded_specialization_inner 0.00B 2.31kB +2.31kB (new)
infer_expression_types_impl 11.42MB 11.42MB +0.02% (1.78kB)
may_have_unbounded_specialization_inner::interned_arguments 0.00B 1.75kB +1.75kB (new)
infer_definition_types 10.78MB 10.78MB +0.01% (1.20kB)
all_narrowing_constraints_for_expression 2.24MB 2.24MB +0.02% (392.00B)
is_redundant_with_impl 764.24kB 764.52kB +0.04% (288.00B)
infer_statement_types_impl 504.58kB 504.77kB +0.04% (192.00B)
infer_scope_types_impl 6.07MB 6.07MB +0.00% (112.00B)
StaticClassLiteral<'db>::try_mro_ 1.87MB 1.87MB +0.00% (64.00B)
infer_unpack_types 259.11kB 259.18kB +0.02% (64.00B)
analyze_non_terminal_call 454.88kB 454.94kB +0.01% (64.00B)
loop_header_reachability 243.32kB 243.35kB +0.01% (32.00B)
member_lookup_with_policy_inner 4.80MB 4.80MB +0.00% (8.00B)

prefect

Name Old New Diff Outcome
may_have_unbounded_specialization_inner::interned_arguments 0.00B 384.00B +384.00B (new)
may_have_unbounded_specialization_inner 0.00B 352.00B +352.00B (new)
Type<'db>::cached_materialization_ 1.03MB 1.03MB +0.02% (240.00B)
is_redundant_with_impl 3.35MB 3.35MB -0.00% (144.00B) ⬇️
infer_expression_types_impl 23.35MB 23.35MB -0.00% (136.00B) ⬇️
member_lookup_with_policy_inner 10.75MB 10.75MB -0.00% (120.00B) ⬇️
Type<'db>::apply_specialization_inner_ 3.42MB 3.42MB -0.00% (24.00B) ⬇️
try_call_dunder_get_inner 1.08MB 1.08MB -0.00% (24.00B) ⬇️
infer_definition_types 34.54MB 34.54MB -0.00% (24.00B) ⬇️
all_narrowing_constraints_for_expression 4.52MB 4.52MB -0.00% (16.00B) ⬇️
StaticClassLiteral<'db>::implicit_attribute_inner_ 803.80kB 803.79kB -0.00% (16.00B) ⬇️
infer_expression_type_impl 250.37kB 250.35kB -0.01% (16.00B) ⬇️
FunctionType<'db>::signature_ 4.38MB 4.38MB +0.00% (16.00B)
infer_unpack_types 426.79kB 426.78kB -0.00% (8.00B) ⬇️
infer_deferred_types 4.88MB 4.88MB +0.00% (8.00B)
... 2 more

trio

Name Old New Diff Outcome
Type<'db>::apply_specialization_inner_::interned_arguments 1.18MB 1.18MB -0.03% (400.00B) ⬇️
Type<'db>::apply_specialization_inner_ 791.83kB 791.55kB -0.04% (288.00B) ⬇️
FunctionType 1.23MB 1.23MB -0.02% (288.00B) ⬇️
may_have_unbounded_specialization_inner 0.00B 136.00B +136.00B (new)
infer_definition_types 4.43MB 4.43MB -0.00% (128.00B) ⬇️
may_have_unbounded_specialization_inner::interned_arguments 0.00B 64.00B +64.00B (new)
infer_deferred_types 1.28MB 1.28MB -0.00% (24.00B) ⬇️

@astral-sh-bot

astral-sh-bot Bot commented Aug 6, 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)

@mtshiba
mtshiba force-pushed the recursive-type-may-diverge branch from 5a0bd94 to 132cc5a Compare August 6, 2026 04:21
@mtshiba
mtshiba force-pushed the recursive-type-may-diverge branch 2 times, most recently from 20099d2 to 4a481b9 Compare August 6, 2026 16:48
@mtshiba mtshiba changed the title [ty] Detect finite recursive specialization orbits [ty] Only treat recursive types with unbounded specializations as fallback cycles Aug 6, 2026
@mtshiba
mtshiba force-pushed the recursive-type-may-diverge branch 2 times, most recently from da5e860 to 5e982bf Compare August 7, 2026 01:48
@mtshiba
mtshiba force-pushed the recursive-type-may-diverge branch from 5e982bf to 5249d00 Compare August 7, 2026 06:46
@mtshiba
mtshiba marked this pull request as ready for review August 7, 2026 10:37
@mtshiba
mtshiba requested a review from a team as a code owner August 7, 2026 10:37
@astral-sh-bot
astral-sh-bot Bot requested a review from charliermarsh August 7, 2026 10:37
@carljm
carljm self-requested a review August 7, 2026 19:08
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.

1 participant