Skip to content

[ty] Require subtyping for transitive constraint pivots#25778

Open
charliermarsh wants to merge 2 commits into
mainfrom
charlie/fix-dynamic-constraint-explosion
Open

[ty] Require subtyping for transitive constraint pivots#25778
charliermarsh wants to merge 2 commits into
mainfrom
charlie/fix-dynamic-constraint-explosion

Conversation

@charliermarsh

@charliermarsh charliermarsh commented Jun 9, 2026

Copy link
Copy Markdown
Member

Summary

When building sequent maps for constraints on different type variables, we use materialized bounds as pivots to derive transitive relationships. We previously accepted a pivot when those bounds were assignable. Unrelated classes with dynamic bases are mutually assignable, so this connected otherwise independent invariant type variables and caused the constraint set in the issue reproducer to grow combinatorially.

This changes those pivot checks to require subtyping. Because the bounds can themselves contain type variables, the new check uses constraint-set-aware subtyping rather than the ordinary subtype relation. Constraint-set type-variable handling is now an independent mode on TypeRelationChecker, so it can be combined with either subtyping or assignability; the mode is also included in relation and signature recursion keys so cached results are not shared across comparison modes.

In a local benchmark of the issue reproducer, check time fell from 14.5 seconds with constraint-set assignability to 46 milliseconds with constraint-set subtyping.

Closes astral-sh/ty#3607.

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

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

@astral-sh-bot

astral-sh-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

Memory usage report

Summary

Project Old New Diff Outcome
flake8 35.38MB 35.38MB -
trio 87.75MB 87.75MB -
sphinx 207.56MB 207.56MB -0.00% (5.91kB) ⬇️
prefect 564.13MB 563.95MB -0.03% (186.61kB) ⬇️

Significant changes

Click to expand detailed breakdown

sphinx

Name Old New Diff Outcome
when_constraint_set_assignable_to_owned_impl 1.50MB 1.50MB -0.11% (1.75kB) ⬇️
is_redundant_with_impl::interned_arguments 1.14MB 1.14MB -0.06% (704.00B) ⬇️
IntersectionType 561.52kB 560.92kB -0.11% (616.00B) ⬇️
assignable_solutions_impl 188.20kB 187.67kB -0.28% (540.00B) ⬇️
is_redundant_with_impl 919.62kB 919.24kB -0.04% (384.00B) ⬇️
when_constraint_set_assignable_to_owned_impl::interned_arguments 257.47kB 257.12kB -0.13% (352.00B) ⬇️
IntersectionType<'db>::from_two_elements_ 53.36kB 53.08kB -0.51% (280.00B) ⬇️
UnionType 654.20kB 653.97kB -0.04% (240.00B) ⬇️
is_possibly_constraint_set_assignable 262.57kB 262.36kB -0.08% (216.00B) ⬇️
IntersectionType<'db>::from_two_elements_::interned_arguments 58.52kB 58.35kB -0.29% (176.00B) ⬇️
UnionType<'db>::from_two_elements_ 292.57kB 292.44kB -0.04% (128.00B) ⬇️
Specialization 1.27MB 1.27MB -0.01% (128.00B) ⬇️
is_possibly_constraint_set_assignable::interned_arguments 159.33kB 159.24kB -0.05% (88.00B) ⬇️
UnionType<'db>::from_two_elements_::interned_arguments 265.89kB 265.80kB -0.03% (88.00B) ⬇️
GenericAlias 546.89kB 546.82kB -0.01% (72.00B) ⬇️
... 5 more

prefect

Name Old New Diff Outcome
when_constraint_set_assignable_to_owned_impl 3.04MB 3.01MB -0.93% (28.88kB) ⬇️
is_redundant_with_impl::interned_arguments 2.37MB 2.35MB -0.84% (20.28kB) ⬇️
is_redundant_with_impl 1.99MB 1.97MB -0.80% (16.35kB) ⬇️
IntersectionType 1012.11kB 997.97kB -1.40% (14.14kB) ⬇️
StaticClassLiteral<'db>::try_mro_ 4.33MB 4.31MB -0.32% (14.00kB) ⬇️
UnionType 1.37MB 1.36MB -0.74% (10.39kB) ⬇️
UnionType<'db>::from_two_elements_ 742.79kB 733.12kB -1.30% (9.67kB) ⬇️
infer_definition_types 75.87MB 75.87MB -0.01% (7.58kB) ⬇️
IntersectionType<'db>::from_two_elements_ 87.81kB 80.40kB -8.43% (7.41kB) ⬇️
UnionType<'db>::from_two_elements_::interned_arguments 613.94kB 607.32kB -1.08% (6.62kB) ⬇️
when_constraint_set_assignable_to_owned_impl::interned_arguments 568.82kB 562.80kB -1.06% (6.02kB) ⬇️
assignable_solutions_impl 324.89kB 319.27kB -1.73% (5.62kB) ⬇️
Specialization 2.51MB 2.50MB -0.19% (4.97kB) ⬇️
is_possibly_constraint_set_assignable 597.90kB 593.09kB -0.81% (4.82kB) ⬇️
infer_scope_types_impl 47.64MB 47.64MB -0.01% (3.92kB) ⬇️
... 30 more

@astral-sh-bot

astral-sh-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-assignment 0 1 0
invalid-return-type 0 0 1
Total 0 1 1

Large timing changes:

Project Old Time New Time Change
pytest-robotframework 0.16s 0.28s +69%

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

Raw diff:

paasta (https://github.com/yelp/paasta)
- paasta_tools/tron_tools.py:573:16 error[invalid-return-type] Return type does not match returned value: expected `dict[str, FieldSelectorConfig]`, found `dict[str | FieldSelectorConfig, FieldSelectorConfig | dict[str, str]]`
+ paasta_tools/tron_tools.py:573:16 error[invalid-return-type] Return type does not match returned value: expected `dict[str, FieldSelectorConfig]`, found `dict[str, FieldSelectorConfig | dict[str, str]]`

prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/runtime/flow_run.py:70:5 error[invalid-assignment] Object of type `dict[<class 'bool'> | <class 'int'> | <class 'float'> | ... omitted 3 union elements, ((x) -> Unknown) | <class 'int'> | <class 'float'> | <class 'str'> | ((dt: str) -> datetime)]` is not assignable to `dict[type[int | float | str | Unknown] | <class 'NoneType'>, (Any, /) -> Any]`

Full report with detailed diff (timing results)

@codspeed-hq

codspeed-hq Bot commented Jun 9, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 4.22%

❌ 1 regressed benchmark
✅ 66 untouched benchmarks
⏩ 60 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation ty_micro[pydantic_core_schema_dict] 113 ms 118 ms -4.22%

Tip

Investigate this regression with the CodSpeed MCP and your agent.


Comparing charlie/fix-dynamic-constraint-explosion (ab9db7e) with main (948359f)

Open in CodSpeed

Footnotes

  1. 60 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@charliermarsh charliermarsh force-pushed the charlie/fix-dynamic-constraint-explosion branch 3 times, most recently from c433edc to 28d7fdb Compare June 9, 2026 16:11
@charliermarsh

Copy link
Copy Markdown
Member Author

I decided to fix the pytest-robotframework regression in a stacked PR: #25786

@charliermarsh charliermarsh added the performance Potential performance improvement label Jun 9, 2026
@charliermarsh charliermarsh force-pushed the charlie/fix-dynamic-constraint-explosion branch from 28d7fdb to be0c908 Compare June 9, 2026 16:54
@charliermarsh charliermarsh marked this pull request as ready for review June 9, 2026 16:54
Comment thread crates/ty_python_semantic/src/types/relation.rs Outdated
Comment thread crates/ty_python_semantic/src/types/relation.rs
@charliermarsh charliermarsh force-pushed the charlie/fix-dynamic-constraint-explosion branch from be0c908 to ab9db7e Compare June 9, 2026 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance Potential performance improvement ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Combinatorial runtime explosion for generic class with many invariant typevars and dynamic bounds

2 participants