From abdfe27c2403a5330f5ef092f94da71fbb1cc11a Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sun, 23 Nov 2025 08:07:49 -0500 Subject: [PATCH] Fix multi-arg tuples --- src/eval/interpreter.zig | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/eval/interpreter.zig b/src/eval/interpreter.zig index 2ec8426976..51a6ab5b8d 100644 --- a/src/eval/interpreter.zig +++ b/src/eval/interpreter.zig @@ -1523,6 +1523,8 @@ pub const Interpreter = struct { const arg_count = args_exprs.len; var elem_layouts = try self.allocator.alloc(Layout, arg_count); defer self.allocator.free(elem_layouts); + var actual_elem_layouts = try self.allocator.alloc(Layout, arg_count); + defer self.allocator.free(actual_elem_layouts); var elem_values = try self.allocator.alloc(StackValue, arg_count); defer { for (elem_values[0..arg_count]) |val| { @@ -1532,13 +1534,53 @@ pub const Interpreter = struct { } var j: usize = 0; + var any_layout_differs = false; while (j < arg_count) : (j += 1) { const arg_rt_var = arg_rt_vars[j]; const val = try self.evalExprMinimal(args_exprs[j], roc_ops, arg_rt_var); elem_values[j] = val; elem_layouts[j] = try self.getRuntimeLayout(arg_rt_var); + actual_elem_layouts[j] = val.layout; + if (!layoutsEqual(elem_layouts[j], val.layout)) { + any_layout_differs = true; + } } + if (any_layout_differs) { + // Build payload tuple with ACTUAL layouts from evaluated values + const actual_tuple_idx = try self.runtime_layout_store.putTuple(actual_elem_layouts); + const actual_tuple_layout = self.runtime_layout_store.getLayout(actual_tuple_idx); + + // Create new outer tuple: (actual_payload_tuple, tag_discriminant) + var outer_elem_layouts = [2]Layout{ actual_tuple_layout, tag_field.layout }; + const proper_outer_idx = try self.runtime_layout_store.putTuple(&outer_elem_layouts); + const proper_outer_layout = self.runtime_layout_store.getLayout(proper_outer_idx); + var proper_dest = try self.pushRaw(proper_outer_layout, 0); + var proper_acc = try proper_dest.asTuple(&self.runtime_layout_store); + + // Write tag discriminant + const proper_tag_field = try proper_acc.getElement(1); + if (proper_tag_field.layout.tag == .scalar and proper_tag_field.layout.data.scalar.tag == .int) { + var tmp = proper_tag_field; + tmp.is_initialized = false; + try tmp.setInt(@intCast(tag_index)); + } + + // Write payload tuple + const proper_payload_field = try proper_acc.getElement(0); + if (proper_payload_field.ptr) |payload_ptr| { + var payload_dest = StackValue{ .layout = actual_tuple_layout, .ptr = payload_ptr, .is_initialized = true }; + var payload_acc = try payload_dest.asTuple(&self.runtime_layout_store); + j = 0; + while (j < elem_values.len) : (j += 1) { + try payload_acc.setElement(j, elem_values[j], roc_ops); + } + } + + return proper_dest; + } + + // Normal case: type system layouts match actual layouts const tuple_layout_idx = try self.runtime_layout_store.putTuple(elem_layouts); const tuple_layout = self.runtime_layout_store.getLayout(tuple_layout_idx);