What happens
rust/encoder/src/control_flow.rs::encode_while (and encode_loop) hands its
condition straight to self.encode_expr(&e.cond) with no special case for
syn::Expr::Let:
pub(crate) fn encode_while(&mut self, e: &syn::ExprWhile) -> Expression {
let condition = self.encode_expr(&e.cond);
...
}
encode_if (same file, ~line 149) DOES special-case syn::Expr::Let for if let.
while let Some(x) = iter.next() { .. } — an extremely common Rust idiom for
draining an iterator/receiver — falls through encode_expr's match arms all the
way to the catch-all in lib.rs, which panics with:
syn::Expr::Let(_) => "let-guard outside if/while",
The message is actively misleading (it fires inside a while), and more importantly
there is no support for while let in the Rust encoder at all — every
non-trivial file that drains an iterator or a channel with while let cannot be
encoded, loud but for the wrong stated reason.
Why the tests did not catch it
This was surfaced by a reviewer of PR #698 as a pre-existing gap in
encode_while/encode_expr's fallback, flagged and explicitly left out of scope
in that PR's body. No test in rust/encoder/tests/ exercises a while let
expression, so nothing pins either the missing feature or the wrong panic message.
Definition of done
- RED-first test(s) in
rust/encoder/tests/ (loops/control-flow suite) that
encode a while let Some(x) = <iter-expr> { .. } program and assert either a
correct std.while-based encoding (mirroring encode_if's Expr::Let
handling — Ball's while has no pattern-binding condition, so this likely
needs an Option/outcome-shaped desugaring similar to how for loops desugar
iteration) or, if genuinely out of scope for now, a loud refusal that correctly
names while let rather than "let-guard outside if/while".
rust/encoder/src/control_flow.rs::encode_while (and encode_loop if
applicable) updated to match; .claude/rules/rust.md documents the resulting
behavior.
cargo test -p ball-lang-encoder, cargo fmt -p ball-lang-encoder -- --check,
cargo clippy -p ball-lang-encoder --all-targets -- -D warnings all clean.
Refs
PR review: #698 (comment)
Evidence: rust/encoder/src/control_flow.rs:360-366 (encode_while), :149
(encode_if's existing Expr::Let handling), rust/encoder/src/lib.rs:2751
("let-guard outside if/while") — all origin/main @ b8ae4e6.
What happens
rust/encoder/src/control_flow.rs::encode_while(andencode_loop) hands itscondition straight to
self.encode_expr(&e.cond)with no special case forsyn::Expr::Let:encode_if(same file, ~line 149) DOES special-casesyn::Expr::Letforif let.while let Some(x) = iter.next() { .. }— an extremely common Rust idiom fordraining an iterator/receiver — falls through
encode_expr's match arms all theway to the catch-all in
lib.rs, which panics with:The message is actively misleading (it fires inside a
while), and more importantlythere is no support for
while letin the Rust encoder at all — everynon-trivial file that drains an iterator or a channel with
while letcannot beencoded, loud but for the wrong stated reason.
Why the tests did not catch it
This was surfaced by a reviewer of PR #698 as a pre-existing gap in
encode_while/encode_expr's fallback, flagged and explicitly left out of scopein that PR's body. No test in
rust/encoder/tests/exercises awhile letexpression, so nothing pins either the missing feature or the wrong panic message.
Definition of done
rust/encoder/tests/(loops/control-flow suite) thatencode a
while let Some(x) = <iter-expr> { .. }program and assert either acorrect
std.while-based encoding (mirroringencode_if'sExpr::Lethandling — Ball's
whilehas no pattern-binding condition, so this likelyneeds an
Option/outcome-shaped desugaring similar to howforloops desugariteration) or, if genuinely out of scope for now, a loud refusal that correctly
names
while letrather than "let-guard outside if/while".rust/encoder/src/control_flow.rs::encode_while(andencode_loopifapplicable) updated to match;
.claude/rules/rust.mddocuments the resultingbehavior.
cargo test -p ball-lang-encoder,cargo fmt -p ball-lang-encoder -- --check,cargo clippy -p ball-lang-encoder --all-targets -- -D warningsall clean.Refs
PR review: #698 (comment)
Evidence:
rust/encoder/src/control_flow.rs:360-366(encode_while),:149(encode_if's existing
Expr::Lethandling),rust/encoder/src/lib.rs:2751("let-guard outside if/while") — all origin/main @ b8ae4e6.