Skip to content

Proposal: Allow coercing ref to anonymous array init to [*] and [*:x] #18924

@castholm

Description

@castholm
const std = @import("std");
const expectEqual = std.testing.expectEqual;

test "ref to anon array init coerced to slice" {
    const values: []const i32 = &.{ 1, -2 };
    try expectEqual(1, values[0]);
    try expectEqual(-2, values[1]);
    try expectEqual(2, values.len);
}

test "ref to anon array init coerced to sentinel slice" {
    const values: [:0]const i32 = &.{ 3, -4 };
    try expectEqual(3, values[0]);
    try expectEqual(-4, values[1]);
    try expectEqual(0, values[2]);
    try expectEqual(2, values.len);
}

test "ref to anon array init coerced to many-ptr" {
    const values: [*]const i32 = &.{ 5, -6 };
    try expectEqual(5, values[0]);
    try expectEqual(-6, values[1]);
}

test "ref to anon array init coerced to sentinel many-ptr" {
    const values: [*:0]const i32 = &.{ 7, -8 };
    try expectEqual(7, values[0]);
    try expectEqual(-8, values[1]);
    try expectEqual(0, values[2]);
}

The latter two tests currently do not compile:

repro.zig:20:36: error: type 'i32' does not support array initialization syntax
    const values: [*]const i32 = &.{ 5, -6 };
                                  ~^~~~~~~~~
repro.zig:26:38: error: type 'i32' does not support array initialization syntax
    const values: [*:0]const i32 = &.{ 7, -8 };
                                    ~^~~~~~~~~

Coercions from ref-to-anon-array-inits to slices are already supported, so I don't see why coercions to many-pointers shouldn't be. There is no ambiguity or risk of error at play and adding support for this is as simple as extending a single check in Sema.

Example of actual code of mine interacting with a C API where I'm currently running into this limitation and need to introduce awkward @as coercions:

fn glShaderSource(shader: c_uint, count: c_int, string: [*]const [*]const u8, length: ?[*]const c_int) void {}
fn glClearBufferfv(buffer: c_uint, drawbuffer: c_int, value: [*]const f32) void {}

const shader_source_preamble = "#version 410 core\n";
const vertex_shader_source = "void main() { gl_Position = vec4(0, 0, 0, 1); }\n";

glShaderSource(
    vertex_shader,
    2,
    &@as([2][*]const u8, .{ shader_source_preamble, vertex_shader_source }),
    &@as([2]c_int, .{ @intCast(shader_source_preamble.len), @intCast(vertex_shader_source.len) }),
);

glClearBufferfv(GL_COLOR, 0, @as([]const f32, &.{ 1, 1, 1, 1 }).ptr);

Supporting coercions from ref-to-anon-array-inits to many-pointers would make code like this much nicer to both read and write:

 glShaderSource(
     vertex_shader,
     2,
-    &@as([2][*]const u8, .{ shader_source_preamble, vertex_shader_source }),
-    &@as([2]c_int, .{ @intCast(shader_source_preamble.len), @intCast(vertex_shader_source.len) }),
+    &.{ shader_source_preamble, vertex_shader_source },
+    &.{ @intCast(shader_source_preamble.len), @intCast(vertex_shader_source.len) },
 );

-glClearBufferfv(GL_COLOR, 0, @as([]const f32, &.{ 1, 1, 1, 1 }).ptr);
+glClearBufferfv(GL_COLOR, 0, &.{ 1, 1, 1, 1 });

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedThis proposal is planned.proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions