Error with error!string union initialization

I would like to initialize an error/string union (std.mem.Allocator.Error![]const u8) and then assign the return value of a function to this union.
But the following code fail with zig test mytest.zig:

const std = @import("std");

test "my test" {
    const phrase = "test";
    std.debug.print("input: {s}\n",.{phrase});
    var o:std.mem.Allocator.Error![]const u8 = "";
    std.debug.print("typeof(o): {}\n",.{@TypeOf(o)});
    
    o = try isoReturn(std.testing.allocator,phrase); 
    defer std.testing.allocator.free(o);

}

pub fn isoReturn(allocator: std.mem.Allocator, phrase: []const u8) std.mem.Allocator.Error![]const u8 {

    var o = try allocator.alloc(u8, phrase.len);
    for (phrase, 0..) |c,i| {
        o[i] = c;
    }
    return o;
}

With this error message:

$ zig test test.zig
/Users/[..]/lib/std/mem/Allocator.zig:308:45: error: access of union field 'pointer' while field 'error_union' is active
    const Slice = @typeInfo(@TypeOf(memory)).pointer;
                  ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
/Users/[..]/lib/std/builtin.zig:556:18: note: union declared here
pub const Type = union(enum) {
                 ^~~~~

But if I declare the union directly with the function call (like: const o = try isoReturn(testing.allocator,phrase); ) I get no error and everything seems to works fine:

Code with union declaration directly with function call
const std = @import("std");

test "my test" {
    const phrase = "text";
    std.debug.print("input: {s}\n",.{phrase});
    
    const o = try isoReturn(std.testing.allocator,phrase); 
    defer std.testing.allocator.free(o);
    std.debug.print("output: {s}\n",.{o});
}

pub fn isoReturn(allocator: std.mem.Allocator, phrase: []const u8) std.mem.Allocator.Error![]const u8 {

    var o = try allocator.alloc(u8, phrase.len);
    for (phrase, 0..) |c,i| {
        o[i] = c;
    }
    return o;
}

Questions

Why my first code fail? If it is because of the union initialization, how to properly make the initialization in this case?

$ zig version
0.14.0-dev.2370+5c6b25d9b

Free expects a slice, but you’re passing it an error union (Allocator.Error![]u8), which is what you declared o to be.

isoReturn returns an error union. try peels away the error part, so o is deduced to be []u8, whichs is what free expects.

2 Likes