You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I reproduced an LSP crash where opening and incrementally editing fuel-o2-exports/contracts/order-book/src/main.sw could abort the server and leave stale semantic highlighting behind in the client.
Daniel pointed out that the generated tuple helpers in std::codec are emitted as one large left-associative && chain. This change fixes the root recursion pressure there instead of carrying the LSP stack-size workaround.
The generator change is in sway-lib-std/generate.sh, and the regenerated output is checked in at sway-lib-std/src/codec.sw. The snapshot updates are included because the generated helper shape changes source spans, IR local numbering, bytecode size, and a few gas values in the affected e2e snapshot outputs.
Root cause
The LSP crash was a stack overflow while processing generated std::codec tuple code. The tuple triviality helpers were emitted as deeply left-associated && expressions, e.g. one expression chaining checks across all tuple elements.
Because && is left-associative, that produces a deeply left-leaning AST. Recursive compiler and LSP passes then consume one stack frame per node while lowering, traversing, or building semantic-token state. On the fuel-o2-exports order-book repro, that was enough to bring down the language server and leave stale semantic highlighting in the editor.
The earlier LSP stack-size mitigation kept the process alive by giving those recursive paths more stack. Daniel's suggestion fixes the source-level shape that was creating the stack pressure in the first place.
Why this mitigates it
The tuple helpers now use:
letr=__runtime_mem_id::<Self>() ==__encoding_mem_id::<Self>();
letr=r&&is_encode_trivial::<A>();
letr=r&&is_encode_trivial::<B>();
r
instead of one large chained expression.
That keeps each expression shallow, so compiler and LSP recursion does not scale with the full tuple arity in a single left-deep AST. The language server no longer needs the stack-size workaround for this repro.
Validation
regenerated sway-lib-std/src/codec.sw from sway-lib-std/generate.sh
verified regeneration produced no extra generated-file diff beyond the checked-in codec.sw
verified no generated left-deep tuple triviality chains remain
Medium Risk
Touches generated AbiEncode/AbiDecode implementations for tuples in the standard library; while intended to be semantics-preserving, any mistake could impact ABI (de)serialization behavior across many users.
Overview
Refactors the generated tuple implementations in sway-lib-std/src/codec.sw so is_encode_trivial/is_decode_trivial are built as a series of let r = r && ...; statements instead of a single long left-associative && expression, reducing AST recursion pressure that was crashing the LSP on large tuples.
Updates sway-lib-std/generate.sh to require/use GNU sed (auto-detecting gsed on macOS) and to emit the new tuple helper shape, and refreshes affected e2e snapshot outputs (*.stdout.snap) to match changed spans/IR numbering and minor size/gas deltas.
Reviewed by Cursor Bugbot for commit 692b463. Bugbot is set up for automated code reviews on this repo. Configure here.
JoshuaBatty
changed the title
[Joshua] Mitigate LSP stack overflows in compile and traversal workers
[fix] Mitigate LSP stack overflows in compile and traversal workers
Apr 29, 2026
JoshuaBatty
changed the title
[fix] Mitigate LSP stack overflows in compile and traversal workers
[Joshua] Mitigate LSP stack overflows in compile and traversal workers
Apr 29, 2026
JoshuaBatty
changed the title
[Joshua] Mitigate LSP stack overflows in compile and traversal workers
Mitigate LSP stack overflows in compile and traversal workers
Apr 29, 2026
JoshuaBatty
changed the title
Mitigate LSP stack overflows in compile and traversal workers
[Joshua] Mitigate LSP stack overflows in compile and traversal workers
Apr 29, 2026
JoshuaBatty
changed the title
[Joshua] Mitigate LSP stack overflows in compile and traversal workers
Mitigate LSP stack overflows in compile and traversal workers
Apr 29, 2026
Would make sense to break the one big expression into multiple ones?
JoshuaBatty
changed the title
Mitigate LSP stack overflows in compile and traversal workers
Fix tuple codec helpers to avoid LSP stack overflows
May 3, 2026
Would make sense to break the one big expression into multiple ones?
Great idea, thanks for pointing this out. I switched the fix over to your suggested approach and removed the LSP stack-size workaround. The tuple codec helpers now avoid the single left-deep && expression and emit shallow statement sequences instead, which fixes the stack pressure at the source rather than just giving the LSP more stack. I also validated this against the original order-book repro and couldn’t reproduce the LSP crash anymore.
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
compilerGeneral compiler. Should eventually become more specific as the issue is triagedlanguage serverLSP serverlib: stdStandard library
2 participants
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
I reproduced an LSP crash where opening and incrementally editing
fuel-o2-exports/contracts/order-book/src/main.swcould abort the server and leave stale semantic highlighting behind in the client.Daniel pointed out that the generated tuple helpers in
std::codecare emitted as one large left-associative&&chain. This change fixes the root recursion pressure there instead of carrying the LSP stack-size workaround.The generator change is in
sway-lib-std/generate.sh, and the regenerated output is checked in atsway-lib-std/src/codec.sw. The snapshot updates are included because the generated helper shape changes source spans, IR local numbering, bytecode size, and a few gas values in the affected e2e snapshot outputs.Root cause
The LSP crash was a stack overflow while processing generated
std::codectuple code. The tuple triviality helpers were emitted as deeply left-associated&&expressions, e.g. one expression chaining checks across all tuple elements.Because
&&is left-associative, that produces a deeply left-leaning AST. Recursive compiler and LSP passes then consume one stack frame per node while lowering, traversing, or building semantic-token state. On thefuel-o2-exportsorder-book repro, that was enough to bring down the language server and leave stale semantic highlighting in the editor.The earlier LSP stack-size mitigation kept the process alive by giving those recursive paths more stack. Daniel's suggestion fixes the source-level shape that was creating the stack pressure in the first place.
Why this mitigates it
The tuple helpers now use:
instead of one large chained expression.
That keeps each expression shallow, so compiler and LSP recursion does not scale with the full tuple arity in a single left-deep AST. The language server no longer needs the stack-size workaround for this repro.
Validation
sway-lib-std/src/codec.swfromsway-lib-std/generate.shcodec.swRUSTUP_TOOLCHAIN=1.93.0 cargo build -p forc-lsp --releasetarget/release/forc-lspfuel-o2-exports/contracts/order-book/src/main.sw225textDocument/didChangenotifications and11textDocument/semanticTokens/rangerequestsstdout.snapfiles after CI snapshot driftRUSTUP_TOOLCHAIN=1.93.0 cargo run --locked --release --bin test -- --locked --kind snapshot