authorgravatar for manlio.perillo@gmail.comManlio Perillo <manlio.perillo@gmail.com> 2023-01-18 18:35:25+01:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-23 15:14:24+02:00
logce6de2df826347feadb66d087c43c77b2891dc0b
tree35d6e155d09c3a5f3947ef7b71e98819cfe78124
parent220020599cc11764eb9ed32025dd506f2affedda

docgen: make the name required in the Code node

Update the genToc funtion to make the name required in the Code node, and add an additional optional field for the expected error, to use with test_err, test_safety and obj_err. Update langref.html.in to ensure all code blocks have a name that - is unique, so that a doctest can be identified by it - is descriptive For test, test_err and test_safefy, ensure that the doctest name starts with "test_", excluding doctests in the "Zig Test" section and doctests that are imported by other doctests. Ensure that the indentation of code_begin and code_end blocks are consistent. Fix a typo in pointer_arthemtic.

2 files changed, 217 insertions(+), 217 deletions(-)

doc/docgen.zig+9-9
......@@ -539,12 +539,15 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
539539 } else if (mem.eql(u8, tag_name, "code_begin")) {
540540 _ = try eatToken(tokenizer, Token.Id.Separator);
541541 const code_kind_tok = try eatToken(tokenizer, Token.Id.TagContent);
542 var name: []const u8 = "test";
542 _ = try eatToken(tokenizer, Token.Id.Separator);
543 const name_tok = try eatToken(tokenizer, Token.Id.TagContent);
544 const name = tokenizer.buffer[name_tok.start..name_tok.end];
545 var error_str: []const u8 = "";
543546 const maybe_sep = tokenizer.next();
544547 switch (maybe_sep.id) {
545548 Token.Id.Separator => {
546 const name_tok = try eatToken(tokenizer, Token.Id.TagContent);
547 name = tokenizer.buffer[name_tok.start..name_tok.end];
549 const error_tok = try eatToken(tokenizer, Token.Id.TagContent);
550 error_str = tokenizer.buffer[error_tok.start..error_tok.end];
548551 _ = try eatToken(tokenizer, Token.Id.BracketClose);
549552 },
550553 Token.Id.BracketClose => {},
......@@ -562,16 +565,13 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
562565 } else if (mem.eql(u8, code_kind_str, "test")) {
563566 code_kind_id = Code.Id.Test;
564567 } else if (mem.eql(u8, code_kind_str, "test_err")) {
565 code_kind_id = Code.Id{ .TestError = name };
566 name = "test";
568 code_kind_id = Code.Id{ .TestError = error_str };
567569 } else if (mem.eql(u8, code_kind_str, "test_safety")) {
568 code_kind_id = Code.Id{ .TestSafety = name };
569 name = "test";
570 code_kind_id = Code.Id{ .TestSafety = error_str };
570571 } else if (mem.eql(u8, code_kind_str, "obj")) {
571572 code_kind_id = Code.Id{ .Obj = null };
572573 } else if (mem.eql(u8, code_kind_str, "obj_err")) {
573 code_kind_id = Code.Id{ .Obj = name };
574 name = "test";
574 code_kind_id = Code.Id{ .Obj = error_str };
575575 } else if (mem.eql(u8, code_kind_str, "lib")) {
576576 code_kind_id = Code.Id.Lib;
577577 } else if (mem.eql(u8, code_kind_str, "syntax")) {
doc/langref.html.in+208-208
......@@ -1039,7 +1039,7 @@ pub fn main() void {
10391039 <p>
10401040 Code written within one or more {#syntax#}test{#endsyntax#} declarations can be used to ensure behavior meets expectations:
10411041 </p>
1042 {#code_begin|test|introducing_zig_test#}
1042 {#code_begin|test|testing_introduction#}
10431043const std = @import("std");
10441044
10451045test "expect addOne adds one to 41" {
......@@ -1124,13 +1124,13 @@ fn addOne(number: i32) i32 {
11241124 syntax. This syntax tells the compiler to ignore the result of the expression on the right side of the
11251125 assignment operator.
11261126 </p>
1127 {#code_begin|test|testdecl_container_top_level#}
1127 {#code_begin|test|testing_nested_container_tests#}
11281128const std = @import("std");
11291129const expect = std.testing.expect;
11301130
11311131// Imported source file tests will run when referenced from a top-level test declaration.
11321132// The next line alone does not cause "introducing_zig_test.zig" tests to run.
1133const imported_file = @import("introducing_zig_test.zig");
1133const imported_file = @import("testing_introduction.zig");
11341134
11351135test {
11361136 // To run nested container tests, either, call `refAllDecls` which will
......@@ -1143,7 +1143,7 @@ test {
11431143 // The `_ = C;` syntax is a no-op reference to the identifier `C`.
11441144 _ = S;
11451145 _ = U;
1146 _ = @import("introducing_zig_test.zig");
1146 _ = @import("testing_introduction.zig");
11471147}
11481148
11491149const S = struct {
......@@ -1184,7 +1184,7 @@ const U = union { // U is referenced by the file's top-level test declaration
11841184 When a test returns an error, the test is considered a failure and its {#link|error return trace|Error Return Traces#}
11851185 is output to standard error. The total number of failures will be reported after all tests have run.
11861186 </p>
1187 {#code_begin|test_err#}
1187 {#code_begin|test_err|testing_failure#}
11881188const std = @import("std");
11891189
11901190test "expect this to fail" {
......@@ -1208,7 +1208,7 @@ test "expect this to succeed" {
12081208 {#syntax#}error.SkipZigTest{#endsyntax#} and the default test runner will consider the test as being skipped.
12091209 The total number of skipped tests will be reported after all tests have run.
12101210 </p>
1211 {#code_begin|test#}
1211 {#code_begin|test|testing_skip#}
12121212test "this will be skipped" {
12131213 return error.SkipZigTest;
12141214}
......@@ -1221,7 +1221,7 @@ test "this will be skipped" {
12211221 {#syntax#}std.testing.allocator{#endsyntax#}, the default test runner will report any leaks that are
12221222 found from using the testing allocator:
12231223 </p>
1224 {#code_begin|test_err|1 tests leaked memory#}
1224 {#code_begin|test_err|testing_detect_leak|1 tests leaked memory#}
12251225const std = @import("std");
12261226
12271227test "detect leak" {
......@@ -1239,7 +1239,7 @@ test "detect leak" {
12391239 Use the {#link|compile variable|Compile Variables#} {#syntax#}@import("builtin").is_test{#endsyntax#}
12401240 to detect a test build:
12411241 </p>
1242 {#code_begin|test|detect_test#}
1242 {#code_begin|test|testing_detect_test#}
12431243const std = @import("std");
12441244const builtin = @import("builtin");
12451245const expect = std.testing.expect;
......@@ -1264,7 +1264,7 @@ fn isATest() bool {
12641264 you create tests. In addition to the <code>expect</code> function, this document uses a couple of more functions
12651265 as exemplified here:
12661266 </p>
1267 {#code_begin|test|testing_functions#}
1267 {#code_begin|test|testing_namespace#}
12681268const std = @import("std");
12691269
12701270test "expectEqual demo" {
......@@ -1319,7 +1319,7 @@ test "expectError demo" {
13191319 <p>
13201320 If a name that does not fit these requirements is needed, such as for linking with external libraries, the {#syntax#}@""{#endsyntax#} syntax may be used.
13211321 </p>
1322 {#code_begin|syntax#}
1322 {#code_begin|syntax|identifiers#}
13231323const @"identifier with spaces in it" = 0xff;
13241324const @"1SmallStep4Man" = 112358;
13251325
......@@ -1342,7 +1342,7 @@ const color: Color = .@"really red";
13421342 {#link|comptime#}. If a container level variable is {#syntax#}const{#endsyntax#} then its value is
13431343 {#syntax#}comptime{#endsyntax#}-known, otherwise it is runtime-known.
13441344 </p>
1345 {#code_begin|test|container_level_variables#}
1345 {#code_begin|test|test_container_level_variables#}
13461346var y: i32 = add(10, x);
13471347const x: i32 = add(12, 34);
13481348
......@@ -1361,7 +1361,7 @@ const expect = std.testing.expect;
13611361 <p>
13621362 Container level variables may be declared inside a {#link|struct#}, {#link|union#}, {#link|enum#}, or {#link|opaque#}:
13631363 </p>
1364 {#code_begin|test|namespaced_container_level_variable#}
1364 {#code_begin|test|test_namespaced_container_level_variable#}
13651365const std = @import("std");
13661366const expect = std.testing.expect;
13671367
......@@ -1385,7 +1385,7 @@ fn foo() i32 {
13851385 <p>
13861386 It is also possible to have local variables with static lifetime by using containers inside functions.
13871387 </p>
1388 {#code_begin|test|static_local_variable#}
1388 {#code_begin|test|test_static_local_variable#}
13891389const std = @import("std");
13901390const expect = std.testing.expect;
13911391
......@@ -1414,7 +1414,7 @@ fn foo() i32 {
14141414 {#header_open|Thread Local Variables#}
14151415 <p>A variable may be specified to be a thread-local variable using the
14161416 {#syntax#}threadlocal{#endsyntax#} keyword:</p>
1417 {#code_begin|test|tls#}
1417 {#code_begin|test|test_thread_local_variables#}
14181418const std = @import("std");
14191419const assert = std.debug.assert;
14201420
......@@ -1458,7 +1458,7 @@ fn testTls() void {
14581458 All variables declared in a {#syntax#}comptime{#endsyntax#} expression are implicitly
14591459 {#syntax#}comptime{#endsyntax#} variables.
14601460 </p>
1461 {#code_begin|test|comptime_vars#}
1461 {#code_begin|test|test_comptime_variables#}
14621462const std = @import("std");
14631463const expect = std.testing.expect;
14641464
......@@ -1582,7 +1582,7 @@ const nan = std.math.nan(f128);
15821582 {#header_open|Floating Point Operations#}
15831583 <p>By default floating point operations use {#syntax#}Strict{#endsyntax#} mode,
15841584 but you can switch to {#syntax#}Optimized{#endsyntax#} mode on a per-block basis:</p>
1585 {#code_begin|obj|foo#}
1585 {#code_begin|obj|float_mode_obj#}
15861586 {#code_release_fast#}
15871587 {#code_disable_cache#}
15881588const std = @import("std");
......@@ -1600,8 +1600,8 @@ export fn foo_optimized(x: f64) f64 {
16001600 <p>For this test we have to separate code into two object files -
16011601 otherwise the optimizer figures out all the values at compile-time,
16021602 which operates in strict mode.</p>
1603 {#code_begin|exe|float_mode#}
1604 {#code_link_object|foo#}
1603 {#code_begin|exe|float_mode_exe#}
1604 {#code_link_object|float_mode_obj#}
16051605const print = @import("std").debug.print;
16061606
16071607extern fn foo_strict(x: f64) f64;
......@@ -2326,7 +2326,7 @@ or
23262326 {#header_close#}
23272327 {#header_close#}
23282328 {#header_open|Arrays#}
2329 {#code_begin|test|arrays#}
2329 {#code_begin|test|test_arrays#}
23302330const expect = @import("std").testing.expect;
23312331const assert = @import("std").debug.assert;
23322332const mem = @import("std").mem;
......@@ -2437,7 +2437,7 @@ test "array initialization with function calls" {
24372437 <p>
24382438 Multidimensional arrays can be created by nesting arrays:
24392439 </p>
2440 {#code_begin|test|multidimensional#}
2440 {#code_begin|test|test_multidimensional_arrays#}
24412441const std = @import("std");
24422442const expect = std.testing.expect;
24432443
......@@ -2468,7 +2468,7 @@ test "multidimensional arrays" {
24682468 The syntax {#syntax#}[N:x]T{#endsyntax#} describes an array which has a sentinel element of value {#syntax#}x{#endsyntax#} at the
24692469 index corresponding to {#syntax#}len{#endsyntax#}.
24702470 </p>
2471 {#code_begin|test|null_terminated_array#}
2471 {#code_begin|test|test_null_terminated_array#}
24722472const std = @import("std");
24732473const expect = std.testing.expect;
24742474
......@@ -2521,7 +2521,7 @@ test "null terminated array" {
25212521 although small powers of two (2-64) are most typical. Note that excessively long vector lengths (e.g. 2^20) may
25222522 result in compiler crashes on current versions of Zig.
25232523 </p>
2524 {#code_begin|test|vector_example#}
2524 {#code_begin|test|test_vector#}
25252525const std = @import("std");
25262526const expectEqual = std.testing.expectEqual;
25272527
......@@ -2609,7 +2609,7 @@ test "Conversion between vectors, arrays, and slices" {
26092609 </li>
26102610 </ul>
26112611 <p>Use {#syntax#}&x{#endsyntax#} to obtain a single-item pointer:</p>
2612 {#code_begin|test|single_item_pointer_test#}
2612 {#code_begin|test|test_single_item_pointer#}
26132613const expect = @import("std").testing.expect;
26142614
26152615test "address of syntax" {
......@@ -2647,7 +2647,7 @@ test "pointer array access" {
26472647 <p>
26482648 Zig supports pointer arithmetic. It's better to assign the pointer to {#syntax#}[*]T{#endsyntax#} and increment that variable. For example, directly incrementing the pointer from a slice will corrupt it.
26492649 </p>
2650 {#code_begin|test|pointer_arthemtic#}
2650 {#code_begin|test|test_pointer_arithmetic#}
26512651const expect = @import("std").testing.expect;
26522652
26532653test "pointer arithmetic with many-item pointer" {
......@@ -2683,7 +2683,7 @@ test "pointer arithmetic with slices" {
26832683 against this kind of undefined behavior. This is one reason
26842684 we prefer slices to pointers.
26852685 </p>
2686 {#code_begin|test|slice_bounds#}
2686 {#code_begin|test|test_slice_bounds#}
26872687const expect = @import("std").testing.expect;
26882688
26892689test "pointer slicing" {
......@@ -2699,7 +2699,7 @@ test "pointer slicing" {
26992699 {#code_end#}
27002700 <p>Pointers work at compile-time too, as long as the code does not depend on
27012701 an undefined memory layout:</p>
2702 {#code_begin|test|comptime_pointers#}
2702 {#code_begin|test|test_comptime_pointers#}
27032703const expect = @import("std").testing.expect;
27042704
27052705test "comptime pointers" {
......@@ -2714,7 +2714,7 @@ test "comptime pointers" {
27142714 {#code_end#}
27152715 <p>To convert an integer address into a pointer, use {#syntax#}@intToPtr{#endsyntax#}.
27162716 To convert a pointer to an integer, use {#syntax#}@ptrToInt{#endsyntax#}:</p>
2717 {#code_begin|test|integer_pointer_conversion#}
2717 {#code_begin|test|test_integer_pointer_conversion#}
27182718const expect = @import("std").testing.expect;
27192719
27202720test "@ptrToInt and @intToPtr" {
......@@ -2726,7 +2726,7 @@ test "@ptrToInt and @intToPtr" {
27262726 {#code_end#}
27272727 <p>Zig is able to preserve memory addresses in comptime code, as long as
27282728 the pointer is never dereferenced:</p>
2729 {#code_begin|test|comptime_pointer_conversion#}
2729 {#code_begin|test|test_comptime_pointer_conversion#}
27302730const expect = @import("std").testing.expect;
27312731
27322732test "comptime @intToPtr" {
......@@ -2746,7 +2746,7 @@ test "comptime @intToPtr" {
27462746 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.
27472747 In the following code, loads and stores with {#syntax#}mmio_ptr{#endsyntax#} are guaranteed to all happen
27482748 and in the same order as in source code:</p>
2749 {#code_begin|test|volatile#}
2749 {#code_begin|test|test_volatile#}
27502750const expect = @import("std").testing.expect;
27512751
27522752test "volatile" {
......@@ -2765,7 +2765,7 @@ test "volatile" {
27652765 operation that Zig cannot protect you against. Use {#syntax#}@ptrCast{#endsyntax#} only when other
27662766 conversions are not possible.
27672767 </p>
2768 {#code_begin|test|pointer_casting#}
2768 {#code_begin|test|test_pointer_casting#}
27692769const std = @import("std");
27702770const expect = std.testing.expect;
27712771
......@@ -2803,7 +2803,7 @@ test "pointer child type" {
28032803 In Zig, a pointer type has an alignment value. If the value is equal to the
28042804 alignment of the underlying type, it can be omitted from the type:
28052805 </p>
2806 {#code_begin|test|variable_alignment#}
2806 {#code_begin|test|test_variable_alignment#}
28072807const std = @import("std");
28082808const builtin = @import("builtin");
28092809const expect = std.testing.expect;
......@@ -2826,7 +2826,7 @@ test "variable alignment" {
28262826 You can specify alignment on variables and functions. If you do this, then
28272827 pointers to them get the specified alignment:
28282828 </p>
2829 {#code_begin|test|variable_func_alignment#}
2829 {#code_begin|test|test_variable_func_alignment#}
28302830const expect = @import("std").testing.expect;
28312831
28322832var foo: u8 align(4) = 100;
......@@ -2860,7 +2860,7 @@ test "function alignment" {
28602860 pointer into a more aligned pointer. This is a no-op at runtime, but inserts a
28612861 {#link|safety check|Incorrect Pointer Alignment#}:
28622862 </p>
2863 {#code_begin|test_safety|incorrect alignment#}
2863 {#code_begin|test_safety|test_incorrect_pointer_alignment|incorrect alignment#}
28642864const std = @import("std");
28652865
28662866test "pointer alignment safety" {
......@@ -2885,7 +2885,7 @@ fn foo(bytes: []u8) u32 {
28852885 did not have the {#syntax#}allowzero{#endsyntax#} attribute, this would be a
28862886 {#link|Pointer Cast Invalid Null#} panic:
28872887 </p>
2888 {#code_begin|test|allowzero#}
2888 {#code_begin|test|test_allowzero#}
28892889const std = @import("std");
28902890const expect = std.testing.expect;
28912891
......@@ -2903,7 +2903,7 @@ test "allowzero" {
29032903 has a length determined by a sentinel value. This provides protection
29042904 against buffer overflow and overreads.
29052905 </p>
2906 {#code_begin|exe_build_err#}
2906 {#code_begin|exe_build_err|sentinel-terminated_pointer#}
29072907 {#link_libc#}
29082908const std = @import("std");
29092909
......@@ -2923,7 +2923,7 @@ pub fn main() anyerror!void {
29232923 {#header_close#}
29242924
29252925 {#header_open|Slices#}
2926 {#code_begin|test_safety|index out of bounds#}
2926 {#code_begin|test_safety|test_basic_slices|index out of bounds#}
29272927const expect = @import("std").testing.expect;
29282928
29292929test "basic slices" {
......@@ -2958,7 +2958,7 @@ test "basic slices" {
29582958}
29592959 {#code_end#}
29602960 <p>This is one reason we prefer slices to pointers.</p>
2961 {#code_begin|test|slices#}
2961 {#code_begin|test|test_slices#}
29622962const std = @import("std");
29632963const expect = std.testing.expect;
29642964const mem = std.mem;
......@@ -3019,7 +3019,7 @@ test "slice pointer" {
30193019 guarantee that there are no sentinel elements before that. Sentinel-terminated slices allow element
30203020 access to the {#syntax#}len{#endsyntax#} index.
30213021 </p>
3022 {#code_begin|test|null_terminated_slice#}
3022 {#code_begin|test|test_null_terminated_slice#}
30233023const std = @import("std");
30243024const expect = std.testing.expect;
30253025
......@@ -3035,7 +3035,7 @@ test "null terminated slice" {
30353035 {#syntax#}data[start..end :x]{#endsyntax#}, where {#syntax#}data{#endsyntax#} is a many-item pointer,
30363036 array or slice and {#syntax#}x{#endsyntax#} is the sentinel value.
30373037 </p>
3038 {#code_begin|test|null_terminated_slicing#}
3038 {#code_begin|test|test_null_terminated_slicing#}
30393039const std = @import("std");
30403040const expect = std.testing.expect;
30413041
......@@ -3052,7 +3052,7 @@ test "null terminated slicing" {
30523052 Sentinel-terminated slicing asserts that the element in the sentinel position of the backing data is
30533053 actually the sentinel value. If this is not the case, safety-protected {#link|Undefined Behavior#} results.
30543054 </p>
3055 {#code_begin|test_safety|sentinel mismatch#}
3055 {#code_begin|test_safety|test_sentinel_mismatch|sentinel mismatch#}
30563056const std = @import("std");
30573057const expect = std.testing.expect;
30583058
......@@ -3074,7 +3074,7 @@ test "sentinel mismatch" {
30743074 {#header_close#}
30753075
30763076 {#header_open|struct#}
3077 {#code_begin|test|structs#}
3077 {#code_begin|test|test_structs#}
30783078// Declare a struct.
30793079// Zig gives no guarantees about the order of fields and the size of
30803080// the struct but the fields are guaranteed to be ABI-aligned.
......@@ -3223,7 +3223,7 @@ test "linked list" {
32233223 Each struct field may have an expression indicating the default field value. Such expressions
32243224 are executed at {#link|comptime#}, and allow the field to be omitted in a struct literal expression:
32253225 </p>
3226 {#code_begin|test|default_field_values#}
3226 {#code_begin|test|test_struct_default_field_values#}
32273227const Foo = struct {
32283228 a: i32 = 1234,
32293229 b: i32,
......@@ -3272,7 +3272,7 @@ test "default struct initialization fields" {
32723272 in a {#link|@bitCast#} or a {#link|@ptrCast#} to reinterpret memory.
32733273 This even works at {#link|comptime#}:
32743274 </p>
3275 {#code_begin|test|packed_structs#}
3275 {#code_begin|test|test_packed_structs#}
32763276const std = @import("std");
32773277const native_endian = @import("builtin").target.cpu.arch.endian();
32783278const expect = std.testing.expect;
......@@ -3316,7 +3316,7 @@ fn doTheTest() !void {
33163316 <p>
33173317 Zig allows the address to be taken of a non-byte-aligned field:
33183318 </p>
3319 {#code_begin|test|pointer_to_non-byte_aligned_field#}
3319 {#code_begin|test|test_pointer_to_non-byte_aligned_field#}
33203320const std = @import("std");
33213321const expect = std.testing.expect;
33223322
......@@ -3341,7 +3341,7 @@ test "pointer to non-byte-aligned field" {
33413341 However, the pointer to a non-byte-aligned field has special properties and cannot
33423342 be passed when a normal pointer is expected:
33433343 </p>
3344 {#code_begin|test_err|expected type#}
3344 {#code_begin|test_err|test_misaligned_pointer|expected type#}
33453345const std = @import("std");
33463346const expect = std.testing.expect;
33473347
......@@ -3372,7 +3372,7 @@ fn bar(x: *const u3) u3 {
33723372 <p>
33733373 Pointers to non-ABI-aligned fields share the same address as the other fields within their host integer:
33743374 </p>
3375 {#code_begin|test|packed_struct_field_addrs#}
3375 {#code_begin|test|test_packed_struct_field_address#}
33763376const std = @import("std");
33773377const expect = std.testing.expect;
33783378
......@@ -3422,7 +3422,7 @@ test "pointer to non-bit-aligned field" {
34223422 Packed structs have the same alignment as their backing integer, however, overaligned
34233423 pointers to packed structs can override this:
34243424 </p>
3425 {#code_begin|test|overaligned_packed_struct#}
3425 {#code_begin|test|test_overaligned_packed_struct#}
34263426const std = @import("std");
34273427const expect = std.testing.expect;
34283428
......@@ -3501,7 +3501,7 @@ fn List(comptime T: type) type {
35013501 the struct literal will directly instantiate the {#link|result location|Result Location Semantics#},
35023502 with no copy:
35033503 </p>
3504 {#code_begin|test|struct_result#}
3504 {#code_begin|test|test_struct_result#}
35053505const std = @import("std");
35063506const expect = std.testing.expect;
35073507
......@@ -3520,7 +3520,7 @@ test "anonymous struct literal" {
35203520 The struct type can be inferred. Here the {#link|result location|Result Location Semantics#}
35213521 does not include a type, and so Zig infers the type:
35223522 </p>
3523 {#code_begin|test|struct_anon#}
3523 {#code_begin|test|test_anonymous_struct#}
35243524const std = @import("std");
35253525const expect = std.testing.expect;
35263526
......@@ -3557,7 +3557,7 @@ fn dump(args: anytype) !void {
35573557 Like arrays, tuples have a .len field, can be indexed (provided the index is comptime-known)
35583558 and work with the ++ and ** operators. They can also be iterated over with {#link|inline for#}.
35593559 </p>
3560 {#code_begin|test|tuple#}
3560 {#code_begin|test|test_tuples#}
35613561const std = @import("std");
35623562const expect = std.testing.expect;
35633563
......@@ -3582,7 +3582,7 @@ test "tuple" {
35823582 {#see_also|comptime|@fieldParentPtr#}
35833583 {#header_close#}
35843584 {#header_open|enum#}
3585 {#code_begin|test|enums#}
3585 {#code_begin|test|test_enums#}
35863586const expect = @import("std").testing.expect;
35873587const mem = @import("std").mem;
35883588
......@@ -3700,7 +3700,7 @@ test "@tagName" {
37003700 <p>
37013701 By default, enums are not guaranteed to be compatible with the C ABI:
37023702 </p>
3703 {#code_begin|obj_err|parameter of type 'test.Foo' not allowed in function with calling convention 'C'#}
3703 {#code_begin|obj_err|enum_export_error|parameter of type 'enum_export_error.Foo' not allowed in function with calling convention 'C'#}
37043704const Foo = enum { a, b, c };
37053705export fn entry(foo: Foo) void { _ = foo; }
37063706 {#code_end#}
......@@ -3708,7 +3708,7 @@ export fn entry(foo: Foo) void { _ = foo; }
37083708 For a C-ABI-compatible enum, provide an explicit tag type to
37093709 the enum:
37103710 </p>
3711 {#code_begin|obj#}
3711 {#code_begin|obj|enum_export#}
37123712const Foo = enum(c_int) { a, b, c };
37133713export fn entry(foo: Foo) void { _ = foo; }
37143714 {#code_end#}
......@@ -3801,7 +3801,7 @@ test "switch on non-exhaustive enum" {
38013801 {#link|Accessing the non-active field|Wrong Union Field Access#} is
38023802 safety-checked {#link|Undefined Behavior#}:
38033803 </p>
3804 {#code_begin|test_err|access of union field 'float' while field 'int' is active#}
3804 {#code_begin|test_err|test_wrong_union_access|access of union field 'float' while field 'int' is active#}
38053805const Payload = union {
38063806 int: i64,
38073807 float: f64,
......@@ -3963,7 +3963,7 @@ test "@tagName" {
39633963 {#header_open|Anonymous Union Literals#}
39643964 <p>{#link|Anonymous Struct Literals#} syntax can be used to initialize unions without specifying
39653965 the type:</p>
3966 {#code_begin|test|anon_union#}
3966 {#code_begin|test|test_anonymous_union#}
39673967const std = @import("std");
39683968const expect = std.testing.expect;
39693969
......@@ -3997,7 +3997,7 @@ fn makeNumber() Number {
39973997 This is typically used for type safety when interacting with C code that does not expose struct details.
39983998 Example:
39993999 </p>
4000 {#code_begin|test_err|expected type '*test.Derp', found '*test.Wat'#}
4000 {#code_begin|test_err|test_opaque|expected type '*test_opaque.Derp', found '*test_opaque.Wat'#}
40014001const Derp = opaque {};
40024002const Wat = opaque {};
40034003
......@@ -4016,7 +4016,7 @@ test "call foo" {
40164016 <p>
40174017 Blocks are used to limit the scope of variable declarations:
40184018 </p>
4019 {#code_begin|test_err|use of undeclared identifier 'x'#}
4019 {#code_begin|test_err|test_blocks|use of undeclared identifier 'x'#}
40204020test "access variable after block scope" {
40214021 {
40224022 var x: i32 = 1;
......@@ -4048,7 +4048,7 @@ test "labeled break from labeled block expression" {
40484048
40494049 {#header_open|Shadowing#}
40504050 <p>{#link|Identifiers#} are never allowed to "hide" other identifiers by using the same name:</p>
4051 {#code_begin|test_err|local variable shadows declaration#}
4051 {#code_begin|test_err|test_shadowing|local variable shadows declaration#}
40524052const pi = 3.14;
40534053
40544054test "inside test block" {
......@@ -4079,7 +4079,7 @@ test "separate scopes" {
40794079
40804080 {#header_open|Empty Blocks#}
40814081 <p>An empty block is equivalent to {#syntax#}void{}{#endsyntax#}:</p>
4082 {#code_begin|test|empty_block#}
4082 {#code_begin|test|test_empty_block#}
40834083const std = @import("std");
40844084const expect = std.testing.expect;
40854085
......@@ -4095,7 +4095,7 @@ test {
40954095 {#header_close#}
40964096
40974097 {#header_open|switch#}
4098 {#code_begin|test|switch#}
4098 {#code_begin|test|test_switch#}
40994099const std = @import("std");
41004100const builtin = @import("builtin");
41014101const expect = std.testing.expect;
......@@ -4212,7 +4212,7 @@ test "switch on tagged union" {
42124212 When a {#syntax#}switch{#endsyntax#} expression does not have an {#syntax#}else{#endsyntax#} clause,
42134213 it must exhaustively list all the possible values. Failure to do so is a compile error:
42144214 </p>
4215 {#code_begin|test_err|unhandled enumeration value#}
4215 {#code_begin|test_err|test_unhandled_enumeration_value|unhandled enumeration value#}
42164216const Color = enum {
42174217 auto,
42184218 off,
......@@ -4390,7 +4390,7 @@ test "test" {
43904390 A while loop is used to repeatedly execute an expression until
43914391 some condition is no longer true.
43924392 </p>
4393 {#code_begin|test|while#}
4393 {#code_begin|test|test_while#}
43944394const expect = @import("std").testing.expect;
43954395
43964396test "while basic" {
......@@ -4404,7 +4404,7 @@ test "while basic" {
44044404 <p>
44054405 Use {#syntax#}break{#endsyntax#} to exit a while loop early.
44064406 </p>
4407 {#code_begin|test|while#}
4407 {#code_begin|test|test_while_break#}
44084408const expect = @import("std").testing.expect;
44094409
44104410test "while break" {
......@@ -4420,7 +4420,7 @@ test "while break" {
44204420 <p>
44214421 Use {#syntax#}continue{#endsyntax#} to jump back to the beginning of the loop.
44224422 </p>
4423 {#code_begin|test|while#}
4423 {#code_begin|test|test_while_continue#}
44244424const expect = @import("std").testing.expect;
44254425
44264426test "while continue" {
......@@ -4438,7 +4438,7 @@ test "while continue" {
44384438 While loops support a continue expression which is executed when the loop
44394439 is continued. The {#syntax#}continue{#endsyntax#} keyword respects this expression.
44404440 </p>
4441 {#code_begin|test|while#}
4441 {#code_begin|test|test_while_continue_expression#}
44424442const expect = @import("std").testing.expect;
44434443
44444444test "while loop continue expression" {
......@@ -4467,7 +4467,7 @@ test "while loop continue expression, more complicated" {
44674467 When you {#syntax#}break{#endsyntax#} from a while loop, the {#syntax#}else{#endsyntax#} branch is not
44684468 evaluated.
44694469 </p>
4470 {#code_begin|test|while#}
4470 {#code_begin|test|test_while_else#}
44714471const expect = @import("std").testing.expect;
44724472
44734473test "while else" {
......@@ -4487,7 +4487,7 @@ fn rangeHasNumber(begin: usize, end: usize, number: usize) bool {
44874487 {#header_open|Labeled while#}
44884488 <p>When a {#syntax#}while{#endsyntax#} loop is labeled, it can be referenced from a {#syntax#}break{#endsyntax#}
44894489 or {#syntax#}continue{#endsyntax#} from within a nested loop:</p>
4490 {#code_begin|test|test_nested_break#}
4490 {#code_begin|test|test_while_nested_break#}
44914491test "nested break" {
44924492 outer: while (true) {
44934493 while (true) {
......@@ -4520,7 +4520,7 @@ test "nested continue" {
45204520 The {#syntax#}else{#endsyntax#} branch is allowed on optional iteration. In this case, it will
45214521 be executed on the first null value encountered.
45224522 </p>
4523 {#code_begin|test|while#}
4523 {#code_begin|test|test_while_null_capture#}
45244524const expect = @import("std").testing.expect;
45254525
45264526test "while null capture" {
......@@ -4562,7 +4562,7 @@ fn eventuallyNullSequence() ?u32 {
45624562 When the {#syntax#}else |x|{#endsyntax#} syntax is present on a {#syntax#}while{#endsyntax#} expression,
45634563 the while condition must have an {#link|Error Union Type#}.
45644564 </p>
4565 {#code_begin|test|while#}
4565 {#code_begin|test|test_while_error_capture#}
45664566const expect = @import("std").testing.expect;
45674567
45684568test "while error union capture" {
......@@ -4627,7 +4627,7 @@ fn typeNameLength(comptime T: type) usize {
46274627 {#see_also|if|Optionals|Errors|comptime|unreachable#}
46284628 {#header_close#}
46294629 {#header_open|for#}
4630 {#code_begin|test|for#}
4630 {#code_begin|test|test_for#}
46314631const expect = @import("std").testing.expect;
46324632
46334633test "for basics" {
......@@ -4695,7 +4695,7 @@ test "for else" {
46954695 {#header_open|Labeled for#}
46964696 <p>When a {#syntax#}for{#endsyntax#} loop is labeled, it can be referenced from a {#syntax#}break{#endsyntax#}
46974697 or {#syntax#}continue{#endsyntax#} from within a nested loop:</p>
4698 {#code_begin|test|test_nested_break#}
4698 {#code_begin|test|test_for_nested_break#}
46994699const std = @import("std");
47004700const expect = std.testing.expect;
47014701
......@@ -4731,7 +4731,7 @@ test "nested continue" {
47314731 The capture value and iterator value of inlined for loops are
47324732 compile-time known.
47334733 </p>
4734 {#code_begin|test|test_inline_loop#}
4734 {#code_begin|test|test_inline_for#}
47354735const expect = @import("std").testing.expect;
47364736
47374737test "inline for loop" {
......@@ -4766,7 +4766,7 @@ fn typeNameLength(comptime T: type) usize {
47664766 {#see_also|while|comptime|Arrays|Slices#}
47674767 {#header_close#}
47684768 {#header_open|if#}
4769 {#code_begin|test|if#}
4769 {#code_begin|test|test_if#}
47704770// If expressions have three uses, corresponding to the three types:
47714771// * bool
47724772// * ?T
......@@ -4927,7 +4927,7 @@ test "if error union with optional" {
49274927 {#see_also|Optionals|Errors#}
49284928 {#header_close#}
49294929 {#header_open|defer#}
4930 {#code_begin|test|defer#}
4930 {#code_begin|test|test_defer#}
49314931const std = @import("std");
49324932const expect = std.testing.expect;
49334933const print = std.debug.print;
......@@ -4973,7 +4973,7 @@ test "defer unwinding" {
49734973 deferUnwindExample();
49744974}
49754975 {#code_end#}
4976 {#code_begin|test_err|cannot return from defer expression#}
4976 {#code_begin|test_err|test_invalid_defer|cannot return from defer expression#}
49774977// Inside a defer expression the return statement is not allowed.
49784978fn deferInvalidExample() !void {
49794979 defer {
......@@ -4983,7 +4983,7 @@ fn deferInvalidExample() !void {
49834983 return error.DeferError;
49844984}
49854985 {#code_end#}
4986 {#code_begin|test|errdefer#}
4986 {#code_begin|test|test_errdefer#}
49874987const std = @import("std");
49884988const print = std.debug.print;
49894989
......@@ -5052,7 +5052,7 @@ test "basic math" {
50525052}
50535053 {#code_end#}
50545054 <p>In fact, this is how {#syntax#}std.debug.assert{#endsyntax#} is implemented:</p>
5055 {#code_begin|test_err#}
5055 {#code_begin|test_err|test_assertion_failure#}
50565056// This is how std.debug.assert is implemented
50575057fn assert(ok: bool) void {
50585058 if (!ok) unreachable; // assertion failure
......@@ -5065,7 +5065,7 @@ test "this will fail" {
50655065 {#code_end#}
50665066 {#header_close#}
50675067 {#header_open|At Compile-Time#}
5068 {#code_begin|test_err|unreachable code#}
5068 {#code_begin|test_err|test_comptime_unreachable|unreachable code#}
50695069const assert = @import("std").debug.assert;
50705070
50715071test "type of unreachable" {
......@@ -5107,7 +5107,7 @@ test "noreturn" {
51075107}
51085108 {#code_end#}
51095109 <p>Another use case for {#syntax#}noreturn{#endsyntax#} is the {#syntax#}exit{#endsyntax#} function:</p>
5110 {#code_begin|test|noreturn_from_exit#}
5110 {#code_begin|test|test_noreturn_from_exit#}
51115111 {#target_windows#}
51125112const std = @import("std");
51135113const builtin = @import("builtin");
......@@ -5130,7 +5130,7 @@ fn bar() anyerror!u32 {
51305130 {#header_close#}
51315131
51325132 {#header_open|Functions#}
5133 {#code_begin|test|functions#}
5133 {#code_begin|test|test_functions#}
51345134const std = @import("std");
51355135const builtin = @import("builtin");
51365136const native_arch = builtin.cpu.arch;
......@@ -5206,7 +5206,7 @@ test "function" {
52065206 as parameters, Zig may choose to copy and pass by value, or pass by reference, whichever way
52075207 Zig decides will be faster. This is made possible, in part, by the fact that parameters are immutable.
52085208 </p>
5209 {#code_begin|test|pass_by_reference_or_value#}
5209 {#code_begin|test|test_pass_by_reference_or_value#}
52105210const Point = struct {
52115211 x: i32,
52125212 y: i32,
......@@ -5283,7 +5283,7 @@ test "fn reflection" {
52835283 <p>
52845284 You can {#link|coerce|Type Coercion#} an error from a subset to a superset:
52855285 </p>
5286 {#code_begin|test|coercing_subset_to_superset#}
5286 {#code_begin|test|test_coerce_error_subset_to_superset#}
52875287const std = @import("std");
52885288
52895289const FileOpenError = error {
......@@ -5308,7 +5308,7 @@ fn foo(err: AllocationError) FileOpenError {
53085308 <p>
53095309 But you cannot {#link|coerce|Type Coercion#} an error from a superset to a subset:
53105310 </p>
5311 {#code_begin|test_err|not a member of destination error set#}
5311 {#code_begin|test_err|test_coerce_error_superset_to_subset|not a member of destination error set#}
53125312const FileOpenError = error {
53135313 AccessDenied,
53145314 OutOfMemory,
......@@ -5330,11 +5330,11 @@ fn foo(err: FileOpenError) AllocationError {
53305330 <p>
53315331 There is a shortcut for declaring an error set with only 1 value, and then getting that value:
53325332 </p>
5333 {#code_begin|syntax#}
5333 {#code_begin|syntax|single_value_error_set_shortcut#}
53345334const err = error.FileNotFound;
53355335 {#code_end#}
53365336 <p>This is equivalent to:</p>
5337 {#code_begin|syntax#}
5337 {#code_begin|syntax|single_value_error_set#}
53385338const err = (error {FileNotFound}).FileNotFound;
53395339 {#code_end#}
53405340 <p>
......@@ -5431,7 +5431,7 @@ test "parse u64" {
54315431 </ul>
54325432 {#header_open|catch#}
54335433 <p>If you want to provide a default value, you can use the {#syntax#}catch{#endsyntax#} binary operator:</p>
5434 {#code_begin|syntax#}
5434 {#code_begin|syntax|catch#}
54355435const parseU64 = @import("error_union_parsing_u64.zig").parseU64;
54365436
54375437fn doAThing(str: []u8) void {
......@@ -5448,7 +5448,7 @@ fn doAThing(str: []u8) void {
54485448 {#header_open|try#}
54495449 <p>Let's say you wanted to return the error if you got one, otherwise continue with the
54505450 function logic:</p>
5451 {#code_begin|syntax#}
5451 {#code_begin|syntax|catch_err_return#}
54525452const parseU64 = @import("error_union_parsing_u64.zig").parseU64;
54535453
54545454fn doAThing(str: []u8) !void {
......@@ -5459,7 +5459,7 @@ fn doAThing(str: []u8) !void {
54595459 <p>
54605460 There is a shortcut for this. The {#syntax#}try{#endsyntax#} expression:
54615461 </p>
5462 {#code_begin|syntax#}
5462 {#code_begin|syntax|try#}
54635463const parseU64 = @import("error_union_parsing_u64.zig").parseU64;
54645464
54655465fn doAThing(str: []u8) !void {
......@@ -5543,7 +5543,7 @@ fn createFoo(param: i32) !Foo {
55435543 It should be noted that {#syntax#}errdefer{#endsyntax#} statements only last until the end of the block
55445544 they are written in, and therefore are not run if an error is returned outside of that block:
55455545 </p>
5546 {#code_begin|test_err|1 tests leaked memory#}
5546 {#code_begin|test_err|test_errdefer_slip_ups|1 tests leaked memory#}
55475547const std = @import("std");
55485548const Allocator = std.mem.Allocator;
55495549
......@@ -5635,7 +5635,7 @@ test "createFoo" {
56355635 The fact that errdefers only last for the block they are declared in is
56365636 especially important when using loops:
56375637 </p>
5638 {#code_begin|test_err|3 errors were logged#}
5638 {#code_begin|test_err|test_errdefer_loop_leak|3 errors were logged#}
56395639const std = @import("std");
56405640const Allocator = std.mem.Allocator;
56415641
......@@ -5799,7 +5799,7 @@ test "merge error sets" {
57995799 Because many functions in Zig return a possible error, Zig supports inferring the error set.
58005800 To infer the error set for a function, prepend the {#syntax#}!{#endsyntax#} operator to the function’s return type, like {#syntax#}!T{#endsyntax#}:
58015801 </p>
5802{#code_begin|test|inferred_error_sets#}
5802 {#code_begin|test|test_inferred_error_sets#}
58035803// With an inferred error set
58045804pub fn add_inferred(comptime T: type, a: T, b: T) !T {
58055805 const ov = @addWithOverflow(a, b);
......@@ -5825,7 +5825,7 @@ test "inferred error set" {
58255825 error.Overflow => {}, // ok
58265826 }
58275827}
5828{#code_end#}
5828 {#code_end#}
58295829 <p>
58305830 When a function has an inferred error set, that function becomes generic and thus it becomes
58315831 trickier to do certain things with it, such as obtain a function pointer, or have an error
......@@ -5845,7 +5845,7 @@ test "inferred error set" {
58455845 <p>
58465846 Error Return Traces show all the points in the code that an error was returned to the calling function. This makes it practical to use {#link|try#} everywhere and then still be able to know what happened if an error ends up bubbling all the way out of your application.
58475847 </p>
5848 {#code_begin|exe_err#}
5848 {#code_begin|exe_err|error_return_trace#}
58495849pub fn main() !void {
58505850 try foo(12);
58515851}
......@@ -5894,7 +5894,7 @@ fn bang2() !void {
58945894 but the original error that started this whole thing was {#syntax#}FileNotFound{#endsyntax#}. In the {#syntax#}bar{#endsyntax#} function, the code handles the original error code,
58955895 and then returns another one, from the switch statement. Error Return Traces make this clear, whereas a stack trace would look like this:
58965896 </p>
5897 {#code_begin|exe_err#}
5897 {#code_begin|exe_err|stack_trace#}
58985898pub fn main() void {
58995899 foo(12);
59005900}
......@@ -6016,7 +6016,7 @@ fn __zig_return_error(stack_trace: *StackTrace) void {
60166016 The question mark symbolizes the optional type. You can convert a type to an optional
60176017 type by putting a question mark in front of it, like this:
60186018 </p>
6019 {#code_begin|syntax#}
6019 {#code_begin|syntax|optional_integer#}
60206020// normal integer
60216021const normal_int: i32 = 1234;
60226022
......@@ -6137,7 +6137,7 @@ test "optional type" {
61376137 Just like {#link|undefined#}, {#syntax#}null{#endsyntax#} has its own type, and the only way to use it is to
61386138 cast it to a different type:
61396139 </p>
6140 {#code_begin|syntax#}
6140 {#code_begin|syntax|null#}
61416141const optional_value: ?i32 = null;
61426142 {#code_end#}
61436143 {#header_close#}
......@@ -6176,7 +6176,7 @@ test "optional pointers" {
61766176 <p>
61776177 Type coercion occurs when one type is expected, but different type is provided:
61786178 </p>
6179 {#code_begin|test|type_coercion#}
6179 {#code_begin|test|test_type_coercion#}
61806180test "type coercion - variable declaration" {
61816181 var a: u8 = 1;
61826182 var b: u16 = a;
......@@ -6216,7 +6216,7 @@ test "type coercion - @as builtin" {
62166216 <p>
62176217 These casts are no-ops at runtime since the value representation does not change.
62186218 </p>
6219 {#code_begin|test|no_op_casts#}
6219 {#code_begin|test|test_no_op_casts#}
62206220test "type coercion - const qualification" {
62216221 var a: i32 = 1;
62226222 var b: *i32 = &a;
......@@ -6228,7 +6228,7 @@ fn foo(_: *const i32) void {}
62286228 <p>
62296229 In addition, pointers coerce to const optional pointers:
62306230 </p>
6231 {#code_begin|test|pointer_coerce_const_optional#}
6231 {#code_begin|test|test_pointer_coerce_const_optional#}
62326232const std = @import("std");
62336233const expect = std.testing.expect;
62346234const mem = std.mem;
......@@ -6285,7 +6285,7 @@ test "float widening" {
62856285 <li>Cast {#syntax#}54.0{#endsyntax#} to {#syntax#}comptime_int{#endsyntax#} resulting in {#syntax#}@as(comptime_int, 10){#endsyntax#}, which is casted to {#syntax#}@as(f32, 10){#endsyntax#}</li>
62866286 <li>Cast {#syntax#}5{#endsyntax#} to {#syntax#}comptime_float{#endsyntax#} resulting in {#syntax#}@as(comptime_float, 10.8){#endsyntax#}, which is casted to {#syntax#}@as(f32, 10.8){#endsyntax#}</li>
62876287 </ul>
6288 {#code_begin|test_err#}
6288 {#code_begin|test_err|test_ambiguous_coercion#}
62896289// Compile time coercion of float to int
62906290test "implicit cast to comptime_int" {
62916291 var f: f32 = 54.0 / 5;
......@@ -6294,7 +6294,7 @@ test "implicit cast to comptime_int" {
62946294 {#code_end#}
62956295 {#header_close#}
62966296 {#header_open|Type Coercion: Slices, Arrays and Pointers#}
6297 {#code_begin|test|coerce__slices_arrays_and_ptrs#}
6297 {#code_begin|test|test_coerce_slices_arrays_and_pointers#}
62986298const std = @import("std");
62996299const expect = std.testing.expect;
63006300
......@@ -6522,7 +6522,7 @@ test "coercion from homogenous tuple to array" {
65226522 This kind of type resolution chooses a type that all peer types can coerce into. Here are
65236523 some examples:
65246524 </p>
6525 {#code_begin|test|peer_type_resolution#}
6525 {#code_begin|test|test_peer_type_resolution#}
65266526const std = @import("std");
65276527const expect = std.testing.expect;
65286528const mem = std.mem;
......@@ -6634,7 +6634,7 @@ test "peer type resolution: *const T and ?*T" {
66346634 require 0 bits to represent. Code that makes use of these types is
66356635 not included in the final generated code:
66366636 </p>
6637 {#code_begin|syntax#}
6637 {#code_begin|syntax|zero_bit_types#}
66386638export fn entry() void {
66396639 var x: void = {};
66406640 var y: void = {};
......@@ -6657,7 +6657,7 @@ export fn entry() void {
66576657 {#syntax#}Map(Key, Value){#endsyntax#}, one can pass {#syntax#}void{#endsyntax#} for the {#syntax#}Value{#endsyntax#}
66586658 type to make it into a {#syntax#}Set{#endsyntax#}:
66596659 </p>
6660 {#code_begin|test|void_in_hashmap#}
6660 {#code_begin|test|test_void_in_hashmap#}
66616661const std = @import("std");
66626662const expect = std.testing.expect;
66636663
......@@ -6687,7 +6687,7 @@ test "turn HashMap into a set with void" {
66876687 <p>
66886688 Expressions of type {#syntax#}void{#endsyntax#} are the only ones whose value can be ignored. For example:
66896689 </p>
6690 {#code_begin|test_err|ignored#}
6690 {#code_begin|test_err|test_expression_ignored|ignored#}
66916691test "ignoring expression value" {
66926692 foo();
66936693}
......@@ -6697,7 +6697,7 @@ fn foo() i32 {
66976697}
66986698 {#code_end#}
66996699 <p>However, if the expression has type {#syntax#}void{#endsyntax#}, there will be no error. Function return values can also be explicitly ignored by assigning them to {#syntax#}_{#endsyntax#}. </p>
6700 {#code_begin|test|void_ignored#}
6700 {#code_begin|test|test_void_ignored#}
67016701test "void is ignored" {
67026702 returnsVoid();
67036703}
......@@ -6727,7 +6727,7 @@ fn foo() i32 {
67276727 declarations of the operand, which must be a {#link|struct#}, {#link|union#}, {#link|enum#},
67286728 or {#link|opaque#}, into the namespace:
67296729 </p>
6730 {#code_begin|test|usingnamespace#}
6730 {#code_begin|test|test_usingnamespace#}
67316731test "using std namespace" {
67326732 const S = struct {
67336733 usingnamespace @import("std");
......@@ -6769,7 +6769,7 @@ pub usingnamespace @cImport({
67696769 <p>
67706770 Compile-time parameters is how Zig implements generics. It is compile-time duck typing.
67716771 </p>
6772 {#code_begin|syntax#}
6772 {#code_begin|syntax|compile-time_duck_typing#}
67736773fn max(comptime T: type, a: T, b: T) T {
67746774 return if (a > b) a else b;
67756775}
......@@ -6795,7 +6795,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
67956795 <p>
67966796 For example, if we were to introduce another function to the above snippet:
67976797 </p>
6798 {#code_begin|test_err|unable to resolve comptime value#}
6798 {#code_begin|test_err|test_unresolved_comptime_value|unable to resolve comptime value#}
67996799fn max(comptime T: type, a: T, b: T) T {
68006800 return if (a > b) a else b;
68016801}
......@@ -6821,7 +6821,7 @@ fn foo(condition: bool) void {
68216821 <p>
68226822 For example:
68236823 </p>
6824 {#code_begin|test_err|operator > not allowed for type 'bool'#}
6824 {#code_begin|test_err|test_comptime_mismatched_type|operator > not allowed for type 'bool'#}
68256825fn max(comptime T: type, a: T, b: T) T {
68266826 return if (a > b) a else b;
68276827}
......@@ -6834,7 +6834,7 @@ test "try to compare bools" {
68346834 value is known at compile-time. This means that we actually could make this work for the bool type
68356835 if we wanted to:
68366836 </p>
6837 {#code_begin|test|comptime_max_with_bool#}
6837 {#code_begin|test|test_comptime_max_with_bool#}
68386838fn max(comptime T: type, a: T, b: T) T {
68396839 if (T == bool) {
68406840 return a or b;
......@@ -6857,7 +6857,7 @@ test "try to compare bools" {
68576857 This means that the actual function generated for {#syntax#}max{#endsyntax#} in this situation looks like
68586858 this:
68596859 </p>
6860 {#code_begin|syntax#}
6860 {#code_begin|syntax|compiler_generated_function#}
68616861fn max(a: bool, b: bool) bool {
68626862 return a or b;
68636863}
......@@ -6884,7 +6884,7 @@ fn max(a: bool, b: bool) bool {
68846884 <p>
68856885 For example:
68866886 </p>
6887 {#code_begin|test|comptime_vars#}
6887 {#code_begin|test|test_comptime_evaluation#}
68886888const expect = @import("std").testing.expect;
68896889
68906890const CmdFn = struct {
......@@ -6966,7 +6966,7 @@ fn performFn(start_value: i32) i32 {
69666966 use a {#syntax#}comptime{#endsyntax#} expression to guarantee that the expression will be evaluated at compile-time.
69676967 If this cannot be accomplished, the compiler will emit an error. For example:
69686968 </p>
6969 {#code_begin|test_err|comptime call of extern function#}
6969 {#code_begin|test_err|test_comptime_call_extern_function|comptime call of extern function#}
69706970extern fn exit() noreturn;
69716971
69726972test "foo" {
......@@ -6997,7 +6997,7 @@ test "foo" {
69976997 <p>
69986998 Let's look at an example:
69996999 </p>
7000 {#code_begin|test|fibonacci_recursion#}
7000 {#code_begin|test|test_fibonacci_recursion#}
70017001const expect = @import("std").testing.expect;
70027002
70037003fn fibonacci(index: u32) u32 {
......@@ -7018,7 +7018,7 @@ test "fibonacci" {
70187018 <p>
70197019 Imagine if we had forgotten the base case of the recursive function and tried to run the tests:
70207020 </p>
7021 {#code_begin|test_err|overflow of integer type#}
7021 {#code_begin|test_err|test_fibonacci_comptime_overflow|overflow of integer type#}
70227022const expect = @import("std").testing.expect;
70237023
70247024fn fibonacci(index: u32) u32 {
......@@ -7041,7 +7041,7 @@ test "fibonacci" {
70417041 undefined behavior, which is always a compile error if the compiler knows it happened.
70427042 But what would have happened if we used a signed integer?
70437043 </p>
7044 {#code_begin|syntax#}
7044 {#code_begin|syntax|fibonacci_comptime_infinite_recursion#}
70457045const assert = @import("std").debug.assert;
70467046
70477047fn fibonacci(index: i32) i32 {
......@@ -7073,7 +7073,7 @@ test "fibonacci" {
70737073 What if we fix the base case, but put the wrong value in the
70747074 {#syntax#}expect{#endsyntax#} line?
70757075 </p>
7076 {#code_begin|test_err|reached unreachable#}
7076 {#code_begin|test_err|test_fibonacci_comptime_unreachable|reached unreachable#}
70777077const assert = @import("std").debug.assert;
70787078
70797079fn fibonacci(index: i32) i32 {
......@@ -7093,7 +7093,7 @@ test "fibonacci" {
70937093 {#syntax#}comptime{#endsyntax#} expressions. This means that we can use functions to
70947094 initialize complex static data. For example:
70957095 </p>
7096 {#code_begin|test|N_primes#}
7096 {#code_begin|test|test_container-level_comptime_expressions#}
70977097const first_25_primes = firstNPrimes(25);
70987098const sum_of_first_25_primes = sum(&first_25_primes);
70997099
......@@ -7152,7 +7152,7 @@ test "variable values" {
71527152 <p>
71537153 Here is an example of a generic {#syntax#}List{#endsyntax#} data structure.
71547154 </p>
7155 {#code_begin|syntax#}
7155 {#code_begin|syntax|generic_data_structure#}
71567156fn List(comptime T: type) type {
71577157 return struct {
71587158 items: []T,
......@@ -7177,7 +7177,7 @@ var list = List(i32){
71777177 <p>
71787178 To explicitly give a type a name, we assign it to a constant.
71797179 </p>
7180 {#code_begin|syntax#}
7180 {#code_begin|syntax|anonymous_struct_name#}
71817181const Node = struct {
71827182 next: ?*Node,
71837183 name: []const u8,
......@@ -7360,7 +7360,7 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void {
73607360 <p>
73617361 And now, what happens if we give too many arguments to {#syntax#}print{#endsyntax#}?
73627362 </p>
7363 {#code_begin|test_err|unused argument in 'here is a string: '{s}' here is a number: {}#}
7363 {#code_begin|test_err|test_print_too_many_args|unused argument in 'here is a string: '{s}' here is a number: {}#}
73647364const print = @import("std").debug.print;
73657365
73667366const a_number: i32 = 1234;
......@@ -7381,7 +7381,7 @@ test "print too many arguments" {
73817381 Zig doesn't care whether the format argument is a string literal,
73827382 only that it is a compile-time known value that can be coerced to a {#syntax#}[]const u8{#endsyntax#}:
73837383 </p>
7384 {#code_begin|exe|print#}
7384 {#code_begin|exe|print_comptime-known_format#}
73857385const print = @import("std").debug.print;
73867386
73877387const a_number: i32 = 1234;
......@@ -7410,7 +7410,7 @@ pub fn main() void {
74107410 can use inline assembly. Here is an example of implementing Hello, World on x86_64 Linux
74117411 using inline assembly:
74127412 </p>
7413 {#code_begin|exe#}
7413 {#code_begin|exe|inline_assembly#}
74147414 {#target_linux_x86_64#}
74157415pub fn main() noreturn {
74167416 const msg = "hello world\n";
......@@ -7572,7 +7572,7 @@ volatile (
75727572 verbatim into one long string and assembled together. There are no template substitution rules regarding
75737573 <code>%</code> as there are in inline assembly expressions.
75747574 </p>
7575 {#code_begin|test|global-asm#}
7575 {#code_begin|test|test_global_assembly#}
75767576 {#target_linux_x86_64#}
75777577const std = @import("std");
75787578const expect = std.testing.expect;
......@@ -7845,7 +7845,7 @@ comptime {
78457845 <p>
78467846 Calls a function, in the same way that invoking an expression with parentheses does:
78477847 </p>
7848 {#code_begin|test|call#}
7848 {#code_begin|test|test_call_builtin#}
78497849const expect = @import("std").testing.expect;
78507850
78517851test "noinline function call" {
......@@ -7979,7 +7979,7 @@ pub const CallModifier = enum {
79797979 This function performs a strong atomic compare exchange operation. It's the equivalent of this code,
79807980 except atomic:
79817981 </p>
7982 {#code_begin|syntax#}
7982 {#code_begin|syntax|not_atomic_cmpxchgStrong#}
79837983fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_value: T) ?T {
79847984 const old_value = ptr.*;
79857985 if (old_value == expected_value) {
......@@ -8060,7 +8060,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
80608060 This function can be used to do "printf debugging" on
80618061 compile-time executing code.
80628062 </p>
8063 {#code_begin|test_err|found compile log statement#}
8063 {#code_begin|test_err|test_compileLog_builtin|found compile log statement#}
80648064const print = @import("std").debug.print;
80658065
80668066const num1 = blk: {
......@@ -8081,7 +8081,7 @@ test "main" {
80818081 not encountered by analysis, the
80828082 program compiles successfully and the generated executable prints:
80838083 </p>
8084 {#code_begin|test|without_compileLog#}
8084 {#code_begin|test|test_without_compileLog_builtin#}
80858085const print = @import("std").debug.print;
80868086
80878087const num1 = blk: {
......@@ -8296,7 +8296,7 @@ test "main" {
82968296 {#syntax#}options.linkage{#endsyntax#} is {#syntax#}Strong{#endsyntax#}, this is equivalent to
82978297 the {#syntax#}export{#endsyntax#} keyword used on a function:
82988298 </p>
8299 {#code_begin|obj#}
8299 {#code_begin|obj|export_builtin#}
83008300comptime {
83018301 @export(internalName, .{ .name = "foo", .linkage = .Strong });
83028302}
......@@ -8304,12 +8304,12 @@ comptime {
83048304fn internalName() callconv(.C) void {}
83058305 {#code_end#}
83068306 <p>This is equivalent to:</p>
8307 {#code_begin|obj#}
8307 {#code_begin|obj|export_builtin_equivalent_code#}
83088308export fn foo() void {}
83098309 {#code_end#}
83108310 <p>Note that even when using {#syntax#}export{#endsyntax#}, the {#syntax#}@"foo"{#endsyntax#} syntax for
83118311 {#link|identifiers|Identifiers#} can be used to choose any string for the symbol name:</p>
8312 {#code_begin|obj#}
8312 {#code_begin|obj|export_any_symbol_name#}
83138313export fn @"A function name that is a complete sentence."() void {}
83148314 {#code_end#}
83158315 <p>
......@@ -8342,7 +8342,7 @@ export fn @"A function name that is a complete sentence."() void {}
83428342 <pre>{#syntax#}@field(lhs: anytype, comptime field_name: []const u8) (field){#endsyntax#}</pre>
83438343 <p>Performs field access by a compile-time string. Works on both fields and declarations.
83448344 </p>
8345 {#code_begin|test|field_decl_access_by_string#}
8345 {#code_begin|test|test_field_builtin#}
83468346const std = @import("std");
83478347
83488348const Point = struct {
......@@ -8424,7 +8424,7 @@ test "decl access by string" {
84248424 Returns whether or not a {#link|container|Containers#} has a declaration
84258425 matching {#syntax#}name{#endsyntax#}.
84268426 </p>
8427 {#code_begin|test|hasDecl#}
8427 {#code_begin|test|test_hasDecl_builtin#}
84288428const std = @import("std");
84298429const expect = std.testing.expect;
84308430
......@@ -8504,7 +8504,7 @@ test "@hasDecl" {
85048504 Attempting to convert a number which is out of range of the destination type results in
85058505 safety-protected {#link|Undefined Behavior#}.
85068506 </p>
8507 {#code_begin|test_err|cast truncated bits#}
8507 {#code_begin|test_err|test_intCast_builtin|cast truncated bits#}
85088508test "integer cast panic" {
85098509 var a: u16 = 0xabcd;
85108510 var b: u8 = @intCast(u8, a);
......@@ -8654,7 +8654,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
86548654 designers targeting Wasm. So unless you are writing a new allocator from scratch, you should use
86558655 something like {#syntax#}@import("std").heap.WasmPageAllocator{#endsyntax#}.
86568656 </p>
8657 {#code_begin|test|wasmMemoryGrow#}
8657 {#code_begin|test|test_wasmMemoryGrow_builtin#}
86588658const std = @import("std");
86598659const native_arch = @import("builtin").target.cpu.arch;
86608660const expect = std.testing.expect;
......@@ -8855,7 +8855,7 @@ pub const PrefetchOptions = struct {
88558855 <p>
88568856 Example:
88578857 </p>
8858 {#code_begin|test_err|evaluation exceeded 1000 backwards branches#}
8858 {#code_begin|test_err|test_without_setEvalBranchQuota_builtin|evaluation exceeded 1000 backwards branches#}
88598859test "foo" {
88608860 comptime {
88618861 var i = 0;
......@@ -8864,7 +8864,7 @@ test "foo" {
88648864}
88658865 {#code_end#}
88668866 <p>Now we use {#syntax#}@setEvalBranchQuota{#endsyntax#}:</p>
8867 {#code_begin|test|setEvalBranchQuota#}
8867 {#code_begin|test|test_setEvalBranchQuota_builtin#}
88688868test "foo" {
88698869 comptime {
88708870 @setEvalBranchQuota(1001);
......@@ -8882,7 +8882,7 @@ test "foo" {
88828882 <p>
88838883 Sets the floating point mode of the current scope. Possible values are:
88848884 </p>
8885 {#code_begin|syntax#}
8885 {#code_begin|syntax|FloatMode#}
88868886pub const FloatMode = enum {
88878887 Strict,
88888888 Optimized,
......@@ -8917,7 +8917,7 @@ pub const FloatMode = enum {
89178917 <p>
89188918 Sets whether runtime safety checks are enabled for the scope that contains the function call.
89198919 </p>
8920 {#code_begin|test_safety|integer overflow#}
8920 {#code_begin|test_safety|test_setRuntimeSafety_builtin|integer overflow#}
89218921 {#code_release_fast#}
89228922test "@setRuntimeSafety" {
89238923 // The builtin applies to the scope that it is called in. So here, integer overflow
......@@ -9020,7 +9020,7 @@ test "@setRuntimeSafety" {
90209020 {#link|pointer|Pointers#}, or {#syntax#}bool{#endsyntax#}. The mask may be any vector length, and its
90219021 length determines the result length.
90229022 </p>
9023 {#code_begin|test|vector_shuffle#}
9023 {#code_begin|test|test_shuffle_builtin#}
90249024const std = @import("std");
90259025const expect = std.testing.expect;
90269026
......@@ -9068,7 +9068,7 @@ test "vector @shuffle" {
90689068 Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value
90699069 {#syntax#}scalar{#endsyntax#}:
90709070 </p>
9071 {#code_begin|test|vector_splat#}
9071 {#code_begin|test|test_splat_builtin#}
90729072const std = @import("std");
90739073const expect = std.testing.expect;
90749074
......@@ -9111,7 +9111,7 @@ test "vector @splat" {
91119111 types the operation associativity is preserved, unless the float mode is
91129112 set to {#syntax#}Optimized{#endsyntax#}.
91139113 </p>
9114 {#code_begin|test|vector_reduce#}
9114 {#code_begin|test|test_reduce_builtin#}
91159115const std = @import("std");
91169116const expect = std.testing.expect;
91179117
......@@ -9133,7 +9133,7 @@ test "vector @reduce" {
91339133 <p>
91349134 Returns a {#syntax#}SourceLocation{#endsyntax#} struct representing the function's name and location in the source code. This must be called in a function.
91359135 </p>
9136 {#code_begin|test|source_location#}
9136 {#code_begin|test|test_src_builtin#}
91379137const std = @import("std");
91389138const expect = std.testing.expect;
91399139
......@@ -9147,7 +9147,7 @@ fn doTheTest() !void {
91479147 try expect(src.line == 9);
91489148 try expect(src.column == 17);
91499149 try expect(std.mem.endsWith(u8, src.fn_name, "doTheTest"));
9150 try expect(std.mem.endsWith(u8, src.file, "source_location.zig"));
9150 try expect(std.mem.endsWith(u8, src.file, "test_src_builtin.zig"));
91519151}
91529152 {#code_end#}
91539153 {#header_close#}
......@@ -9329,7 +9329,7 @@ fn doTheTest() !void {
93299329 Returns the innermost struct, enum, or union that this function call is inside.
93309330 This can be useful for an anonymous struct that needs to refer to itself:
93319331 </p>
9332 {#code_begin|test|this_innermost#}
9332 {#code_begin|test|test_this_builtin#}
93339333const std = @import("std");
93349334const expect = std.testing.expect;
93359335
......@@ -9370,7 +9370,7 @@ fn List(comptime T: type) type {
93709370 <p>
93719371 Calling {#syntax#}@truncate{#endsyntax#} on a number out of range of the destination type is well defined and working code:
93729372 </p>
9373 {#code_begin|test|truncate#}
9373 {#code_begin|test|test_truncate_builtin#}
93749374const std = @import("std");
93759375const expect = std.testing.expect;
93769376
......@@ -9458,7 +9458,7 @@ test "integer truncation" {
94589458 <p>
94599459 The expressions are evaluated, however they are guaranteed to have no <em>runtime</em> side-effects:
94609460 </p>
9461 {#code_begin|test|no_runtime_side_effects#}
9461 {#code_begin|test|test_TypeOf_builtin#}
94629462const std = @import("std");
94639463const expect = std.testing.expect;
94649464
......@@ -9592,14 +9592,14 @@ pub fn build(b: *Builder) void {
95929592 <p>
95939593 When a safety check fails, Zig crashes with a stack trace, like this:
95949594 </p>
9595 {#code_begin|test_err|reached unreachable code#}
9595 {#code_begin|test_err|test_undefined_behavior|reached unreachable code#}
95969596test "safety check" {
95979597 unreachable;
95989598}
95999599 {#code_end#}
96009600 {#header_open|Reaching Unreachable Code#}
96019601 <p>At compile-time:</p>
9602 {#code_begin|test_err|reached unreachable code#}
9602 {#code_begin|test_err|test_comptime_reaching_unreachable|reached unreachable code#}
96039603comptime {
96049604 assert(false);
96059605}
......@@ -9608,7 +9608,7 @@ fn assert(ok: bool) void {
96089608}
96099609 {#code_end#}
96109610 <p>At runtime:</p>
9611 {#code_begin|exe_err#}
9611 {#code_begin|exe_err|runtime_reaching_unreachable#}
96129612const std = @import("std");
96139613
96149614pub fn main() void {
......@@ -9618,7 +9618,7 @@ pub fn main() void {
96189618 {#header_close#}
96199619 {#header_open|Index out of Bounds#}
96209620 <p>At compile-time:</p>
9621 {#code_begin|test_err|index 5 outside array of length 5#}
9621 {#code_begin|test_err|test_comptime_index_out_of_bounds|index 5 outside array of length 5#}
96229622comptime {
96239623 const array: [5]u8 = "hello".*;
96249624 const garbage = array[5];
......@@ -9626,7 +9626,7 @@ comptime {
96269626}
96279627 {#code_end#}
96289628 <p>At runtime:</p>
9629 {#code_begin|exe_err#}
9629 {#code_begin|exe_err|runtime_index_out_of_bounds#}
96309630pub fn main() void {
96319631 var x = foo("hello");
96329632 _ = x;
......@@ -9639,7 +9639,7 @@ fn foo(x: []const u8) u8 {
96399639 {#header_close#}
96409640 {#header_open|Cast Negative Number to Unsigned Integer#}
96419641 <p>At compile-time:</p>
9642 {#code_begin|test_err|type 'u32' cannot represent integer value '-1'#}
9642 {#code_begin|test_err|test_comptime_invalid_cast|type 'u32' cannot represent integer value '-1'#}
96439643comptime {
96449644 var value: i32 = -1;
96459645 const unsigned = @intCast(u32, value);
......@@ -9647,7 +9647,7 @@ comptime {
96479647}
96489648 {#code_end#}
96499649 <p>At runtime:</p>
9650 {#code_begin|exe_err#}
9650 {#code_begin|exe_err|runtime_invalid_cast#}
96519651const std = @import("std");
96529652
96539653pub fn main() void {
......@@ -9662,7 +9662,7 @@ pub fn main() void {
96629662 {#header_close#}
96639663 {#header_open|Cast Truncates Data#}
96649664 <p>At compile-time:</p>
9665 {#code_begin|test_err|type 'u8' cannot represent integer value '300'#}
9665 {#code_begin|test_err|test_comptime_invalid_cast_truncate|type 'u8' cannot represent integer value '300'#}
96669666comptime {
96679667 const spartan_count: u16 = 300;
96689668 const byte = @intCast(u8, spartan_count);
......@@ -9670,7 +9670,7 @@ comptime {
96709670}
96719671 {#code_end#}
96729672 <p>At runtime:</p>
9673 {#code_begin|exe_err#}
9673 {#code_begin|exe_err|runtime_invalid_cast_truncate#}
96749674const std = @import("std");
96759675
96769676pub fn main() void {
......@@ -9697,14 +9697,14 @@ pub fn main() void {
96979697 <li>{#link|@divExact#} (division)</li>
96989698 </ul>
96999699 <p>Example with addition at compile-time:</p>
9700 {#code_begin|test_err|overflow of integer type 'u8' with value '256'#}
9700 {#code_begin|test_err|test_comptime_overflow|overflow of integer type 'u8' with value '256'#}
97019701comptime {
97029702 var byte: u8 = 255;
97039703 byte += 1;
97049704}
97059705 {#code_end#}
97069706 <p>At runtime:</p>
9707 {#code_begin|exe_err#}
9707 {#code_begin|exe_err|runtime_overflow#}
97089708const std = @import("std");
97099709
97109710pub fn main() void {
......@@ -9726,7 +9726,7 @@ pub fn main() void {
97269726 <li>{#syntax#}@import("std").math.shl{#endsyntax#}</li>
97279727 </ul>
97289728 <p>Example of catching an overflow for addition:</p>
9729 {#code_begin|exe_err#}
9729 {#code_begin|exe_err|math_add#}
97309730const math = @import("std").math;
97319731const print = @import("std").debug.print;
97329732pub fn main() !void {
......@@ -9755,7 +9755,7 @@ pub fn main() !void {
97559755 <p>
97569756 Example of {#link|@addWithOverflow#}:
97579757 </p>
9758 {#code_begin|exe#}
9758 {#code_begin|exe|addWithOverflow_builtin#}
97599759const print = @import("std").debug.print;
97609760pub fn main() void {
97619761 var byte: u8 = 255;
......@@ -9779,7 +9779,7 @@ pub fn main() void {
97799779 <li>{#syntax#}-%{#endsyntax#} (wraparound negation)</li>
97809780 <li>{#syntax#}*%{#endsyntax#} (wraparound multiplication)</li>
97819781 </ul>
9782 {#code_begin|test|wraparound_semantics#}
9782 {#code_begin|test|test_wraparound_semantics#}
97839783const std = @import("std");
97849784const expect = std.testing.expect;
97859785const minInt = std.math.minInt;
......@@ -9797,14 +9797,14 @@ test "wraparound addition and subtraction" {
97979797 {#header_close#}
97989798 {#header_open|Exact Left Shift Overflow#}
97999799 <p>At compile-time:</p>
9800 {#code_begin|test_err|operation caused overflow#}
9800 {#code_begin|test_err|test_comptime_shlExact_overwlow|operation caused overflow#}
98019801comptime {
98029802 const x = @shlExact(@as(u8, 0b01010101), 2);
98039803 _ = x;
98049804}
98059805 {#code_end#}
98069806 <p>At runtime:</p>
9807 {#code_begin|exe_err#}
9807 {#code_begin|exe_err|runtime_shlExact_overflow#}
98089808const std = @import("std");
98099809
98109810pub fn main() void {
......@@ -9816,14 +9816,14 @@ pub fn main() void {
98169816 {#header_close#}
98179817 {#header_open|Exact Right Shift Overflow#}
98189818 <p>At compile-time:</p>
9819 {#code_begin|test_err|exact shift shifted out 1 bits#}
9819 {#code_begin|test_err|test_comptime_shrExact_overflow|exact shift shifted out 1 bits#}
98209820comptime {
98219821 const x = @shrExact(@as(u8, 0b10101010), 2);
98229822 _ = x;
98239823}
98249824 {#code_end#}
98259825 <p>At runtime:</p>
9826 {#code_begin|exe_err#}
9826 {#code_begin|exe_err|runtime_shrExact_overflow#}
98279827const std = @import("std");
98289828
98299829pub fn main() void {
......@@ -9835,7 +9835,7 @@ pub fn main() void {
98359835 {#header_close#}
98369836 {#header_open|Division by Zero#}
98379837 <p>At compile-time:</p>
9838 {#code_begin|test_err|division by zero#}
9838 {#code_begin|test_err|test_comptime_division_by_zero|division by zero#}
98399839comptime {
98409840 const a: i32 = 1;
98419841 const b: i32 = 0;
......@@ -9844,7 +9844,7 @@ comptime {
98449844}
98459845 {#code_end#}
98469846 <p>At runtime:</p>
9847 {#code_begin|exe_err#}
9847 {#code_begin|exe_err|runtime_division_by_zero#}
98489848const std = @import("std");
98499849
98509850pub fn main() void {
......@@ -9857,7 +9857,7 @@ pub fn main() void {
98579857 {#header_close#}
98589858 {#header_open|Remainder Division by Zero#}
98599859 <p>At compile-time:</p>
9860 {#code_begin|test_err|division by zero#}
9860 {#code_begin|test_err|test_comptime_remainder_division_by_zero|division by zero#}
98619861comptime {
98629862 const a: i32 = 10;
98639863 const b: i32 = 0;
......@@ -9866,7 +9866,7 @@ comptime {
98669866}
98679867 {#code_end#}
98689868 <p>At runtime:</p>
9869 {#code_begin|exe_err#}
9869 {#code_begin|exe_err|runtime_remainder_division_by_zero#}
98709870const std = @import("std");
98719871
98729872pub fn main() void {
......@@ -9879,7 +9879,7 @@ pub fn main() void {
98799879 {#header_close#}
98809880 {#header_open|Exact Division Remainder#}
98819881 <p>At compile-time:</p>
9882 {#code_begin|test_err|exact division produced remainder#}
9882 {#code_begin|test_err|test_comptime_divExact_remainder|exact division produced remainder#}
98839883comptime {
98849884 const a: u32 = 10;
98859885 const b: u32 = 3;
......@@ -9888,7 +9888,7 @@ comptime {
98889888}
98899889 {#code_end#}
98909890 <p>At runtime:</p>
9891 {#code_begin|exe_err#}
9891 {#code_begin|exe_err|runtime_divExact_remainder#}
98929892const std = @import("std");
98939893
98949894pub fn main() void {
......@@ -9901,7 +9901,7 @@ pub fn main() void {
99019901 {#header_close#}
99029902 {#header_open|Attempt to Unwrap Null#}
99039903 <p>At compile-time:</p>
9904 {#code_begin|test_err|unable to unwrap null#}
9904 {#code_begin|test_err|test_comptime_unwrap_null|unable to unwrap null#}
99059905comptime {
99069906 const optional_number: ?i32 = null;
99079907 const number = optional_number.?;
......@@ -9909,7 +9909,7 @@ comptime {
99099909}
99109910 {#code_end#}
99119911 <p>At runtime:</p>
9912 {#code_begin|exe_err#}
9912 {#code_begin|exe_err|runtime_unwrap_null#}
99139913const std = @import("std");
99149914
99159915pub fn main() void {
......@@ -9920,7 +9920,7 @@ pub fn main() void {
99209920 {#code_end#}
99219921 <p>One way to avoid this crash is to test for null instead of assuming non-null, with
99229922 the {#syntax#}if{#endsyntax#} expression:</p>
9923 {#code_begin|exe|test#}
9923 {#code_begin|exe|testing_null_with_if#}
99249924const print = @import("std").debug.print;
99259925pub fn main() void {
99269926 const optional_number: ?i32 = null;
......@@ -9936,7 +9936,7 @@ pub fn main() void {
99369936 {#header_close#}
99379937 {#header_open|Attempt to Unwrap Error#}
99389938 <p>At compile-time:</p>
9939 {#code_begin|test_err|caught unexpected error 'UnableToReturnNumber'#}
9939 {#code_begin|test_err|test_comptime_unwrap_error|caught unexpected error 'UnableToReturnNumber'#}
99409940comptime {
99419941 const number = getNumberOrFail() catch unreachable;
99429942 _ = number;
......@@ -9947,7 +9947,7 @@ fn getNumberOrFail() !i32 {
99479947}
99489948 {#code_end#}
99499949 <p>At runtime:</p>
9950 {#code_begin|exe_err#}
9950 {#code_begin|exe_err|runtime_unwrap_error#}
99519951const std = @import("std");
99529952
99539953pub fn main() void {
......@@ -9961,7 +9961,7 @@ fn getNumberOrFail() !i32 {
99619961 {#code_end#}
99629962 <p>One way to avoid this crash is to test for an error instead of assuming a successful result, with
99639963 the {#syntax#}if{#endsyntax#} expression:</p>
9964 {#code_begin|exe#}
9964 {#code_begin|exe|testing_error_with_if#}
99659965const print = @import("std").debug.print;
99669966
99679967pub fn main() void {
......@@ -9982,7 +9982,7 @@ fn getNumberOrFail() !i32 {
99829982 {#header_close#}
99839983 {#header_open|Invalid Error Code#}
99849984 <p>At compile-time:</p>
9985 {#code_begin|test_err|integer value '11' represents no error#}
9985 {#code_begin|test_err|test_comptime_invalid_error_code|integer value '11' represents no error#}
99869986comptime {
99879987 const err = error.AnError;
99889988 const number = @errorToInt(err) + 10;
......@@ -9991,7 +9991,7 @@ comptime {
99919991}
99929992 {#code_end#}
99939993 <p>At runtime:</p>
9994 {#code_begin|exe_err#}
9994 {#code_begin|exe_err|runtime_invalid_error_code#}
99959995const std = @import("std");
99969996
99979997pub fn main() void {
......@@ -10004,7 +10004,7 @@ pub fn main() void {
1000410004 {#header_close#}
1000510005 {#header_open|Invalid Enum Cast#}
1000610006 <p>At compile-time:</p>
10007 {#code_begin|test_err|enum 'test.Foo' has no tag with value '3'#}
10007 {#code_begin|test_err|test_comptime_invalid_enum_cast|enum 'test_comptime_invalid_enum_cast.Foo' has no tag with value '3'#}
1000810008const Foo = enum {
1000910009 a,
1001010010 b,
......@@ -10017,7 +10017,7 @@ comptime {
1001710017}
1001810018 {#code_end#}
1001910019 <p>At runtime:</p>
10020 {#code_begin|exe_err#}
10020 {#code_begin|exe_err|runtime_invalid_enum_cast#}
1002110021const std = @import("std");
1002210022
1002310023const Foo = enum {
......@@ -10036,7 +10036,7 @@ pub fn main() void {
1003610036
1003710037 {#header_open|Invalid Error Set Cast#}
1003810038 <p>At compile-time:</p>
10039 {#code_begin|test_err|'error.B' not a member of error set 'error{A,C}'#}
10039 {#code_begin|test_err|test_comptime_invalid_error_set_cast|'error.B' not a member of error set 'error{A,C}'#}
1004010040const Set1 = error{
1004110041 A,
1004210042 B,
......@@ -10050,7 +10050,7 @@ comptime {
1005010050}
1005110051 {#code_end#}
1005210052 <p>At runtime:</p>
10053 {#code_begin|exe_err#}
10053 {#code_begin|exe_err|runtime_invalid_error_set_cast#}
1005410054const std = @import("std");
1005510055
1005610056const Set1 = error{
......@@ -10073,7 +10073,7 @@ fn foo(set1: Set1) void {
1007310073
1007410074 {#header_open|Incorrect Pointer Alignment#}
1007510075 <p>At compile-time:</p>
10076 {#code_begin|test_err|pointer address 0x1 is not aligned to 4 bytes#}
10076 {#code_begin|test_err|test_comptime_incorrect_pointer_alignment|pointer address 0x1 is not aligned to 4 bytes#}
1007710077comptime {
1007810078 const ptr = @intToPtr(*align(1) i32, 0x1);
1007910079 const aligned = @alignCast(4, ptr);
......@@ -10081,7 +10081,7 @@ comptime {
1008110081}
1008210082 {#code_end#}
1008310083 <p>At runtime:</p>
10084 {#code_begin|exe_err#}
10084 {#code_begin|exe_err|runtime_incorrect_pointer_alignment#}
1008510085const mem = @import("std").mem;
1008610086pub fn main() !void {
1008710087 var array align(4) = [_]u32{ 0x11111111, 0x11111111 };
......@@ -10097,7 +10097,7 @@ fn foo(bytes: []u8) u32 {
1009710097 {#header_close#}
1009810098 {#header_open|Wrong Union Field Access#}
1009910099 <p>At compile-time:</p>
10100 {#code_begin|test_err|access of union field 'float' while field 'int' is active#}
10100 {#code_begin|test_err|test_comptime_wrong_union_field_access|access of union field 'float' while field 'int' is active#}
1010110101comptime {
1010210102 var f = Foo{ .int = 42 };
1010310103 f.float = 12.34;
......@@ -10109,7 +10109,7 @@ const Foo = union {
1010910109};
1011010110 {#code_end#}
1011110111 <p>At runtime:</p>
10112 {#code_begin|exe_err#}
10112 {#code_begin|exe_err|runtime_wrong_union_field_access#}
1011310113const std = @import("std");
1011410114
1011510115const Foo = union {
......@@ -10133,7 +10133,7 @@ fn bar(f: *Foo) void {
1013310133 <p>
1013410134 To change the active field of a union, assign the entire union, like this:
1013510135 </p>
10136 {#code_begin|exe#}
10136 {#code_begin|exe|change_active_union_field#}
1013710137const std = @import("std");
1013810138
1013910139const Foo = union {
......@@ -10155,7 +10155,7 @@ fn bar(f: *Foo) void {
1015510155 To change the active field of a union when a meaningful value for the field is not known,
1015610156 use {#link|undefined#}, like this:
1015710157 </p>
10158 {#code_begin|exe#}
10158 {#code_begin|exe|undefined_active_union_field#}
1015910159const std = @import("std");
1016010160
1016110161const Foo = union {
......@@ -10188,7 +10188,7 @@ fn bar(f: *Foo) void {
1018810188 allow address zero, but normal {#link|Pointers#} do not.
1018910189 </p>
1019010190 <p>At compile-time:</p>
10191 {#code_begin|test_err|null pointer casted to type#}
10191 {#code_begin|test_err|test_comptime_invalid_null_pointer_cast|null pointer casted to type#}
1019210192comptime {
1019310193 const opt_ptr: ?*i32 = null;
1019410194 const ptr = @ptrCast(*i32, opt_ptr);
......@@ -10196,7 +10196,7 @@ comptime {
1019610196}
1019710197 {#code_end#}
1019810198 <p>At runtime:</p>
10199 {#code_begin|exe_err#}
10199 {#code_begin|exe_err|runtime_invalid_null_pointer_cast#}
1020010200pub fn main() void {
1020110201 var opt_ptr: ?*i32 = null;
1020210202 var ptr = @ptrCast(*i32, opt_ptr);
......@@ -10224,7 +10224,7 @@ pub fn main() void {
1022410224 {#syntax#}std.ArrayList{#endsyntax#} accept an {#syntax#}Allocator{#endsyntax#} parameter in
1022510225 their initialization functions:
1022610226 </p>
10227 {#code_begin|test|allocator#}
10227 {#code_begin|test|test_allocator#}
1022810228const std = @import("std");
1022910229const Allocator = std.mem.Allocator;
1023010230const expect = std.testing.expect;
......@@ -10278,7 +10278,7 @@ fn concat(allocator: Allocator, a: []const u8, b: []const u8) ![]u8 {
1027810278 cyclical pattern (such as a video game main loop, or a web server request handler),
1027910279 such that it would make sense to free everything at once at the end?
1028010280 In this case, it is recommended to follow this pattern:
10281 {#code_begin|exe|cli_allocation#}
10281 {#code_begin|exe|cli_allocation#}
1028210282const std = @import("std");
1028310283
1028410284pub fn main() !void {
......@@ -10290,7 +10290,7 @@ pub fn main() !void {
1029010290 const ptr = try allocator.create(i32);
1029110291 std.debug.print("ptr={*}\n", .{ptr});
1029210292}
10293 {#code_end#}
10293 {#code_end#}
1029410294 When using this kind of allocator, there is no need to free anything manually. Everything
1029510295 gets freed at once with the call to {#syntax#}arena.deinit(){#endsyntax#}.
1029610296 </li>
......@@ -10328,7 +10328,7 @@ pub fn main() !void {
1032810328 <p>String literals such as {#syntax#}"foo"{#endsyntax#} are in the global constant data section.
1032910329 This is why it is an error to pass a string literal to a mutable slice, like this:
1033010330 </p>
10331 {#code_begin|test_err|expected type '[]u8', found '*const [5:0]u8'#}
10331 {#code_begin|test_err|test_string_literal_to_slice|expected type '[]u8', found '*const [5:0]u8'#}
1033210332fn foo(s: []u8) void {
1033310333 _ = s;
1033410334}
......@@ -10338,7 +10338,7 @@ test "string literal to mutable slice" {
1033810338}
1033910339 {#code_end#}
1034010340 <p>However if you make the slice constant, then it works:</p>
10341 {#code_begin|test|strlit#}
10341 {#code_begin|test|test_string_literal_to_const_slice#}
1034210342fn foo(s: []const u8) void {
1034310343 _ = s;
1034410344}
......@@ -10474,7 +10474,7 @@ test "string literal to constant slice" {
1047410474 which the compiler makes available to every Zig source file. It contains
1047510475 compile-time constants such as the current target, endianness, and release mode.
1047610476 </p>
10477 {#code_begin|syntax#}
10477 {#code_begin|syntax|compile_variables#}
1047810478const builtin = @import("builtin");
1047910479const separator = if (builtin.os.tag == .windows) '\\' else '/';
1048010480 {#code_end#}
......@@ -10526,7 +10526,7 @@ const separator = if (builtin.os.tag == .windows) '\\' else '/';
1052610526 {#header_open|Building an Executable#}
1052710527 <p>This <code class="file">build.zig</code> file is automatically generated
1052810528 by <kbd>zig init-exe</kbd>.</p>
10529 {#code_begin|syntax|build#}
10529 {#code_begin|syntax|build_executable#}
1053010530const Builder = @import("std").build.Builder;
1053110531
1053210532pub fn build(b: *Builder) void {
......@@ -10560,7 +10560,7 @@ pub fn build(b: *Builder) void {
1056010560 {#header_open|Building a Library#}
1056110561 <p>This <code class="file">build.zig</code> file is automatically generated
1056210562 by <kbd>zig init-lib</kbd>.</p>
10563 {#code_begin|syntax|build#}
10563 {#code_begin|syntax|build_library#}
1056410564const Builder = @import("std").build.Builder;
1056510565
1056610566pub fn build(b: *Builder) void {
......@@ -10622,7 +10622,7 @@ lib.addCSourceFile("src/lib.c", &[_][]const u8{
1062210622 The {#syntax#}@cImport{#endsyntax#} builtin function can be used
1062310623 to directly import symbols from <code class="file">.h</code> files:
1062410624 </p>
10625 {#code_begin|exe#}
10625 {#code_begin|exe|cImport_builtin#}
1062610626 {#link_libc#}
1062710627const c = @cImport({
1062810628 // See https://github.com/ziglang/zig/issues/515
......@@ -10738,7 +10738,7 @@ pub extern fn do_something(foo: enum_FOO) c_int;{#end_shell_samp#}
1073810738 To see where the cached files are stored when compiling code that uses {#syntax#}@cImport{#endsyntax#},
1073910739 use the <kbd>--verbose-cimport</kbd> flag:
1074010740 </p>
10741 {#code_begin|exe|verbose#}
10741 {#code_begin|exe|verbose_cimport_flag#}
1074210742 {#link_libc#}
1074310743 {#code_verbose_cimport#}
1074410744const c = @cImport({
......@@ -10856,7 +10856,7 @@ pub const MAKELOCAL = @compileError("unable to translate C expr: unexpected toke
1085610856
1085710857 {#header_open|C Variadic Functions#}
1085810858 <p>Zig supports extern variadic functions.</p>
10859 {#code_begin|test|variadic_function#}
10859 {#code_begin|test|test_variadic_function#}
1086010860 {#link_libc#}
1086110861 {#code_verbose_cimport#}
1086210862const std = @import("std");
......@@ -10872,7 +10872,7 @@ test "variadic function" {
1087210872 <p>
1087310873 Variadic functions can be implemented using {#link|@cVaStart#}, {#link|@cVaEnd#}, {#link|@cVaArg#} and {#link|@cVaCopy#}
1087410874 </p>
10875 {#code_begin|test|defining_variadic_function#}
10875 {#code_begin|test|test_defining_variadic_function#}
1087610876const std = @import("std");
1087710877const testing = std.testing;
1087810878const builtin = @import("builtin");
......@@ -10926,7 +10926,7 @@ int main(int argc, char **argv) {
1092610926 return 0;
1092710927}
1092810928 {#end_syntax_block#}
10929 {#code_begin|syntax|build#}
10929 {#code_begin|syntax|build_c#}
1093010930const Builder = @import("std").build.Builder;
1093110931
1093210932pub fn build(b: *Builder) void {
......@@ -10988,7 +10988,7 @@ int main(int argc, char **argv) {
1098810988 return 0;
1098910989}
1099010990 {#end_syntax_block#}
10991 {#code_begin|syntax|build#}
10991 {#code_begin|syntax|build_object#}
1099210992const Builder = @import("std").build.Builder;
1099310993
1099410994pub fn build(b: *Builder) void {
......@@ -11040,7 +11040,7 @@ The result is 3{#end_shell_samp#}
1104011040 {#header_open|WASI#}
1104111041 <p>Zig's support for WebAssembly System Interface (WASI) is under active development.
1104211042 Example of using the standard library and reading command line arguments:</p>
11043 {#code_begin|exe|args#}
11043 {#code_begin|exe|wasi_args#}
1104411044 {#target_wasi#}
1104511045const std = @import("std");
1104611046
......@@ -11061,7 +11061,7 @@ pub fn main() !void {
11061110612: hello{#end_shell_samp#}
1106211062 <p>A more interesting example would be extracting the list of preopens from the runtime.
1106311063 This is now supported in the standard library via {#syntax#}std.fs.wasi.PreopenList{#endsyntax#}:</p>
11064 {#code_begin|exe|preopens#}
11064 {#code_begin|exe|wasi_preopens#}
1106511065 {#target_wasi#}
1106611066const std = @import("std");
1106711067const fs = std.fs;