Repository navigation
perf(python): emit union field reads via narrow helper instead of typing.cast - #4731
Merged
MangelMaxime merged 1 commit intoJul 8, 2026
Merged
Conversation
…typing.cast` Union case field reads are compiled as `cast(Case, x).field`, which required disabling `reportUnnecessaryCast` globally (single-case unions and already-narrowed values make some of those casts redundant from Pyright's view). Move the "cast" into a small library helper `narrow(Case, x)` in union.py: a typed identity function (single runtime call, same cost as the previous inline cast). This keeps generated code free of `typing.cast`, so `reportUnnecessaryCast` can stay enabled for the rest of the generated Python. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Member
|
I tried to find a way to not disable |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #4725, targeting its branch.
#4725 speeds up union case field reads by emitting
cast(Case, x).fieldinstead of the.fields-rebuild property. To make Pyright accept those casts it disablesreportUnnecessaryCastglobally, because some sites (single-case unions, already-narrowed values) make the cast redundant from Pyright's point of view.This PR moves that "cast" into a tiny library helper so generated code stays
cast-free and the global rule can stay on.Changes
fable_library/union.py— addnarrow[T](case: type[T], value: object) -> T, a typed identity function (documented, exported in__all__). It plays the same role astyping.castbut is scoped to unions.Fable2Python.Transforms.fs— union field reads now emitnarrow(Case, x).fieldinstead ofcast(Case, x).field.pyrightconfig.json— revertreportUnnecessaryCastback totrue;narrowis nottyping.cast, so the rule no longer fires on these reads (and still guards the rest of the generated code).Generated output before → after:
Why not
cast(T, value)insidenarrow?narrow's body isreturn value # pyright: ignore[reportReturnType]rather thanreturn cast(T, value).typing.castis a plain Python function (return val), so routing through it would make two calls per field read instead of one — a needless regression on the exact hot path this optimization targets (~8M reads in the #4725 benchmark). The ignore is targeted, andreportUnnecessaryTypeIgnoreComment(enabled) confirms it's genuinely necessary.Verification
union.py: 0 errors/warnings; the ignore is not flagged as unnecessary.narrow(Tree_Leaf, x).value_resolves to the field's real type (int).narrow(...)for both user unions and library unions (Result/Choice); the only remainingcastin output is a legitimately-necessary one thatreportUnnecessaryCast: trueaccepts.🤖 Generated with Claude Code