diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2023-05-21 22:21:50 +0100 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2023-06-13 21:48:21 +0100 |
| commit | 588f45a0a1492711b2cd9991ba8e9137e583e513 (patch) | |
| tree | 8a10108df3ecdbef4102329b489b2a47dfbf8426 /src | |
| parent | c9531eb833e1e2c432dc2bfb0ca3b25622b7001e (diff) | |
| download | zig-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.zig | 27 |
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, |
