authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-19 10:38:24-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-19 10:38:24-07:00
logb0f6889d121cae004687e381cd7b0d8156490433
tree5c7a7f232de11e5cbba8f20a361b7cbf3b5ae93b
parent9b177a7d21250b82cd18677c5c71ab04e431120d
parent571388a93d773e02aa88173d0ffec32ff2852e61

Merge pull request 'docs: langref: Clear up terminology used for top-level doc comments' (#31920) into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31920 Reviewed-by: Andrew Kelley <andrew@ziglang.org>

10 files changed, 143 insertions(+), 167 deletions(-)

doc/langref.html.in+50-73
...@@ -388,22 +388,15 @@...@@ -388,22 +388,15 @@
388 </p>388 </p>
389 {#see_also|Values|Tuples|@import|Errors|Entry Point|Source Encoding|try#}389 {#see_also|Values|Tuples|@import|Errors|Entry Point|Source Encoding|try#}
390 {#header_close#}390 {#header_close#}
391
391 {#header_open|Comments#}392 {#header_open|Comments#}
392 <p>393 <p>There are three types of comments. Normal comments are ignored, while {#link|Doc Comments#}
393 Zig supports 3 types of comments. Normal comments are ignored, but doc comments394 and {#link|Top-Level Doc Comments#} are used by the compiler to generate
394 and top-level doc comments are used by the compiler to generate the package documentation.395 the package documentation.</p>
395 </p>
396 <p>
397 The generated documentation is still experimental, and can be produced with:
398 </p>
399 {#shell_samp#}zig test -femit-docs main.zig{#end_shell_samp#}
400 {#code|comments.zig#}396 {#code|comments.zig#}
401397
402 <p>398 <p>There are no multiline comments. Zig has the property that each line
403 There are no multiline comments in Zig (e.g. like <code class="c">/* */</code>399 of code can be tokenized independently.</p>
404 comments in C). This allows Zig to have the property that each line
405 of code can be tokenized out of context.
406 </p>
407 {#header_open|Doc Comments#}400 {#header_open|Doc Comments#}
408 <p>401 <p>
409 A doc comment is one that begins with exactly three slashes (i.e.402 A doc comment is one that begins with exactly three slashes (i.e.
...@@ -429,17 +422,28 @@...@@ -429,17 +422,28 @@
429 {#header_open|Top-Level Doc Comments#}422 {#header_open|Top-Level Doc Comments#}
430 <p>423 <p>
431 A top-level doc comment is one that begins with two slashes and an exclamation424 A top-level doc comment is one that begins with two slashes and an exclamation
432 point: {#syntax#}//!{#endsyntax#}; it documents the current module.425 point: {#syntax#}//!{#endsyntax#}; it documents the type which owns the containing
426 {#link|Namespace#}.
433 </p>427 </p>
434 <p>428 <p>
435 It is a compile error if a top-level doc comment is not placed at the start429 It is a compile error if a top-level doc comment is not placed at the start
436 of a {#link|container|Containers#}, before any expressions.430 of a namespace, before any expressions.
437 </p>431 </p>
438 {#code|tldoc_comments.zig#}432 {#code|tldoc_comments.zig#}
439433
440 {#header_close#}434 {#header_close#}
441 {#header_close#}435 {#header_close#}
442436
437 {#header_open|Namespace#}
438 <p>A namespace in Zig is created by {#link|struct#}, {#link|enum#}, {#link|union#}, and {#link|opaque#}.</p>
439 <p>They contain {#link|Namespace Level Variables#},
440 {#link|function|Functions#} declarations, and {#link|comptime#} blocks.</p>
441 <p>Although namespaces use curly braces to surround their definition,
442 they should not be confused with {#link|blocks|Blocks#} or function bodies.</p>
443 <p><strong>Every Zig source file is implicitly a struct</strong>, with the keyword
444 {#syntax#}struct{#endsyntax#} and curly braces omitted.</p>
445 {#header_close#}
446
443 {#header_open|Identifiers#}447 {#header_open|Identifiers#}
444 <p>448 <p>
445 Identifiers must start with an alphabetic character or underscore and may be followed449 Identifiers must start with an alphabetic character or underscore and may be followed
...@@ -813,7 +817,7 @@...@@ -813,7 +817,7 @@
813 {#code|destructuring_to_existing.zig#}817 {#code|destructuring_to_existing.zig#}
814818
815 <p>819 <p>
816 A destructuring expression may only appear within a block (i.e. not at container scope).820 A destructuring expression may only appear within a block (i.e. not at {#link|Namespace#} scope).
817 The left hand side of the assignment must consist of a comma separated list,821 The left hand side of the assignment must consist of a comma separated list,
818 each element of which may be either an lvalue (for instance, an existing `var`) or a variable declaration:822 each element of which may be either an lvalue (for instance, an existing `var`) or a variable declaration:
819 </p>823 </p>
...@@ -993,27 +997,23 @@...@@ -993,27 +997,23 @@
993 </p>997 </p>
994 {#see_also|Exporting a C Library#}998 {#see_also|Exporting a C Library#}
995999
996 {#header_open|Container Level Variables#}1000 {#header_open|Namespace Level Variables#}
997 <p>1001 <p>{#link|Namespace|Namespace#} level variables have global lifetime and are
998 {#link|Container|Containers#} level variables have static lifetime and are order-independent and lazily analyzed.1002 order-independent and lazily analyzed. The initialization value of
999 The initialization value of container level variables is implicitly1003 namespace level variables is implicitly {#link|comptime#}. If a namespace
1000 {#link|comptime#}. If a container level variable is {#syntax#}const{#endsyntax#} then its value is1004 level variable is {#syntax#}const{#endsyntax#} then its value is
1001 {#syntax#}comptime{#endsyntax#}-known, otherwise it is runtime-known.1005 {#syntax#}comptime{#endsyntax#}-known, otherwise it is runtime-known.</p>
1002 </p>1006 {#code|test_namespace_level_variables.zig#}
1003 {#code|test_container_level_variables.zig#}1007 <p>Namespace level variables may be declared inside a {#link|struct#},
10041008 {#link|union#}, {#link|enum#}, or {#link|opaque#}:</p>
1005 <p>1009 {#code|test_namespaced_variable.zig#}
1006 Container level variables may be declared inside a {#link|struct#}, {#link|union#}, {#link|enum#}, or {#link|opaque#}:
1007 </p>
1008 {#code|test_namespaced_container_level_variable.zig#}
10091010
1010 {#header_close#}1011 {#header_close#}
10111012
1012 {#header_open|Static Local Variables#}1013 {#header_open|Locally-Scoped Global Variables#}
1013 <p>1014 <p>It is also possible to have local variables with global lifetime by
1014 It is also possible to have local variables with static lifetime by using containers inside functions.1015 using {#link|namespaces|Namespace#} inside functions.</p>
1015 </p>1016 {#code|test_locally_scoped_global_variable.zig#}
1016 {#code|test_static_local_variable.zig#}
10171017
1018 {#header_close#}1018 {#header_close#}
10191019
...@@ -1022,10 +1022,8 @@...@@ -1022,10 +1022,8 @@
1022 {#syntax#}threadlocal{#endsyntax#} keyword,1022 {#syntax#}threadlocal{#endsyntax#} keyword,
1023 which makes each thread work with a separate instance of the variable:</p>1023 which makes each thread work with a separate instance of the variable:</p>
1024 {#code|test_thread_local_variables.zig#}1024 {#code|test_thread_local_variables.zig#}
10251025 <p>For {#link|Single Threaded Builds#}, all thread local variables are
1026 <p>1026 treated as regular {#link|Namespace Level Variables#}.</p>
1027 For {#link|Single Threaded Builds#}, all thread local variables are treated as regular {#link|Container Level Variables#}.
1028 </p>
1029 <p>1027 <p>
1030 Thread local variables may not be {#syntax#}const{#endsyntax#}.1028 Thread local variables may not be {#syntax#}const{#endsyntax#}.
1031 </p>1029 </p>
...@@ -2470,7 +2468,7 @@ or...@@ -2470,7 +2468,7 @@ or
2470 <p>Unions can be declared with an enum tag type.2468 <p>Unions can be declared with an enum tag type.
2471 This turns the union into a <em>tagged</em> union, which makes it eligible2469 This turns the union into a <em>tagged</em> union, which makes it eligible
2472 to use with {#link|switch#} expressions. When switching on tagged unions,2470 to use with {#link|switch#} expressions. When switching on tagged unions,
2473 the tag value can be obtained using an additional capture. 2471 the tag value can be obtained using an additional capture.
2474 Tagged unions coerce to their tag type: {#link|Type Coercion: Unions and Enums#}.2472 Tagged unions coerce to their tag type: {#link|Type Coercion: Unions and Enums#}.
2475 </p>2473 </p>
2476 {#code|test_tagged_union.zig#}2474 {#code|test_tagged_union.zig#}
...@@ -4123,13 +4121,11 @@ fn performFn(start_value: i32) i32 {...@@ -4123,13 +4121,11 @@ fn performFn(start_value: i32) i32 {
4123 </p>4121 </p>
4124 {#code|test_fibonacci_comptime_unreachable.zig#}4122 {#code|test_fibonacci_comptime_unreachable.zig#}
41254123
41264124 <p>At {#link|Namespace#} level (outside of any function), all expressions
4127 <p>4125 are implicitly {#syntax#}comptime{#endsyntax#} expressions. This means
4128 At {#link|container|Containers#} level (outside of any function), all expressions are implicitly4126 that we can use functions to initialize complex constant data. For
4129 {#syntax#}comptime{#endsyntax#} expressions. This means that we can use functions to4127 example:</p>
4130 initialize complex static data. For example:4128 {#code|test_namespace-level_comptime_expressions.zig#}
4131 </p>
4132 {#code|test_container-level_comptime_expressions.zig#}
41334129
4134 <p>4130 <p>
4135 When we compile this program, Zig generates the constants4131 When we compile this program, Zig generates the constants
...@@ -4309,7 +4305,7 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void {...@@ -4309,7 +4305,7 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void {
43094305
4310 {#header_open|Global Assembly#}4306 {#header_open|Global Assembly#}
4311 <p>4307 <p>
4312 When an assembly expression occurs in a {#link|container|Containers#} level {#link|comptime#} block, this is4308 When an assembly expression occurs in a {#link|Namespace#} level {#link|comptime#} block, this is
4313 <strong>global assembly</strong>.4309 <strong>global assembly</strong>.
4314 </p>4310 </p>
4315 <p>4311 <p>
...@@ -4946,25 +4942,18 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -4946,25 +4942,18 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
4946 {#header_close#}4942 {#header_close#}
49474943
4948 {#header_open|@hasDecl#}4944 {#header_open|@hasDecl#}
4949 <pre>{#syntax#}@hasDecl(comptime Container: type, comptime name: []const u8) bool{#endsyntax#}</pre>4945 <pre>{#syntax#}@hasDecl(comptime Namespace: type, comptime name: []const u8) bool{#endsyntax#}</pre>
4950 <p>4946 <p>Returns whether or not a {#link|Namespace#} has a declaration matching {#syntax#}name{#endsyntax#}.</p>
4951 Returns whether or not a {#link|container|Containers#} has a declaration
4952 matching {#syntax#}name{#endsyntax#}.
4953 </p>
4954 {#code|test_hasDecl_builtin.zig#}4947 {#code|test_hasDecl_builtin.zig#}
49554948
4956 {#see_also|@hasField#}4949 {#see_also|@hasField#}
4957 {#header_close#}4950 {#header_close#}
49584951
4959 {#header_open|@hasField#}4952 {#header_open|@hasField#}
4960 <pre>{#syntax#}@hasField(comptime Container: type, comptime name: []const u8) bool{#endsyntax#}</pre>4953 <pre>{#syntax#}@hasField(comptime T: type, comptime name: []const u8) bool{#endsyntax#}</pre>
4961 <p>Returns whether the field name of a struct, union, or enum exists.</p>4954 <p>Returns whether the field name of a struct, union, or enum exists.</p>
4962 <p>4955 <p>The result is a compile time constant.</p>
4963 The result is a compile time constant.4956 <p>It does not include functions, variables, or constants.</p>
4964 </p>
4965 <p>
4966 It does not include functions, variables, or constants.
4967 </p>
4968 {#see_also|@hasDecl#}4957 {#see_also|@hasDecl#}
4969 {#header_close#}4958 {#header_close#}
49704959
...@@ -5980,7 +5969,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -5980,7 +5969,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
5980 {#header_open|Single Threaded Builds#}5969 {#header_open|Single Threaded Builds#}
5981 <p>Zig has a compile option <kbd>-fsingle-threaded</kbd> which has the following effects:</p>5970 <p>Zig has a compile option <kbd>-fsingle-threaded</kbd> which has the following effects:</p>
5982 <ul>5971 <ul>
5983 <li>All {#link|Thread Local Variables#} are treated as regular {#link|Container Level Variables#}.</li>5972 <li>All {#link|Thread Local Variables#} are treated as regular {#link|Namespace Level Variables#}.</li>
5984 <li>The overhead of {#link|Async Functions#} becomes equivalent to function call overhead.</li>5973 <li>The overhead of {#link|Async Functions#} becomes equivalent to function call overhead.</li>
5985 <li>The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#}5974 <li>The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#}
5986 and therefore various userland APIs which read this variable become more efficient.5975 and therefore various userland APIs which read this variable become more efficient.
...@@ -6635,7 +6624,7 @@ const builtin = @import("builtin");...@@ -6635,7 +6624,7 @@ const builtin = @import("builtin");
6635 {#header_open|Panic Handler#}6624 {#header_open|Panic Handler#}
6636 <p>6625 <p>
6637 The Zig Standard Library looks for a declaration named {#syntax#}panic{#endsyntax#} in the root module's6626 The Zig Standard Library looks for a declaration named {#syntax#}panic{#endsyntax#} in the root module's
6638 root source file. If present, it is expected to be a namespace (container type) with declarations6627 root source file. If present, it is expected to be a {#link|Namespace#} with declarations
6639 providing different panic handlers.6628 providing different panic handlers.
6640 </p>6629 </p>
6641 <p>6630 <p>
...@@ -7755,18 +7744,6 @@ fn readU32Be() u32 {}...@@ -7755,18 +7744,6 @@ fn readU32Be() u32 {}
7755 {#header_close#}7744 {#header_close#}
77567745
7757 {#header_open|Appendix#}7746 {#header_open|Appendix#}
7758 {#header_open|Containers#}
7759 <p>
7760 A <em>container</em> in Zig is any syntactical construct that acts as a namespace to hold {#link|variable|Container Level Variables#} and {#link|function|Functions#} declarations.
7761 Containers are also type definitions which can be instantiated.
7762 {#link|Structs|struct#}, {#link|enums|enum#}, {#link|unions|union#}, {#link|opaques|opaque#}, and even Zig source files themselves are containers.
7763 </p>
7764 <p>
7765 Although containers (except Zig source files) use curly braces to surround their definition, they should not be confused with {#link|blocks|Blocks#} or functions.
7766 Containers do not contain statements.
7767 </p>
7768 {#header_close#}
7769
7770 {#header_open|Grammar#}7747 {#header_open|Grammar#}
7771 {#syntax_block|peg|grammar.peg#}7748 {#syntax_block|peg|grammar.peg#}
7772Root <- skip ContainerMembers eof7749Root <- skip ContainerMembers eof
doc/langref/test_container-level_comptime_expressions.zig deleted-37
...@@ -1,37 +0,0 @@
1const first_25_primes = firstNPrimes(25);
2const sum_of_first_25_primes = sum(&first_25_primes);
3
4fn firstNPrimes(comptime n: usize) [n]i32 {
5 var prime_list: [n]i32 = undefined;
6 var next_index: usize = 0;
7 var test_number: i32 = 2;
8 while (next_index < prime_list.len) : (test_number += 1) {
9 var test_prime_index: usize = 0;
10 var is_prime = true;
11 while (test_prime_index < next_index) : (test_prime_index += 1) {
12 if (test_number % prime_list[test_prime_index] == 0) {
13 is_prime = false;
14 break;
15 }
16 }
17 if (is_prime) {
18 prime_list[next_index] = test_number;
19 next_index += 1;
20 }
21 }
22 return prime_list;
23}
24
25fn sum(numbers: []const i32) i32 {
26 var result: i32 = 0;
27 for (numbers) |x| {
28 result += x;
29 }
30 return result;
31}
32
33test "variable values" {
34 try @import("std").testing.expectEqual(1060, sum_of_first_25_primes);
35}
36
37// test
doc/langref/test_container_level_variables.zig deleted-16
...@@ -1,16 +0,0 @@
1var y: i32 = add(10, x);
2const x: i32 = add(12, 34);
3
4test "container level variables" {
5 try expectEqual(46, x);
6 try expectEqual(56, y);
7}
8
9fn add(a: i32, b: i32) i32 {
10 return a + b;
11}
12
13const std = @import("std");
14const expectEqual = std.testing.expectEqual;
15
16// test
doc/langref/test_locally_scoped_global_variable.zig created+17
...@@ -0,0 +1,17 @@
1const std = @import("std");
2const expectEqual = std.testing.expectEqual;
3
4test "static local variable" {
5 try expectEqual(1235, foo());
6 try expectEqual(1236, foo());
7}
8
9fn foo() i32 {
10 const S = struct {
11 var x: i32 = 1234;
12 };
13 S.x += 1;
14 return S.x;
15}
16
17// test
doc/langref/test_namespace-level_comptime_expressions.zig created+37
...@@ -0,0 +1,37 @@
1const first_25_primes = firstNPrimes(25);
2const sum_of_first_25_primes = sum(&first_25_primes);
3
4fn firstNPrimes(comptime n: usize) [n]i32 {
5 var prime_list: [n]i32 = undefined;
6 var next_index: usize = 0;
7 var test_number: i32 = 2;
8 while (next_index < prime_list.len) : (test_number += 1) {
9 var test_prime_index: usize = 0;
10 var is_prime = true;
11 while (test_prime_index < next_index) : (test_prime_index += 1) {
12 if (test_number % prime_list[test_prime_index] == 0) {
13 is_prime = false;
14 break;
15 }
16 }
17 if (is_prime) {
18 prime_list[next_index] = test_number;
19 next_index += 1;
20 }
21 }
22 return prime_list;
23}
24
25fn sum(numbers: []const i32) i32 {
26 var result: i32 = 0;
27 for (numbers) |x| {
28 result += x;
29 }
30 return result;
31}
32
33test "variable values" {
34 try @import("std").testing.expectEqual(1060, sum_of_first_25_primes);
35}
36
37// test
doc/langref/test_namespace_level_variables.zig created+16
...@@ -0,0 +1,16 @@
1var y: i32 = add(10, x);
2const x: i32 = add(12, 34);
3
4test "container level variables" {
5 try expectEqual(46, x);
6 try expectEqual(56, y);
7}
8
9fn add(a: i32, b: i32) i32 {
10 return a + b;
11}
12
13const std = @import("std");
14const expectEqual = std.testing.expectEqual;
15
16// test
doc/langref/test_namespaced_container_level_variable.zig deleted-18
...@@ -1,18 +0,0 @@
1const std = @import("std");
2const expectEqual = std.testing.expectEqual;
3
4test "namespaced container level variable" {
5 try expectEqual(1235, foo());
6 try expectEqual(1236, foo());
7}
8
9const S = struct {
10 var x: i32 = 1234;
11};
12
13fn foo() i32 {
14 S.x += 1;
15 return S.x;
16}
17
18// test
doc/langref/test_namespaced_variable.zig created+18
...@@ -0,0 +1,18 @@
1const std = @import("std");
2const expectEqual = std.testing.expectEqual;
3
4test "namespaced container level variable" {
5 try expectEqual(1235, foo());
6 try expectEqual(1236, foo());
7}
8
9const S = struct {
10 var x: i32 = 1234;
11};
12
13fn foo() i32 {
14 S.x += 1;
15 return S.x;
16}
17
18// test
doc/langref/test_static_local_variable.zig deleted-17
...@@ -1,17 +0,0 @@
1const std = @import("std");
2const expectEqual = std.testing.expectEqual;
3
4test "static local variable" {
5 try expectEqual(1235, foo());
6 try expectEqual(1236, foo());
7}
8
9fn foo() i32 {
10 const S = struct {
11 var x: i32 = 1234;
12 };
13 S.x += 1;
14 return S.x;
15}
16
17// test
doc/langref/tldoc_comments.zig+5-6
...@@ -1,11 +1,10 @@...@@ -1,11 +1,10 @@
1//! This module provides functions for retrieving the current date and1//! Provides functions for retrieving the current date and time with varying
2//! time with varying degrees of precision and accuracy. It does not2//! degrees of precision and accuracy.
3//! depend on libc, but will use functions from it if available.
43
5const S = struct {4const S = struct {
6 //! Top level comments are allowed inside a container other than a module,5 //! Top level comments are allowed inside namespaces other than the
7 //! but it is not very useful. Currently, when producing the package6 //! implicit struct created by files, but it is not very useful. Currently,
8 //! documentation, these comments are ignored.7 //! when producing the package documentation, these comments are ignored.
9};8};
109
11// syntax10// syntax