Skip to content

rust encoder: while let unsupported, panics with misleading "let-guard outside if/while" #778

Description

@ahmednfwela

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.

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions