Fix GS9998 for member index-assignment in state machines (#887)#888
Merged
DavidObando merged 1 commit intoJun 19, 2026
Merged
Conversation
A member CLR-indexer write such as `psi.Environment["k"] = v` or `obj.Map["k"] = v` inside an `async func` failed at emit with `GS9998: Variable '<idxAsn#>' has no local slot or parameter index`. The index write binds to a synthesized receiver temp (`<idxAsn#>`) carried on a BoundClrIndexAssignmentExpression. That node stores its receiver as a raw VariableSymbol Target which the bound-tree rewriter never visits. The async capture walker hoists the temp into a state-machine field, but the MoveNext rewriter only redirects BoundVariableExpression references, so the raw symbol survived unrewritten and the emitter had no slot for it. The async MoveNext rewriter already handled the native map/slice variant (BoundIndexAssignmentExpression) but was missing the CLR-indexer override. The iterator and async-iterator MoveNext builders were missing overrides for both index-assignment node kinds. Add the missing overrides so a hoisted index-assignment Target is redirected to its state-machine field via the WithExpressionTarget form (same approach as the closure-boxing fix, issue #618), across all three state-machine rewriters. Add regression tests covering async, iterator, and async-iterator.
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.
Fixes #887.
Problem
A member CLR-indexer write such as
psi.Environment["k"] = vorobj.Map["k"] = v(on aDictionary) inside anasync funcfailed at emit:The LSP showed no errors while editing; the failure only surfaced at emit time.
Root cause
The index write binds to a synthesized receiver temp (
<idxAsn#>) carried on aBoundClrIndexAssignmentExpression. That node stores its receiver as a rawVariableSymbolTarget which the bound-tree rewriter never visits. The async capture walker correctly hoists the temp into a state-machine field, but the MoveNext rewriter only redirectsBoundVariableExpressionreferences — so the raw symbol survived unrewritten and the emitter had no slot for it.The async MoveNext rewriter already handled the native map/slice variant (
BoundIndexAssignmentExpression) but was missing the CLR-indexer override. While investigating I found the iterator and async-iterator MoveNext builders had the same latent gap for both index-assignment node kinds.Fix
Add the missing MoveNext-rewriter overrides so a hoisted index-assignment
Targetis redirected to its state-machine field via the existingWithExpressionTargetform (the same approach as the closure-boxing fix, issue #618):src/Core/CodeAnalysis/Lowering/Async/MoveNextBodyRewriter.cs—RewriteClrIndexAssignmentExpressionsrc/Core/CodeAnalysis/Lowering/Iterators/IteratorMoveNextBodyBuilder.cs— both index-assignment overrides (in both nested rewriters)src/Core/CodeAnalysis/Lowering/Iterators/AsyncIteratorMoveNextBodyBuilder.cs— both index-assignment overridesTests
New
Issue887ClrIndexerAssignmentAsyncEmitTests.cscovers async (including the exactProcessStartInfoobject-initializer +Environment[...]repro from the issue), iterator, and async-iterator. All pass with correct runtime results.