[ty] fix too-many-cycle panics when inferring literal type loop variables#23875
[ty] fix too-many-cycle panics when inferring literal type loop variables#23875mtshiba merged 3 commits intoastral-sh:mainfrom
Conversation
Typing conformance resultsNo changes detected ✅Current numbersThe percentage of diagnostics emitted that were expected errors held steady at 85.29%. The percentage of expected errors that received a diagnostic held steady at 78.13%. The number of fully passing files held steady at 64/132. |
|
Memory usage reportSummary
Significant changesClick to expand detailed breakdownprefect
sphinx
trio
flake8
|
dcreager
left a comment
There was a problem hiding this comment.
Simply adding a field will increase the size of
LiteralValueType, which will in turn increase the size ofType.
To address this, I decided to use a technique already used byLiteralValueTypeInner: embedding the flags as an enum discriminant. It's a bit of an ugly solution, but I couldn't find better way.
The max payload is for IntLiteral, which contains two u32s. My reading is that the u8 discriminant is padded to 32 bits, making the overall size of the type 12 bytes. That padding means that there should be room to squeeze an 8-bit bitflags or similar to store "promotable" and "recursively defined". (You'd have to add it to each variant of the enum, rather than putting it in an extra field of the struct wrapper, to make sure that it gets placed into the discriminant's padding.) i.e. in the playground this shows 12 bytes for both approaches.
(I'm fairly certain I got the types right in the playground. You could also add a static assertion like we have here to verify that the size of LiteralValueTypeInner stays consistent at 12 bytes.)
|
I took some time to understand why literal types are special here - why don't we need to carry this flag on all types? I guess it's because the recursively-defined flag in the end only has an effect on the maximum size of unions of literals. So there's no scenario where it would matter for another type to carry it. |
* main: (94 commits) Fix shell injection via `shell=True` in subprocess calls (#23894) [ty] Refactor `relation.rs` to store state on a struct rather than passing around 7 arguments every time we recurse (#23837) Don't return code actions for non-Python documents (#23905) [ty] Make the default database truly statically infallible (#23929) [ty] Add `Download` button to ty playground which creates a zip export (#23478) [ty] Respect `kw_only` overwrites in dataclasses (#23930) [ty] Clarify in diagnostics that `from __future__ import annotations` only stringifies type annotations (#23928) [ty] Add a `Copy Markdown` button to playground (#23002) [ty] Fix folding range classification of lines starting with `#` (#23831) [ty] Fix folding ranges for notebooks (#23830) [ty] fix too-many-cycle panics when inferring literal type loop variables (#23875) Add `RegularCallableTypeOf` and `into_regular_callable` in `ty_extensions` (#23909) [ty] treat properties as full structural types (#23925) [ty] Avoid duplicated work during multi-inference (#23923) [ty]: make `possibly-missing-attribute` ignored by default [ty]: split out `possibly-missing-submodule` from `possibly-missing-attribute` Update astral-sh/setup-uv action to v7.5.0 (#23922) [ty] Show truthiness in ConstraintSet display and simplify falsy error message (#23913) Bump 0.15.6 (#23919) [ty] Narrow type context during collection literal inference (#23844) ...
Summary
Fixes astral-sh/ty#3011
See the comment in #3011 for an analysis of this bug.
We can simply add a
recursively_definedfield to the literal value type to prevent this bug. But there's one problem. Simply adding a field will increase the size ofLiteralValueType, which will in turn increase the size ofType.To address this, I decided to use a technique already used by
LiteralValueTypeInner: embedding the flags as an enum discriminant. It's a bit of an ugly solution, but I couldn't find better way.Test Plan
new corpus test