Commit d5f1a8823e

mlugg <mlugg@mlugg.co.uk>
2023-04-20 01:55:52
Sema: allow ptr field access on pointer-to-array
Also remove an incorrect piece of logic which allowed fetching the 'len' property on non-single-ptrs (e.g. many-ptrs) and add a corresponding compile error test case. Resolves: #4765
1 parent 31b6d14
Changed files (3)
src
test
behavior
cases
src/Sema.zig
@@ -23279,6 +23279,22 @@ fn fieldVal(
                     Type.usize,
                     try Value.Tag.int_u64.create(arena, inner_ty.arrayLen()),
                 );
+            } else if (mem.eql(u8, field_name, "ptr") and is_pointer_to) {
+                const ptr_info = object_ty.ptrInfo().data;
+                const result_ty = try Type.ptr(sema.arena, sema.mod, .{
+                    .pointee_type = ptr_info.pointee_type.childType(),
+                    .sentinel = ptr_info.sentinel,
+                    .@"align" = ptr_info.@"align",
+                    .@"addrspace" = ptr_info.@"addrspace",
+                    .bit_offset = ptr_info.bit_offset,
+                    .host_size = ptr_info.host_size,
+                    .vector_index = ptr_info.vector_index,
+                    .@"allowzero" = ptr_info.@"allowzero",
+                    .mutable = ptr_info.mutable,
+                    .@"volatile" = ptr_info.@"volatile",
+                    .size = .Many,
+                });
+                return sema.coerce(block, result_ty, object, src);
             } else {
                 return sema.fail(
                     block,
@@ -23311,20 +23327,6 @@ fn fieldVal(
                         .{ field_name, object_ty.fmt(sema.mod) },
                     );
                 }
-            } else if (ptr_info.pointee_type.zigTypeTag() == .Array) {
-                if (mem.eql(u8, field_name, "len")) {
-                    return sema.addConstant(
-                        Type.usize,
-                        try Value.Tag.int_u64.create(arena, ptr_info.pointee_type.arrayLen()),
-                    );
-                } else {
-                    return sema.fail(
-                        block,
-                        field_name_src,
-                        "no member named '{s}' in '{}'",
-                        .{ field_name, ptr_info.pointee_type.fmt(sema.mod) },
-                    );
-                }
             }
         },
         .Type => {
test/behavior/array.zig
@@ -677,3 +677,13 @@ test "array of array agregate init" {
     var b = [1][10]u32{a} ** 2;
     try std.testing.expect(b[1][1] == 11);
 }
+
+test "pointer to array has ptr field" {
+    const arr: *const [5]u32 = &.{ 10, 20, 30, 40, 50 };
+    try std.testing.expect(arr.ptr == @as([*]const u32, arr));
+    try std.testing.expect(arr.ptr[0] == 10);
+    try std.testing.expect(arr.ptr[1] == 20);
+    try std.testing.expect(arr.ptr[2] == 30);
+    try std.testing.expect(arr.ptr[3] == 40);
+    try std.testing.expect(arr.ptr[4] == 50);
+}
test/cases/compile_errors/len_access_on_array_many_ptr.zig
@@ -0,0 +1,10 @@
+export fn foo() void {
+    const x: [*][5]u8 = undefined;
+    _ = x.len;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :3:10: error: type '[*][5]u8' does not support field access