aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2023-05-21 22:21:50 +0100
committermlugg <mlugg@mlugg.co.uk>2023-06-13 21:48:21 +0100
commit588f45a0a1492711b2cd9991ba8e9137e583e513 (patch)
tree8a10108df3ecdbef4102329b489b2a47dfbf8426 /src
parentc9531eb833e1e2c432dc2bfb0ca3b25622b7001e (diff)
downloadzig-588f45a0a1492711b2cd9991ba8e9137e583e513.tar.gz
zig-588f45a0a1492711b2cd9991ba8e9137e583e513.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig27
1 files changed, 25 insertions, 2 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index f0c64fb0b7..17867d1dd2 100644
--- a/src/Sema.zig
+++ b/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,