Repository navigation
fix(hy-emit): fill an elided literal's head through parentheses (fixes #630) - #631
Merged
limitlessprojects merged 1 commit intoOct 18, 2026
Conversation
…tlessprojects#630) `emit_expr_exp` is the only site that gives a type-elided composite literal its head from the surrounding type, and it matched the expression directly. A redundant parenthesis therefore put the literal out of reach of the `ty: None` / `elem: None` arms, the expected type was discarded, and the emit fell through to the "spell the type" refusal - on a program `hyb check` accepts with 0 diagnostics: struct svc { replicas int tag string } fn main() { m := map[string]svc{"a": ({replicas: 2, tag: "x"})} fmt.println("{m}") } $ hyb check elided.hy -> OK (0 diagnostics) $ hyb build elided.hy -> error [emit]: not yet supported: type-elided struct literal - spell the type Without the parens the same program builds, runs, and prints `map[a:{2 x}]`; with the peel it prints the same thing. `Paren` is documented as span-only and semantically transparent (`hy-syntax/src/ast.rs`: "kept for faithful spans"), so the elision has to apply identically through it. Dropping the parens from output is safe at every call site: `emit_expr_exp` is only reached from the element slots of composite literals, where Go gives parentheses no meaning. The peel stays local to `emit_expr_exp` on purpose - `Self::peel_parens` is private to `stmt.rs` today and limitlessprojects#619 promotes it separately, so this change is one hunk in one file and does not touch that helper. Tests: `diff_elided_map_value_struct_literal_under_parens` and `diff_elided_slice_elem_struct_literal_under_parens` (the latter also covers double parens) fail without the peel; `diff_elided_map_value_ struct_literal` pins the unparenthesised spelling unchanged. Verified on 28754ab: `cargo test -p hy-emit --lib` 173 passed / 0 failed (171 before, +2); with expr.rs reverted and the tests kept, exactly the two new ones fail and the other 171 pass; `cargo test --workspace` all suites ok; `tools/differential_loop.py` accept-side 21/23, reject-side 56/56 - the two misses are the local non-ASCII %TEMP% cgo fixtures (`a7-borrow-by-default`, `a7-own-transfer-at-return`), which fail the same way on unpatched main.
Owner
|
Landed as two-parent merge b8e850b onto main (worktree merge of pr-631 @ de0a97a, GitHub marks this PR merged). Thank you @Leimiu-G — clean, minimal, and exactly the right fix. Live-bypass probe on main @ 55cd957 (before landing): confirmed LIVE — check-accepts/emit-rejects gap:
Post-merge verification on b8e850b: both paren scenarios now emit and build ( Battery on merged tree: cargo test --workspace 1386/0 (+2 = the PR's two tests), corpus 100/100 verdict agreement (tripwire quiet), differential FULL 34+66. Closes #630. Credit: Leimiu-G. |
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 #630.
What
hy-emit/src/expr.rs::emit_expr_expis the only place that fills an elided composite literal's headfrom its surrounding type. It matched the expression directly, so a redundant parenthesis put the
literal out of reach of the
ty: None/elem: Nonearms,expectedwas discarded, and the emitfell through to the "spell the type" refusal — on a program
hyb checkpasses with 0 diagnostics.Peel
Parenbefore the expected-type dispatch:Parenis documented as span-only (hy-syntax/src/ast.rs: "kept for faithful spans"), so theelision has to apply identically through it. Dropping the parens from output is safe at all three
call sites — each is an element slot of a composite literal, where Go gives parentheses no meaning.
The peel is local to
emit_expr_expon purpose:Self::peel_parensis private tostmt.rstoday,and #619 promotes it separately, so this PR keeps to one hunk in one file.
Verification
Emitted Go is byte-identical with and without the parens, and the program output matches:
Tests — two new pins next to the existing
diff_elided_map_value_struct_literal:diff_elided_map_value_struct_literal_under_parensdiff_elided_slice_elem_struct_literal_under_parens(also covers double parens)Falsifiable: with
expr.rsreverted and the tests kept, exactly those two fail and the other171 pass — no collateral, no test that passes without the fix.
Workspace and differential corpus on
28754ab(patched):cargo test --workspace— all suites ok, 0 failedcargo test -p hy-emit --test '*'— oktools/differential_loop.py— accept-side 21/23, reject-side 56/56The 2 accept-side misses are the local environment, not this change: both are
a7-*cgo fixturesthat fail assembling under a non-ASCII
%TEMP%(can't create C:\Users\????\AppData\Local\Temp\ go-build...\_x006.o). They fail identically on unpatchedmain.Related
Same invariant as #618 (parenthesized receiver loses its type) and #609 (line-leading
(swallowedas an argument list) — the 8th independent locus where a site dispatches on
Exprshape withoutpeeling first.