Conversation
Apply the existing Struct rewriter to constant assignments nested in blocks while keeping the generated classes at the original expression location. Add strict and rewrite-tree coverage for direct and nested blocks, including the unchanged local-variable path. Assisted-by: OpenAI Codex.
Track the block depth at each class boundary so direct assignments inside a class nested in a block continue through the existing class-body rewriter path. Cover an invalid Struct member once to catch duplicate rewrites. Assisted-by: OpenAI Codex.
Keep generated class definitions as statements and return the original constant from rewritten assignments so block expressions retain Ruby assignment semantics. Add a map-based type regression for the generated class value. Assisted-by: OpenAI Codex.
jez
left a comment
There was a problem hiding this comment.
I don't believe that this change should need to look at blocks at all—blocks is a red herring. It should simply traverse all assignments inside the tree.
The change should not need to deepCopy anything.
froydnj
left a comment
There was a problem hiding this comment.
I agree with jez's comments.
Move Struct rewriting to postTransformAssign so nested assignments are handled regardless of their enclosing AST node. Splice direct class-body replacements back into the class RHS to preserve the existing tree shape, and add conditional-assignment coverage. Assisted-by: OpenAI Codex.
|
Thanks, that makes sense. I removed the block-depth tracking and moved the Struct rewrite into I also added a conditional-assignment case to cover nesting outside blocks. All 304 Legacy and Prism rewriter targets pass locally, along with both positive and LSP variants for the fixture. Could you take another look when convenient? |
Return a reconstructed constant reference after emitting the generated classes so rewritten assignments keep Ruby expression semantics. Normalize self-qualified paths to lexical reads and keep direct class-body expansion unchanged. Restore block-value regression coverage for ordinary and self-qualified constants. Assisted-by: OpenAI Codex.
|
I found one return-value regression while rechecking the latest revision: the generated Commit 5a3c809 keeps both generated classes in I restored the block-result regression and added |
|
@jez, could you unblock Buildkite for the latest commit when convenient? The local Legacy and Prism rewriter suites are green. |
Motivation
Fixes #10631.
Constant assignments such as
Generated = Struct.new(:value)normally go through the Struct rewriter, which gives the generated class its members and constructor type. The old entry point only considered direct class-body statements, so assignments nested under another expression skipped the rewrite and strict files received error 7027 with aT.let(..., Struct)autocorrect that fails at runtime.This change invokes the existing Struct rewriter from
postTransformAssign, allowing the tree walk to handle matching assignments wherever they occur in the AST. It does not special-case blocks. For assignments whose value is used, the generated classes are emitted asInsSeqstatements and a rebuilt reference to the target constant remains as the result, preserving Ruby assignment-expression semantics. The reference builder handles lexical, root-qualified, relative-qualified, andself::paths without adding a generic ASTdeepCopy.Direct class-body replacements are still spliced into the class RHS to preserve the existing AST shape. Local-variable
Struct.newcalls remain unchanged because they do not match the Struct rewriter's constant-lhs requirement.The regression fixture covers direct and nested blocks, immediate use of the generated class, an unchanged local-variable path, a class nested inside a block, a conditional assignment outside a block, and assignment values returned from blocks, including a
self::-qualified target. The rewrite-tree snapshot also verifies that direct class-body assignments are not rewritten twice.Test plan
tools/scripts/format_cxx.sh -t rewriter/rewriter.ccstruct_nested_blockstruct_nested_blocktest_PosTests/testdata/rewriter/*targetsgit diff --checkPrepared with OpenAI Codex assistance.