const expect = @import("std").testing.expect; const print = @import("std").debug.print; // `opaque` types in Zig have an unknown (albeit non-zero) size and alignment. // Because of this these data types cannot be stored directly. // These are used to maintain type safety with pointers to types that we don't have information about. // ```zig // const Window = opaque {}; // const Button = opaque {}; // extern fn show_window(*Window) callconv(.C) void; // test "opaque" { // var main_window: *Window = undefined; // show_window(main_window); // var ok_button: *Button = undefined; // show_window(ok_button); // } //``` // ./test-c1.zig:653:17: error: expected type '*Window', found '*Button' // show_window(ok_button); // ^ // ./test-c1.zig:653:17: note: pointer type child 'Button' cannot cast into pointer type child 'Window' // show_window(ok_button); // ^ // Opaque types may have declarations in their definitions (the same as structs, enums and unions). // XXX: This is a C function that is not defined in the Zig code. extern fn show_window(*Window) callconv(.C) void; const Window = opaque { fn show(self: *Window) void { show_window(self); } }; test "opaque with declarations" { var main_window: *Window = undefined; main_window.show(); } // The typical usecase of opaque is to maintain type safety // when interoperating with C code that does not expose complete type information.