Pass a slice as a default value ptr to a comptime generated struct field

That’s a long name :slight_smile:

I am trying to grow up and parse my own CLI arguments, but I have kinda reached a dead end. I want to pass a slice as the default value ptr to this struct field I am creating, but I get this error, and I have zero idea what to do with it:

src/main.zig:20:10: error: expected type '?*const anyopaque', found '*const []const u8'
        .default_value_ptr = &slc,
        ~^~~~~~~~~~~~~~~~~~~~~~~~
src/main.zig:20:10: note: cannot implicitly cast double pointer '*const []const u8' to anyopaque pointer '?*const anyopaque'

This is the minimal code I could come up with for replicating the issue I’m having:

pub fn main() !void {
    const s = SomeStruct{};
    _ = s;
}

const arr = "012345";
const slc = f(arr[0..3]);

fn f(input: []const u8) []const u8 {
    return input;
}

const SomeStruct = @Type(.{ .@"struct" = .{
    .layout = .auto,
    .fields = &.{
        .name = "nesto",
        .type = []const u8,
        .default_value_ptr = &slc,
        .is_comptime = false,
        .alignment = 1,
    },
    .decls = &.{},
    .is_tuple = false,
} });

The code works if the value is for example some integer type, which kinda makes sense, but I still cannot really figure out why.

Thanks in advance! :slight_smile:

Zid does not allow implicit casting. For this you will need to @ptrCast to erase the type.

        .default_value_ptr = @ptrCast(&slc),
1 Like

Zig does not allow implicit casting.

It does allow *sometype => *anyopaque.
The key here is cannot implicitly cast *double* pointer .
The slice also counts as a pointer, so because you may also want to cast the inner pointer it does not do it implicitly. (from my understanding)

2 Likes

Thank yall!

This does solve the issue for the example I gave above, but not for my actual usecase. I did try this already but the usecase just crashes the compiler without any stack trace.

This is the type of &slc in my usecase. What am I missing here?

Compile Log Output:
@as(*const []const u8, &@as([]const u8, @as([*]const u8, @ptrCast(&@as([9]u8, "something".*)))[0..9]))

It looks really chaotic xD

I’m definitely doing something wrong with the slice there

Compile output log looks hairy, but if you read it from left to right, it makes sense.

The first as says that you have a constant pointer to a slice, the next on is the address of a slice, and the rest give the actual type of the slice.

The one thing I’m not sure on is how this behaves in comptime since you are creating a type, it will all be in comptime. I honestly haven’t done a lot with type generation of this sort, so I won’t be much further help. Are you getting any stack traces or compiler errors?

No stack traces, no compiler errors, but I did figure it out just now. Yay!

The problem was that I was passing a slice to a var array. When I changed it to const, it works as a charm! I remembered this topic I read today Comptime-Mutable Memory Changes by mlugg.

I will post the full code when finished, recreate the error. Maybe someone can take a look and see if I was just doing dumb things, if the compiler could have helped me more, or both :slight_smile:

1 Like

The following code passed the test

const arr = "012345";
const slc = f(arr[0..3]);

fn f(input: []const u8) []const u8 {
    return input;
}

const SomeStruct: type = @Type(.{ .@"struct" = .{
    .layout = .auto,
    .fields = &[_]std.builtin.Type.StructField{.{
        .name = "nesto",
        .type = []const u8,
        .default_value_ptr = @ptrCast(&slc),
        .is_comptime = false,
        .alignment = 1,
    }},
    .decls = &.{},
    .is_tuple = false,
} });

test SomeStruct {
    const s: SomeStruct = .{};
    try std.testing.expectEqualStrings("012", s.nesto);
}
1 Like