Skip to content

Commit 95a3737

Browse files
authored
Merge pull request #6421 from tadeokondrak/opaque-syntax
Add opaque syntax that allows declarations
2 parents 3c43eec + bf4bfe5 commit 95a3737

27 files changed

+371
-211
lines changed

doc/docgen.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: anytype, source_token:
808808
.Keyword_noalias,
809809
.Keyword_noinline,
810810
.Keyword_nosuspend,
811+
.Keyword_opaque,
811812
.Keyword_or,
812813
.Keyword_orelse,
813814
.Keyword_packed,

doc/langref.html.in

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,7 +1988,7 @@ test "null terminated array" {
19881988
<li>Supports slice syntax: {#syntax#}ptr[start..end]{#endsyntax#}</li>
19891989
<li>Supports pointer arithmetic: {#syntax#}ptr + x{#endsyntax#}, {#syntax#}ptr - x{#endsyntax#}</li>
19901990
<li>{#syntax#}T{#endsyntax#} must have a known size, which means that it cannot be
1991-
{#syntax#}c_void{#endsyntax#} or any other {#link|opaque type|Opaque Types#}.</li>
1991+
{#syntax#}c_void{#endsyntax#} or any other {#link|opaque type|opaque#}.</li>
19921992
</ul>
19931993
</li>
19941994
</ul>
@@ -5545,7 +5545,7 @@ test "turn HashMap into a set with void" {
55455545
</p>
55465546
<p>
55475547
{#syntax#}void{#endsyntax#} is distinct from {#syntax#}c_void{#endsyntax#}, which is defined like this:
5548-
{#syntax#}pub const c_void = @Type(.Opaque);{#endsyntax#}.
5548+
{#syntax#}pub const c_void = opaque {};{#endsyntax#}.
55495549
{#syntax#}void{#endsyntax#} has a known size of 0 bytes, and {#syntax#}c_void{#endsyntax#} has an unknown, but non-zero, size.
55505550
</p>
55515551
<p>
@@ -8471,7 +8471,7 @@ test "integer truncation" {
84718471
<li>{#link|Error Set Type#}</li>
84728472
<li>{#link|Error Union Type#}</li>
84738473
<li>{#link|Vectors#}</li>
8474-
<li>{#link|Opaque Types#}</li>
8474+
<li>{#link|opaque#}</li>
84758475
<li>{#link|@Frame#}</li>
84768476
<li>{#syntax#}anyframe{#endsyntax#}</li>
84778477
<li>{#link|struct#}</li>
@@ -8547,17 +8547,18 @@ fn foo(comptime T: type, ptr: *T) T {
85478547
{#header_close#}
85488548
{#header_close#}
85498549

8550-
{#header_open|Opaque Types#}
8550+
{#header_open|opaque#}
85518551
<p>
8552-
{#syntax#}@Type(.Opaque){#endsyntax#} creates a new type with an unknown (but non-zero) size and alignment.
8552+
{#syntax#}opaque {}{#endsyntax#} declares a new type with an unknown (but non-zero) size and alignment.
8553+
It can have declarations like structs, unions, or enums.
85538554
</p>
85548555
<p>
85558556
This is typically used for type safety when interacting with C code that does not expose struct details.
85568557
Example:
85578558
</p>
85588559
{#code_begin|test_err|expected type '*Derp', found '*Wat'#}
8559-
const Derp = @Type(.Opaque);
8560-
const Wat = @Type(.Opaque);
8560+
const Derp = opaque {};
8561+
const Wat = opaque {};
85618562

85628563
extern fn bar(d: *Derp) void;
85638564
fn foo(w: *Wat) callconv(.C) void {
@@ -11193,7 +11194,7 @@ PtrTypeStart
1119311194
ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE
1119411195

1119511196
ContainerDeclType
11196-
&lt;- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)?
11197+
&lt;- (KEYWORD_struct / KEYWORD_enum / KEYWORD_opaque) (LPAREN Expr RPAREN)?
1119711198
/ KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
1119811199

1119911200
# Alignment
@@ -11340,6 +11341,7 @@ KEYWORD_inline &lt;- 'inline' end_of_word
1134011341
KEYWORD_noalias &lt;- 'noalias' end_of_word
1134111342
KEYWORD_nosuspend &lt;- 'nosuspend' end_of_word
1134211343
KEYWORD_null &lt;- 'null' end_of_word
11344+
KEYWORD_opaque &lt;- 'opaque' end_of_word
1134311345
KEYWORD_or &lt;- 'or' end_of_word
1134411346
KEYWORD_orelse &lt;- 'orelse' end_of_word
1134511347
KEYWORD_packed &lt;- 'packed' end_of_word
@@ -11368,7 +11370,7 @@ keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_anyframe / KEYWORD_anytype
1136811370
/ KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer
1136911371
/ KEYWORD_error / KEYWORD_export / KEYWORD_extern / KEYWORD_false
1137011372
/ KEYWORD_fn / KEYWORD_for / KEYWORD_if / KEYWORD_inline
11371-
/ KEYWORD_noalias / KEYWORD_null / KEYWORD_or
11373+
/ KEYWORD_noalias / KEYWORD_null / KEYWORD_opaque / KEYWORD_or
1137211374
/ KEYWORD_orelse / KEYWORD_packed / KEYWORD_pub
1137311375
/ KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
1137411376
/ KEYWORD_struct / KEYWORD_suspend

lib/std/builtin.zig

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ pub const TypeInfo = union(enum) {
198198
Union: Union,
199199
Fn: Fn,
200200
BoundFn: Fn,
201-
Opaque: void,
201+
Opaque: Opaque,
202202
Frame: Frame,
203203
AnyFrame: AnyFrame,
204204
Vector: Vector,
@@ -359,6 +359,12 @@ pub const TypeInfo = union(enum) {
359359
args: []const FnArg,
360360
};
361361

362+
/// This data structure is used by the Zig language code generation and
363+
/// therefore must be kept in sync with the compiler implementation.
364+
pub const Opaque = struct {
365+
decls: []const Declaration,
366+
};
367+
362368
/// This data structure is used by the Zig language code generation and
363369
/// therefore must be kept in sync with the compiler implementation.
364370
pub const Frame = struct {

lib/std/c.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,8 @@ pub extern "c" fn pthread_cond_signal(cond: *pthread_cond_t) c_int;
329329
pub extern "c" fn pthread_cond_broadcast(cond: *pthread_cond_t) c_int;
330330
pub extern "c" fn pthread_cond_destroy(cond: *pthread_cond_t) c_int;
331331

332-
pub const pthread_t = *@Type(.Opaque);
333-
pub const FILE = @Type(.Opaque);
332+
pub const pthread_t = *opaque {};
333+
pub const FILE = opaque {};
334334

335335
pub extern "c" fn dlopen(path: [*:0]const u8, mode: c_int) ?*c_void;
336336
pub extern "c" fn dlclose(handle: *c_void) c_int;

lib/std/os/linux/bpf/kern.zig

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,28 @@ const in_bpf_program = switch (std.builtin.arch) {
1212

1313
pub const helpers = if (in_bpf_program) @import("helpers.zig") else struct {};
1414

15-
pub const BpfSock = @Type(.Opaque);
16-
pub const BpfSockAddr = @Type(.Opaque);
17-
pub const FibLookup = @Type(.Opaque);
18-
pub const MapDef = @Type(.Opaque);
19-
pub const PerfEventData = @Type(.Opaque);
20-
pub const PerfEventValue = @Type(.Opaque);
21-
pub const PidNsInfo = @Type(.Opaque);
22-
pub const SeqFile = @Type(.Opaque);
23-
pub const SkBuff = @Type(.Opaque);
24-
pub const SkMsgMd = @Type(.Opaque);
25-
pub const SkReusePortMd = @Type(.Opaque);
26-
pub const Sock = @Type(.Opaque);
27-
pub const SockAddr = @Type(.Opaque);
28-
pub const SockOps = @Type(.Opaque);
29-
pub const SockTuple = @Type(.Opaque);
30-
pub const SpinLock = @Type(.Opaque);
31-
pub const SysCtl = @Type(.Opaque);
32-
pub const Tcp6Sock = @Type(.Opaque);
33-
pub const TcpRequestSock = @Type(.Opaque);
34-
pub const TcpSock = @Type(.Opaque);
35-
pub const TcpTimewaitSock = @Type(.Opaque);
36-
pub const TunnelKey = @Type(.Opaque);
37-
pub const Udp6Sock = @Type(.Opaque);
38-
pub const XdpMd = @Type(.Opaque);
39-
pub const XfrmState = @Type(.Opaque);
15+
pub const BpfSock = opaque {};
16+
pub const BpfSockAddr = opaque {};
17+
pub const FibLookup = opaque {};
18+
pub const MapDef = opaque {};
19+
pub const PerfEventData = opaque {};
20+
pub const PerfEventValue = opaque {};
21+
pub const PidNsInfo = opaque {};
22+
pub const SeqFile = opaque {};
23+
pub const SkBuff = opaque {};
24+
pub const SkMsgMd = opaque {};
25+
pub const SkReusePortMd = opaque {};
26+
pub const Sock = opaque {};
27+
pub const SockAddr = opaque {};
28+
pub const SockOps = opaque {};
29+
pub const SockTuple = opaque {};
30+
pub const SpinLock = opaque {};
31+
pub const SysCtl = opaque {};
32+
pub const Tcp6Sock = opaque {};
33+
pub const TcpRequestSock = opaque {};
34+
pub const TcpSock = opaque {};
35+
pub const TcpTimewaitSock = opaque {};
36+
pub const TunnelKey = opaque {};
37+
pub const Udp6Sock = opaque {};
38+
pub const XdpMd = opaque {};
39+
pub const XfrmState = opaque {};

lib/std/os/uefi.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub var handle: Handle = undefined;
1717
pub var system_table: *tables.SystemTable = undefined;
1818

1919
/// A handle to an event structure.
20-
pub const Event = *@Type(.Opaque);
20+
pub const Event = *opaque {};
2121

2222
/// GUIDs must be align(8)
2323
pub const Guid = extern struct {
@@ -51,7 +51,7 @@ pub const Guid = extern struct {
5151
};
5252

5353
/// An EFI Handle represents a collection of related interfaces.
54-
pub const Handle = *@Type(.Opaque);
54+
pub const Handle = *opaque {};
5555

5656
/// This structure represents time information.
5757
pub const Time = extern struct {
@@ -108,4 +108,4 @@ pub const TimeCapabilities = extern struct {
108108
};
109109

110110
/// File Handle as specified in the EFI Shell Spec
111-
pub const FileHandle = *@Type(.Opaque);
111+
pub const FileHandle = *opaque {};

lib/std/os/uefi/protocols/hii.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
const uefi = @import("std").os.uefi;
77
const Guid = uefi.Guid;
88

9-
pub const HIIHandle = *@Type(.Opaque);
9+
pub const HIIHandle = *opaque {};
1010

1111
/// The header found at the start of each package.
1212
pub const HIIPackageHeader = packed struct {

lib/std/os/windows/bits.zig

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ pub const UCHAR = u8;
3232
pub const FLOAT = f32;
3333
pub const HANDLE = *c_void;
3434
pub const HCRYPTPROV = ULONG_PTR;
35-
pub const HBRUSH = *@Type(.Opaque);
36-
pub const HCURSOR = *@Type(.Opaque);
37-
pub const HICON = *@Type(.Opaque);
38-
pub const HINSTANCE = *@Type(.Opaque);
39-
pub const HMENU = *@Type(.Opaque);
40-
pub const HMODULE = *@Type(.Opaque);
41-
pub const HWND = *@Type(.Opaque);
42-
pub const HDC = *@Type(.Opaque);
43-
pub const HGLRC = *@Type(.Opaque);
44-
pub const FARPROC = *@Type(.Opaque);
35+
pub const HBRUSH = *opaque {};
36+
pub const HCURSOR = *opaque {};
37+
pub const HICON = *opaque {};
38+
pub const HINSTANCE = *opaque {};
39+
pub const HMENU = *opaque {};
40+
pub const HMODULE = *opaque {};
41+
pub const HWND = *opaque {};
42+
pub const HDC = *opaque {};
43+
pub const HGLRC = *opaque {};
44+
pub const FARPROC = *opaque {};
4545
pub const INT = c_int;
4646
pub const LPBYTE = *BYTE;
4747
pub const LPCH = *CHAR;
@@ -81,7 +81,7 @@ pub const WPARAM = usize;
8181
pub const LPARAM = ?*c_void;
8282
pub const LRESULT = ?*c_void;
8383

84-
pub const va_list = *@Type(.Opaque);
84+
pub const va_list = *opaque {};
8585

8686
pub const TRUE = 1;
8787
pub const FALSE = 0;
@@ -1175,10 +1175,10 @@ pub const UNICODE_STRING = extern struct {
11751175
Buffer: [*]WCHAR,
11761176
};
11771177

1178-
const ACTIVATION_CONTEXT_DATA = @Type(.Opaque);
1179-
const ASSEMBLY_STORAGE_MAP = @Type(.Opaque);
1180-
const FLS_CALLBACK_INFO = @Type(.Opaque);
1181-
const RTL_BITMAP = @Type(.Opaque);
1178+
const ACTIVATION_CONTEXT_DATA = opaque {};
1179+
const ASSEMBLY_STORAGE_MAP = opaque {};
1180+
const FLS_CALLBACK_INFO = opaque {};
1181+
const RTL_BITMAP = opaque {};
11821182
pub const PRTL_BITMAP = *RTL_BITMAP;
11831183
const KAFFINITY = usize;
11841184

lib/std/os/windows/ws2_32.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// and substantial portions of the software.
66
usingnamespace @import("bits.zig");
77

8-
pub const SOCKET = *@Type(.Opaque);
8+
pub const SOCKET = *opaque {};
99
pub const INVALID_SOCKET = @intToPtr(SOCKET, ~@as(usize, 0));
1010
pub const SOCKET_ERROR = -1;
1111

lib/std/zig/ast.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ pub const Error = union(enum) {
288288
pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found '{}'");
289289
pub const ExpectedFn = SingleTokenError("Expected function, found '{}'");
290290
pub const ExpectedReturnType = SingleTokenError("Expected 'var' or return type expression, found '{}'");
291-
pub const ExpectedAggregateKw = SingleTokenError("Expected '" ++ Token.Id.Keyword_struct.symbol() ++ "', '" ++ Token.Id.Keyword_union.symbol() ++ "', or '" ++ Token.Id.Keyword_enum.symbol() ++ "', found '{}'");
291+
pub const ExpectedAggregateKw = SingleTokenError("Expected '" ++ Token.Id.Keyword_struct.symbol() ++ "', '" ++ Token.Id.Keyword_union.symbol() ++ "', '" ++ Token.Id.Keyword_enum.symbol() ++ "', or '" ++ Token.Id.Keyword_opaque.symbol() ++ "', found '{}'");
292292
pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found '{}'");
293293
pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found '{}'");
294294
pub const ExpectedSemiOrElse = SingleTokenError("Expected ';' or 'else', found '{}'");

lib/std/zig/parse.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2896,11 +2896,12 @@ const Parser = struct {
28962896
/// <- KEYWORD_struct
28972897
/// / KEYWORD_enum (LPAREN Expr RPAREN)?
28982898
/// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
2899+
/// / KEYWORD_opaque
28992900
fn parseContainerDeclType(p: *Parser) !?ContainerDeclType {
29002901
const kind_token = p.nextToken();
29012902

29022903
const init_arg_expr = switch (p.token_ids[kind_token]) {
2903-
.Keyword_struct => Node.ContainerDecl.InitArg{ .None = {} },
2904+
.Keyword_struct, .Keyword_opaque => Node.ContainerDecl.InitArg{ .None = {} },
29042905
.Keyword_enum => blk: {
29052906
if (p.eatToken(.LParen) != null) {
29062907
const expr = try p.expectNode(parseExpr, .{

lib/std/zig/render.zig

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1492,7 +1492,19 @@ fn renderExpression(
14921492

14931493
// TODO remove after 0.7.0 release
14941494
if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@OpaqueType"))
1495-
return ais.writer().writeAll("@Type(.Opaque)");
1495+
return ais.writer().writeAll("opaque {}");
1496+
1497+
// TODO remove after 0.7.0 release
1498+
{
1499+
const params = builtin_call.paramsConst();
1500+
if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@Type") and
1501+
params.len == 1)
1502+
{
1503+
if (params[0].castTag(.EnumLiteral)) |enum_literal|
1504+
if (mem.eql(u8, tree.tokenSlice(enum_literal.name), "Opaque"))
1505+
return ais.writer().writeAll("opaque {}");
1506+
}
1507+
}
14961508

14971509
try renderToken(tree, ais, builtin_call.builtin_token, Space.None); // @name
14981510

lib/std/zig/tokenizer.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub const Token = struct {
4747
.{ "noinline", .Keyword_noinline },
4848
.{ "nosuspend", .Keyword_nosuspend },
4949
.{ "null", .Keyword_null },
50+
.{ "opaque", .Keyword_opaque },
5051
.{ "or", .Keyword_or },
5152
.{ "orelse", .Keyword_orelse },
5253
.{ "packed", .Keyword_packed },
@@ -173,6 +174,7 @@ pub const Token = struct {
173174
Keyword_noinline,
174175
Keyword_nosuspend,
175176
Keyword_null,
177+
Keyword_opaque,
176178
Keyword_or,
177179
Keyword_orelse,
178180
Keyword_packed,
@@ -296,6 +298,7 @@ pub const Token = struct {
296298
.Keyword_noinline => "noinline",
297299
.Keyword_nosuspend => "nosuspend",
298300
.Keyword_null => "null",
301+
.Keyword_opaque => "opaque",
299302
.Keyword_or => "or",
300303
.Keyword_orelse => "orelse",
301304
.Keyword_packed => "packed",

0 commit comments

Comments
 (0)