Repository: ProvableHQ/leo (2026-03-30T15:35:40Z)

Issue:
[Bug] Compiler panic in `BlockToFunctionRewriter`: `Expected tuple type when accessing tuple field` on non-tuple in `final` block
The compiler panics with `Expected tuple type when accessing tuple field: p.0` in [`passes/src/common/block_to_function_rewriter.rs` `rewrite_block`](https://github.com/ProvableHQ/leo/blob/2865788596/crates/passes/src/common/block_to_function_rewriter.rs) when a `final` block contains a tuple field assignment on a non-tuple variable. The type checker correctly emits a diagnostic but `BlockToFunctionRewriter` runs unconditionally and panics.

MRE:
```leo
program test.aleo {
    fn foo(p: u32) -> Final {
        let f = final {
            p.0 = 1u32;
        };
        return f;
    }
}
```

Reproduce: create a minimal `program.json` (`"program": "test.aleo"`), save the MRE as `src/main.leo`, run `leo build`.

Output:
```
Error [ETYC0372117]: Expected a tuple but type `u32` was found.
    --> fuzz_input.leo:4:13
     |
   4 |             p.0 = 1u32;
     |             ^^^

thread 'main' panicked at crates/passes/src/common/block_to_function_rewriter.rs:
Expected tuple type when accessing tuple field: p.0
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

Expected behavior: only the type error diagnostic, no panic.

Git commit: 2865788596
Build: release
cargo 1.93.1 (083ac5135 2025-12-15)
rustc 1.93.1 (01f6ddf75 2026-02-11)



Discussion:

Patch:
diff --git a/crates/passes/src/common/block_to_function_rewriter.rs b/crates/passes/src/common/block_to_function_rewriter.rs
index 2cf57affaf..4bcdb657f0 100644
--- a/crates/passes/src/common/block_to_function_rewriter.rs
+++ b/crates/passes/src/common/block_to_function_rewriter.rs
@@ -141,7 +141,9 @@ impl BlockToFunctionRewriter<'_> {
                 match index_opt {
                     Some(index) => {
                         let Type::Tuple(TupleType { elements }) = var_type else {
-                            panic!("Expected tuple type when accessing tuple field: {symbol}.{index}");
+                            // The type checker has already emitted an error for this invalid access;
+                            // return no inputs so compilation can continue to report all diagnostics.
+                            return vec![];
                         };
 
                         let synthetic_name = format!("\"{symbol}.{index}\"");


Test patch:
diff --git a/tests/expectations/compiler/bugs/b29223_fail.out b/tests/expectations/compiler/bugs/b29223_fail.out
new file mode 100644
index 0000000000..ffd92c869e
--- /dev/null
+++ b/tests/expectations/compiler/bugs/b29223_fail.out
@@ -0,0 +1,10 @@
+Error [ETYC0372155]: Cannot assign to `p` inside a `final` block because it was declared outside the block.
+    --> compiler-test:7:13
+     |
+   7 |             p.0 = 1u32;
+     |             ^
+Error [ETYC0372117]: Expected a tuple but type `u32` was found.
+    --> compiler-test:7:13
+     |
+   7 |             p.0 = 1u32;
+     |             ^^^
diff --git a/tests/tests/compiler/bugs/b29223_fail.leo b/tests/tests/compiler/bugs/b29223_fail.leo
new file mode 100644
index 0000000000..944f2a9068
--- /dev/null
+++ b/tests/tests/compiler/bugs/b29223_fail.leo
@@ -0,0 +1,11 @@
+// Regression test for https://github.com/ProvableHQ/leo/issues/29223
+// The compiler should emit a type error, not panic, when a non-tuple variable
+// is accessed with a tuple field index inside a `final` block.
+program test.aleo {
+    fn foo(p: u32) -> Final {
+        let f = final {
+            p.0 = 1u32;
+        };
+        return f;
+    }
+}