Commit 588f45a0a1

mlugg <mlugg@mlugg.co.uk>
2023-05-21 23:21:50
Sema: allow in-memory coercion of tuples
This allows tuples whose fields are in-memory coercible to themselves be coerced in memory. No InMemoryCoercionResult field has been added, so in future one could be added to improve error messages.
1 parent c9531eb
Changed files (1)
src/Sema.zig
@@ -27326,11 +27326,18 @@ fn coerceValueInMemory(
                         .fields.values()[i].ty.toIntern(),
                     else => unreachable,
                 };
-                dest_elem.* = try mod.intern_pool.getCoerced(mod.gpa, switch (aggregate.storage) {
+                const cur_val = switch (aggregate.storage) {
                     .bytes => |bytes| (try mod.intValue(Type.u8, bytes[i])).toIntern(),
                     .elems => |elems| elems[i],
                     .repeated_elem => |elem| elem,
-                }, elem_ty);
+                };
+                dest_elem.* = (try sema.coerceValueInMemory(
+                    block,
+                    cur_val.toValue(),
+                    mod.intern_pool.typeOf(cur_val).toType(),
+                    elem_ty.toType(),
+                    dst_ty_src,
+                )).toIntern();
             }
             return (try mod.intern(.{ .aggregate = .{
                 .ty = dst_ty.toIntern(),
@@ -27891,6 +27898,22 @@ fn coerceInMemoryAllowed(
         return .ok;
     }
 
+    // Tuples (with in-memory-coercible fields)
+    if (dest_ty.isTuple(mod) and src_ty.isTuple(mod)) tuple: {
+        if (dest_ty.containerLayout(mod) != src_ty.containerLayout(mod)) break :tuple;
+        if (dest_ty.structFieldCount(mod) != src_ty.structFieldCount(mod)) break :tuple;
+        const field_count = dest_ty.structFieldCount(mod);
+        for (0..field_count) |field_idx| {
+            if (dest_ty.structFieldIsComptime(field_idx, mod) != src_ty.structFieldIsComptime(field_idx, mod)) break :tuple;
+            if (dest_ty.structFieldAlign(field_idx, mod) != src_ty.structFieldAlign(field_idx, mod)) break :tuple;
+            const dest_field_ty = dest_ty.structFieldType(field_idx, mod);
+            const src_field_ty = src_ty.structFieldType(field_idx, mod);
+            const field = try sema.coerceInMemoryAllowed(block, dest_field_ty, src_field_ty, dest_is_mut, target, dest_src, src_src);
+            if (field != .ok) break :tuple;
+        }
+        return .ok;
+    }
+
     return InMemoryCoercionResult{ .no_match = .{
         .actual = dest_ty,
         .wanted = src_ty,