Commit 278db0ad45

Carl Åstholm <carl@astholm.se>
2024-02-13 22:30:14
Sema: support coercing ref to anonymous array init to many-pointer
1 parent fdd6c31
Changed files (2)
src
test
behavior
src/Sema.zig
@@ -4557,14 +4557,20 @@ fn zirValidateArrayInitRefTy(
     };
     const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(mod);
     assert(ptr_ty.zigTypeTag(mod) == .Pointer); // validated by a previous instruction
-    if (ptr_ty.isSlice(mod)) {
-        // Use array of correct length
-        const arr_ty = try mod.arrayType(.{
-            .len = extra.elem_count,
-            .child = ptr_ty.childType(mod).toIntern(),
-            .sentinel = if (ptr_ty.sentinel(mod)) |s| s.toIntern() else .none,
-        });
-        return Air.internedToRef(arr_ty.toIntern());
+    switch (mod.intern_pool.indexToKey(ptr_ty.toIntern())) {
+        .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
+            .Slice, .Many => {
+                // Use array of correct length
+                const arr_ty = try mod.arrayType(.{
+                    .len = extra.elem_count,
+                    .child = ptr_ty.childType(mod).toIntern(),
+                    .sentinel = if (ptr_ty.sentinel(mod)) |s| s.toIntern() else .none,
+                });
+                return Air.internedToRef(arr_ty.toIntern());
+            },
+            else => {},
+        },
+        else => {},
     }
     // Otherwise, we just want the pointer child type
     const ret_ty = ptr_ty.childType(mod);
test/behavior/array.zig
@@ -804,6 +804,52 @@ test "slice initialized through reference to anonymous array init provides resul
     try std.testing.expectEqualSlices(u16, &.{ 123, 456, 123, 456 }, foo);
 }
 
+test "sentinel-terminated slice initialized through reference to anonymous array init provides result types" {
+    var my_u32: u32 = 123;
+    var my_u64: u64 = 456;
+    _ = .{ &my_u32, &my_u64 };
+    const foo: [:999]const u16 = &.{
+        @intCast(my_u32),
+        @intCast(my_u64),
+        @truncate(my_u32),
+        @truncate(my_u64),
+    };
+    try std.testing.expectEqualSentinel(u16, 999, &.{ 123, 456, 123, 456 }, foo);
+}
+
+test "many-item pointer initialized through reference to anonymous array init provides result types" {
+    var my_u32: u32 = 123;
+    var my_u64: u64 = 456;
+    _ = .{ &my_u32, &my_u64 };
+    const foo: [*]const u16 = &.{
+        @intCast(my_u32),
+        @intCast(my_u64),
+        @truncate(my_u32),
+        @truncate(my_u64),
+    };
+    try expectEqual(123, foo[0]);
+    try expectEqual(456, foo[1]);
+    try expectEqual(123, foo[2]);
+    try expectEqual(456, foo[3]);
+}
+
+test "many-item sentinel-terminated pointer initialized through reference to anonymous array init provides result types" {
+    var my_u32: u32 = 123;
+    var my_u64: u64 = 456;
+    _ = .{ &my_u32, &my_u64 };
+    const foo: [*:999]const u16 = &.{
+        @intCast(my_u32),
+        @intCast(my_u64),
+        @truncate(my_u32),
+        @truncate(my_u64),
+    };
+    try expectEqual(123, foo[0]);
+    try expectEqual(456, foo[1]);
+    try expectEqual(123, foo[2]);
+    try expectEqual(456, foo[3]);
+    try expectEqual(999, foo[4]);
+}
+
 test "pointer to array initialized through reference to anonymous array init provides result types" {
     var my_u32: u32 = 123;
     var my_u64: u64 = 456;
@@ -817,6 +863,19 @@ test "pointer to array initialized through reference to anonymous array init pro
     try std.testing.expectEqualSlices(u16, &.{ 123, 456, 123, 456 }, foo);
 }
 
+test "pointer to sentinel-terminated array initialized through reference to anonymous array init provides result types" {
+    var my_u32: u32 = 123;
+    var my_u64: u64 = 456;
+    _ = .{ &my_u32, &my_u64 };
+    const foo: *const [4:999]u16 = &.{
+        @intCast(my_u32),
+        @intCast(my_u64),
+        @truncate(my_u32),
+        @truncate(my_u64),
+    };
+    try std.testing.expectEqualSentinel(u16, 999, &.{ 123, 456, 123, 456 }, foo);
+}
+
 test "tuple initialized through reference to anonymous array init provides result types" {
     const Tuple = struct { u64, *const u32 };
     const foo: *const Tuple = &.{