Passing an `*Io.Writer` or an `*Io.Writer.Discarding`

Hello!

Let’s say I have this function, which has to log stuff into a file, and I use a buffer and a writer like this:

const trace_file = try cwd.createFile(init.io, trace_path, .{ .read = false });
var trace_writer = trace_file.writer(init.io, &trace_buffer);
const twriter = &trace_writer.interface;

doSmth(..., twriter);

fn doSmth(args: types, trace: *Io.Writer) {
    try trace.writeAll("very important data"); 
}

Now, imagine this is costly, and I want to control at runtime if this file should be written or not. I can just pass an optional value and react accordingly:

doSmth(..., null);

fn doSmth(args: types, trace: ?*Io.Writer) {
    if (trace) |writer| { try trace.writeAll("very important data"); }
}

But then I saw the std.Io.Writer.Discarding and I thought I could get rid of the annoying null check if I do this!

var twriter = std.Io.Writer.Discarding.init(&.{});

doSmth(..., &twriter);

fn doSmth(args: types, trace: *Io.Writer) {
    try trace.writeAll("very important data"); 
}

If it’s a buffered writer it will write, and if it’s a Discarding (I suppose) Zig’s compiler will optimize this away.

But I coded that an I get the following error message:

src/main.zig:120:66: error: expected type '*Io.Writer', found '*Io.Writer.Discarding'
    const results = try simulation.v1(arena, rng, config, users, &twriter);
                                                                 ^~~~~~~~
src/main.zig:120:66: note: pointer type child 'Io.Writer.Discarding' cannot cast into pointer type child 'Io.Writer'
/home/pau/.zvm/master/lib/std/Io/Writer.zig:2384:24: note: struct declared here
pub const Discarding = struct {
                       ^~~~~~
/home/pau/.zvm/master/lib/std/Io/Writer.zig:1:1: note: struct declared here
const Writer = @This();
^~~~~
src/simulation.zig:44:82: note: parameter type declared here
pub fn v1(gpa: Allocator, rng: Random, simconf: SimConfig, users: []User, trace: *Io.Writer) !SimResults {

Am I doing something wrong? I assume so because this would be so perfect xd. If not, I could go back to the null or make this parameter a union maybe? regardless, that’s a little bit ugly.

Thank you :slight_smile:

Here’s the fix. Looking at the error message and the implementation of Io.Writer.Discarding should hopefully point you towards the “why”

var twriter = std.Io.Writer.Discarding.init(&.{});

doSmth(..., &twriter.writer);
1 Like

I would have been nice, but no, I did pass the pointer adequately at some point, and I’ve written the incorrect error message on the post xd. I am going to edit it now, thank you :))

// use the interface
doSmth(..., &twriter.writer);
1 Like

Okay, with the reply of @truly-not-taken i realized I was not just missing the pointer, but the .writer at the end.

Thank you you both!

1 Like