Why context in AnyWriter is const

Hi, I’m studying this PR: Add type-erased writer and GenericWriter by ianprime0509 · Pull Request #17634 · ziglang/zig · GitHub

context: *const anyopaque,
writeFn: *const fn (context: *const anyopaque, bytes: []const u8) anyerror!usize,

Since the write will go into the context, context must be mutable, so I think here it should be declared like context: *anyopaque.

Is there anything I’m missing?

if you look at usage, such as BufferedWriter you see the data behind the pointer is another non const pointer.

I think this is intentional to encourage you to keep the non-erased implementation available at some point, you can see in GenericWriter the context is copied, requiring it to be a pointer if the implementation has functionality that isn’t expressed in the interface such as BufferedWriter.flush.

Regardless, in 0.15 this will be replaced with an intrusive type erased interface without the generic layer that is overall a much better implementation.

1 Like

Yes, it’s a mutable pointer, I just want to know the reason why the declaration is a const pointer, since obviously it should be a mutable one.

One possible reason I can think of is that a const pointer is more general, and we can easy cast a const pointer to mutable with @constCast. If we declare the interface as a mutable pointer, then everything call that will need to be mutable, which more strict than before.

// Here my_file must be mutable if we declare context as mutable pointer
// However, since File only contains a fd, all read/write are done on it,
// there is nothing to be changed inside File, so it could be defined as const.
const file = File.open(...);
var wtr = my_file.writer();

Just a guess: I think the reason is because of the GenericWriter layer as stated, it copies the context meaning your original writer would not be modified so if you wanted to use functionality that isnt in generic writer you’d have to get the context out of the generic writer. Having a const pointer in AnyWriter forces you to make your writer context a non const pointer so you can mutate the data, since the context in GenericWriter is now a pointer you no longer need to extract it to use.

but it doesn’t really matter as the whole thing is being replaced next release which will be soon

I think this question is a generic one, and I just take the AnyWriter as an example, if we want to design an interface like Writer, how should we define our VTable? const pointer or mutable?

new reader/writer would be a better study, as an intrusive interface it doges that question entirely.

generally, interfaces should take mutable pointers to context, no telling what the implementation needs to do.