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 {...@@ -539,12 +539,15 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
539 } else if (mem.eql(u8, tag_name, "code_begin")) {539 } else if (mem.eql(u8, tag_name, "code_begin")) {
540 _ = try eatToken(tokenizer, Token.Id.Separator);540 _ = try eatToken(tokenizer, Token.Id.Separator);
541 const code_kind_tok = try eatToken(tokenizer, Token.Id.TagContent);541 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 = "";
543 const maybe_sep = tokenizer.next();546 const maybe_sep = tokenizer.next();
544 switch (maybe_sep.id) {547 switch (maybe_sep.id) {
545 Token.Id.Separator => {548 Token.Id.Separator => {
546 const name_tok = try eatToken(tokenizer, Token.Id.TagContent);549 const error_tok = try eatToken(tokenizer, Token.Id.TagContent);
547 name = tokenizer.buffer[name_tok.start..name_tok.end];550 error_str = tokenizer.buffer[error_tok.start..error_tok.end];
548 _ = try eatToken(tokenizer, Token.Id.BracketClose);551 _ = try eatToken(tokenizer, Token.Id.BracketClose);
549 },552 },
550 Token.Id.BracketClose => {},553 Token.Id.BracketClose => {},
...@@ -562,16 +565,13 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {...@@ -562,16 +565,13 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
562 } else if (mem.eql(u8, code_kind_str, "test")) {565 } else if (mem.eql(u8, code_kind_str, "test")) {
563 code_kind_id = Code.Id.Test;566 code_kind_id = Code.Id.Test;
564 } else if (mem.eql(u8, code_kind_str, "test_err")) {567 } else if (mem.eql(u8, code_kind_str, "test_err")) {
565 code_kind_id = Code.Id{ .TestError = name };568 code_kind_id = Code.Id{ .TestError = error_str };
566 name = "test";
567 } else if (mem.eql(u8, code_kind_str, "test_safety")) {569 } else if (mem.eql(u8, code_kind_str, "test_safety")) {
568 code_kind_id = Code.Id{ .TestSafety = name };570 code_kind_id = Code.Id{ .TestSafety = error_str };
569 name = "test";
570 } else if (mem.eql(u8, code_kind_str, "obj")) {571 } else if (mem.eql(u8, code_kind_str, "obj")) {
571 code_kind_id = Code.Id{ .Obj = null };572 code_kind_id = Code.Id{ .Obj = null };
572 } else if (mem.eql(u8, code_kind_str, "obj_err")) {573 } else if (mem.eql(u8, code_kind_str, "obj_err")) {
573 code_kind_id = Code.Id{ .Obj = name };574 code_kind_id = Code.Id{ .Obj = error_str };
574 name = "test";
575 } else if (mem.eql(u8, code_kind_str, "lib")) {575 } else if (mem.eql(u8, code_kind_str, "lib")) {
576 code_kind_id = Code.Id.Lib;576 code_kind_id = Code.Id.Lib;
577 } else if (mem.eql(u8, code_kind_str, "syntax")) {577 } else if (mem.eql(u8, code_kind_str, "syntax")) {
doc/langref.html.in+208-208
...@@ -1039,7 +1039,7 @@ pub fn main() void {...@@ -1039,7 +1039,7 @@ pub fn main() void {
1039 <p>1039 <p>
1040 Code written within one or more {#syntax#}test{#endsyntax#} declarations can be used to ensure behavior meets expectations:1040 Code written within one or more {#syntax#}test{#endsyntax#} declarations can be used to ensure behavior meets expectations:
1041 </p>1041 </p>
1042 {#code_begin|test|introducing_zig_test#}1042 {#code_begin|test|testing_introduction#}
1043const std = @import("std");1043const std = @import("std");
10441044
1045test "expect addOne adds one to 41" {1045test "expect addOne adds one to 41" {
...@@ -1124,13 +1124,13 @@ fn addOne(number: i32) i32 {...@@ -1124,13 +1124,13 @@ fn addOne(number: i32) i32 {
1124 syntax. This syntax tells the compiler to ignore the result of the expression on the right side of the1124 syntax. This syntax tells the compiler to ignore the result of the expression on the right side of the
1125 assignment operator.1125 assignment operator.
1126 </p>1126 </p>
1127 {#code_begin|test|testdecl_container_top_level#}1127 {#code_begin|test|testing_nested_container_tests#}
1128const std = @import("std");1128const std = @import("std");
1129const expect = std.testing.expect;1129const expect = std.testing.expect;
11301130
1131// Imported source file tests will run when referenced from a top-level test declaration.1131// Imported source file tests will run when referenced from a top-level test declaration.
1132// The next line alone does not cause "introducing_zig_test.zig" tests to run.1132// 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
1135test {1135test {
1136 // To run nested container tests, either, call `refAllDecls` which will1136 // To run nested container tests, either, call `refAllDecls` which will
...@@ -1143,7 +1143,7 @@ test {...@@ -1143,7 +1143,7 @@ test {
1143 // The `_ = C;` syntax is a no-op reference to the identifier `C`.1143 // The `_ = C;` syntax is a no-op reference to the identifier `C`.
1144 _ = S;1144 _ = S;
1145 _ = U;1145 _ = U;
1146 _ = @import("introducing_zig_test.zig");1146 _ = @import("testing_introduction.zig");
1147}1147}
11481148
1149const S = struct {1149const S = struct {
...@@ -1184,7 +1184,7 @@ const U = union { // U is referenced by the file's top-level test declaration...@@ -1184,7 +1184,7 @@ const U = union { // U is referenced by the file's top-level test declaration
1184 When a test returns an error, the test is considered a failure and its {#link|error return trace|Error Return Traces#}1184 When a test returns an error, the test is considered a failure and its {#link|error return trace|Error Return Traces#}
1185 is output to standard error. The total number of failures will be reported after all tests have run.1185 is output to standard error. The total number of failures will be reported after all tests have run.
1186 </p>1186 </p>
1187 {#code_begin|test_err#}1187 {#code_begin|test_err|testing_failure#}
1188const std = @import("std");1188const std = @import("std");
11891189
1190test "expect this to fail" {1190test "expect this to fail" {
...@@ -1208,7 +1208,7 @@ test "expect this to succeed" {...@@ -1208,7 +1208,7 @@ test "expect this to succeed" {
1208 {#syntax#}error.SkipZigTest{#endsyntax#} and the default test runner will consider the test as being skipped.1208 {#syntax#}error.SkipZigTest{#endsyntax#} and the default test runner will consider the test as being skipped.
1209 The total number of skipped tests will be reported after all tests have run.1209 The total number of skipped tests will be reported after all tests have run.
1210 </p>1210 </p>
1211 {#code_begin|test#}1211 {#code_begin|test|testing_skip#}
1212test "this will be skipped" {1212test "this will be skipped" {
1213 return error.SkipZigTest;1213 return error.SkipZigTest;
1214}1214}
...@@ -1221,7 +1221,7 @@ test "this will be skipped" {...@@ -1221,7 +1221,7 @@ test "this will be skipped" {
1221 {#syntax#}std.testing.allocator{#endsyntax#}, the default test runner will report any leaks that are1221 {#syntax#}std.testing.allocator{#endsyntax#}, the default test runner will report any leaks that are
1222 found from using the testing allocator:1222 found from using the testing allocator:
1223 </p>1223 </p>
1224 {#code_begin|test_err|1 tests leaked memory#}1224 {#code_begin|test_err|testing_detect_leak|1 tests leaked memory#}
1225const std = @import("std");1225const std = @import("std");
12261226
1227test "detect leak" {1227test "detect leak" {
...@@ -1239,7 +1239,7 @@ test "detect leak" {...@@ -1239,7 +1239,7 @@ test "detect leak" {
1239 Use the {#link|compile variable|Compile Variables#} {#syntax#}@import("builtin").is_test{#endsyntax#}1239 Use the {#link|compile variable|Compile Variables#} {#syntax#}@import("builtin").is_test{#endsyntax#}
1240 to detect a test build:1240 to detect a test build:
1241 </p>1241 </p>
1242 {#code_begin|test|detect_test#}1242 {#code_begin|test|testing_detect_test#}
1243const std = @import("std");1243const std = @import("std");
1244const builtin = @import("builtin");1244const builtin = @import("builtin");
1245const expect = std.testing.expect;1245const expect = std.testing.expect;
...@@ -1264,7 +1264,7 @@ fn isATest() bool {...@@ -1264,7 +1264,7 @@ fn isATest() bool {
1264 you create tests. In addition to the <code>expect</code> function, this document uses a couple of more functions1264 you create tests. In addition to the <code>expect</code> function, this document uses a couple of more functions
1265 as exemplified here:1265 as exemplified here:
1266 </p>1266 </p>
1267 {#code_begin|test|testing_functions#}1267 {#code_begin|test|testing_namespace#}
1268const std = @import("std");1268const std = @import("std");
12691269
1270test "expectEqual demo" {1270test "expectEqual demo" {
...@@ -1319,7 +1319,7 @@ test "expectError demo" {...@@ -1319,7 +1319,7 @@ test "expectError demo" {
1319 <p>1319 <p>
1320 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.1320 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.
1321 </p>1321 </p>
1322 {#code_begin|syntax#}1322 {#code_begin|syntax|identifiers#}
1323const @"identifier with spaces in it" = 0xff;1323const @"identifier with spaces in it" = 0xff;
1324const @"1SmallStep4Man" = 112358;1324const @"1SmallStep4Man" = 112358;
13251325
...@@ -1342,7 +1342,7 @@ const color: Color = .@"really red";...@@ -1342,7 +1342,7 @@ const color: Color = .@"really red";
1342 {#link|comptime#}. If a container level variable is {#syntax#}const{#endsyntax#} then its value is1342 {#link|comptime#}. If a container level variable is {#syntax#}const{#endsyntax#} then its value is
1343 {#syntax#}comptime{#endsyntax#}-known, otherwise it is runtime-known.1343 {#syntax#}comptime{#endsyntax#}-known, otherwise it is runtime-known.
1344 </p>1344 </p>
1345 {#code_begin|test|container_level_variables#}1345 {#code_begin|test|test_container_level_variables#}
1346var y: i32 = add(10, x);1346var y: i32 = add(10, x);
1347const x: i32 = add(12, 34);1347const x: i32 = add(12, 34);
13481348
...@@ -1361,7 +1361,7 @@ const expect = std.testing.expect;...@@ -1361,7 +1361,7 @@ const expect = std.testing.expect;
1361 <p>1361 <p>
1362 Container level variables may be declared inside a {#link|struct#}, {#link|union#}, {#link|enum#}, or {#link|opaque#}:1362 Container level variables may be declared inside a {#link|struct#}, {#link|union#}, {#link|enum#}, or {#link|opaque#}:
1363 </p>1363 </p>
1364 {#code_begin|test|namespaced_container_level_variable#}1364 {#code_begin|test|test_namespaced_container_level_variable#}
1365const std = @import("std");1365const std = @import("std");
1366const expect = std.testing.expect;1366const expect = std.testing.expect;
13671367
...@@ -1385,7 +1385,7 @@ fn foo() i32 {...@@ -1385,7 +1385,7 @@ fn foo() i32 {
1385 <p>1385 <p>
1386 It is also possible to have local variables with static lifetime by using containers inside functions.1386 It is also possible to have local variables with static lifetime by using containers inside functions.
1387 </p>1387 </p>
1388 {#code_begin|test|static_local_variable#}1388 {#code_begin|test|test_static_local_variable#}
1389const std = @import("std");1389const std = @import("std");
1390const expect = std.testing.expect;1390const expect = std.testing.expect;
13911391
...@@ -1414,7 +1414,7 @@ fn foo() i32 {...@@ -1414,7 +1414,7 @@ fn foo() i32 {
1414 {#header_open|Thread Local Variables#}1414 {#header_open|Thread Local Variables#}
1415 <p>A variable may be specified to be a thread-local variable using the1415 <p>A variable may be specified to be a thread-local variable using the
1416 {#syntax#}threadlocal{#endsyntax#} keyword:</p>1416 {#syntax#}threadlocal{#endsyntax#} keyword:</p>
1417 {#code_begin|test|tls#}1417 {#code_begin|test|test_thread_local_variables#}
1418const std = @import("std");1418const std = @import("std");
1419const assert = std.debug.assert;1419const assert = std.debug.assert;
14201420
...@@ -1458,7 +1458,7 @@ fn testTls() void {...@@ -1458,7 +1458,7 @@ fn testTls() void {
1458 All variables declared in a {#syntax#}comptime{#endsyntax#} expression are implicitly1458 All variables declared in a {#syntax#}comptime{#endsyntax#} expression are implicitly
1459 {#syntax#}comptime{#endsyntax#} variables.1459 {#syntax#}comptime{#endsyntax#} variables.
1460 </p>1460 </p>
1461 {#code_begin|test|comptime_vars#}1461 {#code_begin|test|test_comptime_variables#}
1462const std = @import("std");1462const std = @import("std");
1463const expect = std.testing.expect;1463const expect = std.testing.expect;
14641464
...@@ -1582,7 +1582,7 @@ const nan = std.math.nan(f128);...@@ -1582,7 +1582,7 @@ const nan = std.math.nan(f128);
1582 {#header_open|Floating Point Operations#}1582 {#header_open|Floating Point Operations#}
1583 <p>By default floating point operations use {#syntax#}Strict{#endsyntax#} mode,1583 <p>By default floating point operations use {#syntax#}Strict{#endsyntax#} mode,
1584 but you can switch to {#syntax#}Optimized{#endsyntax#} mode on a per-block basis:</p>1584 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#}
1586 {#code_release_fast#}1586 {#code_release_fast#}
1587 {#code_disable_cache#}1587 {#code_disable_cache#}
1588const std = @import("std");1588const std = @import("std");
...@@ -1600,8 +1600,8 @@ export fn foo_optimized(x: f64) f64 {...@@ -1600,8 +1600,8 @@ export fn foo_optimized(x: f64) f64 {
1600 <p>For this test we have to separate code into two object files -1600 <p>For this test we have to separate code into two object files -
1601 otherwise the optimizer figures out all the values at compile-time,1601 otherwise the optimizer figures out all the values at compile-time,
1602 which operates in strict mode.</p>1602 which operates in strict mode.</p>
1603 {#code_begin|exe|float_mode#}1603 {#code_begin|exe|float_mode_exe#}
1604 {#code_link_object|foo#}1604 {#code_link_object|float_mode_obj#}
1605const print = @import("std").debug.print;1605const print = @import("std").debug.print;
16061606
1607extern fn foo_strict(x: f64) f64;1607extern fn foo_strict(x: f64) f64;
...@@ -2326,7 +2326,7 @@ or...@@ -2326,7 +2326,7 @@ or
2326 {#header_close#}2326 {#header_close#}
2327 {#header_close#}2327 {#header_close#}
2328 {#header_open|Arrays#}2328 {#header_open|Arrays#}
2329 {#code_begin|test|arrays#}2329 {#code_begin|test|test_arrays#}
2330const expect = @import("std").testing.expect;2330const expect = @import("std").testing.expect;
2331const assert = @import("std").debug.assert;2331const assert = @import("std").debug.assert;
2332const mem = @import("std").mem;2332const mem = @import("std").mem;
...@@ -2437,7 +2437,7 @@ test "array initialization with function calls" {...@@ -2437,7 +2437,7 @@ test "array initialization with function calls" {
2437 <p>2437 <p>
2438 Multidimensional arrays can be created by nesting arrays:2438 Multidimensional arrays can be created by nesting arrays:
2439 </p>2439 </p>
2440 {#code_begin|test|multidimensional#}2440 {#code_begin|test|test_multidimensional_arrays#}
2441const std = @import("std");2441const std = @import("std");
2442const expect = std.testing.expect;2442const expect = std.testing.expect;
24432443
...@@ -2468,7 +2468,7 @@ test "multidimensional arrays" {...@@ -2468,7 +2468,7 @@ test "multidimensional arrays" {
2468 The syntax {#syntax#}[N:x]T{#endsyntax#} describes an array which has a sentinel element of value {#syntax#}x{#endsyntax#} at the2468 The syntax {#syntax#}[N:x]T{#endsyntax#} describes an array which has a sentinel element of value {#syntax#}x{#endsyntax#} at the
2469 index corresponding to {#syntax#}len{#endsyntax#}.2469 index corresponding to {#syntax#}len{#endsyntax#}.
2470 </p>2470 </p>
2471 {#code_begin|test|null_terminated_array#}2471 {#code_begin|test|test_null_terminated_array#}
2472const std = @import("std");2472const std = @import("std");
2473const expect = std.testing.expect;2473const expect = std.testing.expect;
24742474
...@@ -2521,7 +2521,7 @@ test "null terminated array" {...@@ -2521,7 +2521,7 @@ test "null terminated array" {
2521 although small powers of two (2-64) are most typical. Note that excessively long vector lengths (e.g. 2^20) may2521 although small powers of two (2-64) are most typical. Note that excessively long vector lengths (e.g. 2^20) may
2522 result in compiler crashes on current versions of Zig.2522 result in compiler crashes on current versions of Zig.
2523 </p>2523 </p>
2524 {#code_begin|test|vector_example#}2524 {#code_begin|test|test_vector#}
2525const std = @import("std");2525const std = @import("std");
2526const expectEqual = std.testing.expectEqual;2526const expectEqual = std.testing.expectEqual;
25272527
...@@ -2609,7 +2609,7 @@ test "Conversion between vectors, arrays, and slices" {...@@ -2609,7 +2609,7 @@ test "Conversion between vectors, arrays, and slices" {
2609 </li>2609 </li>
2610 </ul>2610 </ul>
2611 <p>Use {#syntax#}&x{#endsyntax#} to obtain a single-item pointer:</p>2611 <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#}
2613const expect = @import("std").testing.expect;2613const expect = @import("std").testing.expect;
26142614
2615test "address of syntax" {2615test "address of syntax" {
...@@ -2647,7 +2647,7 @@ test "pointer array access" {...@@ -2647,7 +2647,7 @@ test "pointer array access" {
2647 <p>2647 <p>
2648 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.2648 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.
2649 </p>2649 </p>
2650 {#code_begin|test|pointer_arthemtic#}2650 {#code_begin|test|test_pointer_arithmetic#}
2651const expect = @import("std").testing.expect;2651const expect = @import("std").testing.expect;
26522652
2653test "pointer arithmetic with many-item pointer" {2653test "pointer arithmetic with many-item pointer" {
...@@ -2683,7 +2683,7 @@ test "pointer arithmetic with slices" {...@@ -2683,7 +2683,7 @@ test "pointer arithmetic with slices" {
2683 against this kind of undefined behavior. This is one reason2683 against this kind of undefined behavior. This is one reason
2684 we prefer slices to pointers.2684 we prefer slices to pointers.
2685 </p>2685 </p>
2686 {#code_begin|test|slice_bounds#}2686 {#code_begin|test|test_slice_bounds#}
2687const expect = @import("std").testing.expect;2687const expect = @import("std").testing.expect;
26882688
2689test "pointer slicing" {2689test "pointer slicing" {
...@@ -2699,7 +2699,7 @@ test "pointer slicing" {...@@ -2699,7 +2699,7 @@ test "pointer slicing" {
2699 {#code_end#}2699 {#code_end#}
2700 <p>Pointers work at compile-time too, as long as the code does not depend on2700 <p>Pointers work at compile-time too, as long as the code does not depend on
2701 an undefined memory layout:</p>2701 an undefined memory layout:</p>
2702 {#code_begin|test|comptime_pointers#}2702 {#code_begin|test|test_comptime_pointers#}
2703const expect = @import("std").testing.expect;2703const expect = @import("std").testing.expect;
27042704
2705test "comptime pointers" {2705test "comptime pointers" {
...@@ -2714,7 +2714,7 @@ test "comptime pointers" {...@@ -2714,7 +2714,7 @@ test "comptime pointers" {
2714 {#code_end#}2714 {#code_end#}
2715 <p>To convert an integer address into a pointer, use {#syntax#}@intToPtr{#endsyntax#}.2715 <p>To convert an integer address into a pointer, use {#syntax#}@intToPtr{#endsyntax#}.
2716 To convert a pointer to an integer, use {#syntax#}@ptrToInt{#endsyntax#}:</p>2716 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#}
2718const expect = @import("std").testing.expect;2718const expect = @import("std").testing.expect;
27192719
2720test "@ptrToInt and @intToPtr" {2720test "@ptrToInt and @intToPtr" {
...@@ -2726,7 +2726,7 @@ test "@ptrToInt and @intToPtr" {...@@ -2726,7 +2726,7 @@ test "@ptrToInt and @intToPtr" {
2726 {#code_end#}2726 {#code_end#}
2727 <p>Zig is able to preserve memory addresses in comptime code, as long as2727 <p>Zig is able to preserve memory addresses in comptime code, as long as
2728 the pointer is never dereferenced:</p>2728 the pointer is never dereferenced:</p>
2729 {#code_begin|test|comptime_pointer_conversion#}2729 {#code_begin|test|test_comptime_pointer_conversion#}
2730const expect = @import("std").testing.expect;2730const expect = @import("std").testing.expect;
27312731
2732test "comptime @intToPtr" {2732test "comptime @intToPtr" {
...@@ -2746,7 +2746,7 @@ test "comptime @intToPtr" {...@@ -2746,7 +2746,7 @@ test "comptime @intToPtr" {
2746 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.2746 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.
2747 In the following code, loads and stores with {#syntax#}mmio_ptr{#endsyntax#} are guaranteed to all happen2747 In the following code, loads and stores with {#syntax#}mmio_ptr{#endsyntax#} are guaranteed to all happen
2748 and in the same order as in source code:</p>2748 and in the same order as in source code:</p>
2749 {#code_begin|test|volatile#}2749 {#code_begin|test|test_volatile#}
2750const expect = @import("std").testing.expect;2750const expect = @import("std").testing.expect;
27512751
2752test "volatile" {2752test "volatile" {
...@@ -2765,7 +2765,7 @@ test "volatile" {...@@ -2765,7 +2765,7 @@ test "volatile" {
2765 operation that Zig cannot protect you against. Use {#syntax#}@ptrCast{#endsyntax#} only when other2765 operation that Zig cannot protect you against. Use {#syntax#}@ptrCast{#endsyntax#} only when other
2766 conversions are not possible.2766 conversions are not possible.
2767 </p>2767 </p>
2768 {#code_begin|test|pointer_casting#}2768 {#code_begin|test|test_pointer_casting#}
2769const std = @import("std");2769const std = @import("std");
2770const expect = std.testing.expect;2770const expect = std.testing.expect;
27712771
...@@ -2803,7 +2803,7 @@ test "pointer child type" {...@@ -2803,7 +2803,7 @@ test "pointer child type" {
2803 In Zig, a pointer type has an alignment value. If the value is equal to the2803 In Zig, a pointer type has an alignment value. If the value is equal to the
2804 alignment of the underlying type, it can be omitted from the type:2804 alignment of the underlying type, it can be omitted from the type:
2805 </p>2805 </p>
2806 {#code_begin|test|variable_alignment#}2806 {#code_begin|test|test_variable_alignment#}
2807const std = @import("std");2807const std = @import("std");
2808const builtin = @import("builtin");2808const builtin = @import("builtin");
2809const expect = std.testing.expect;2809const expect = std.testing.expect;
...@@ -2826,7 +2826,7 @@ test "variable alignment" {...@@ -2826,7 +2826,7 @@ test "variable alignment" {
2826 You can specify alignment on variables and functions. If you do this, then2826 You can specify alignment on variables and functions. If you do this, then
2827 pointers to them get the specified alignment:2827 pointers to them get the specified alignment:
2828 </p>2828 </p>
2829 {#code_begin|test|variable_func_alignment#}2829 {#code_begin|test|test_variable_func_alignment#}
2830const expect = @import("std").testing.expect;2830const expect = @import("std").testing.expect;
28312831
2832var foo: u8 align(4) = 100;2832var foo: u8 align(4) = 100;
...@@ -2860,7 +2860,7 @@ test "function alignment" {...@@ -2860,7 +2860,7 @@ test "function alignment" {
2860 pointer into a more aligned pointer. This is a no-op at runtime, but inserts a2860 pointer into a more aligned pointer. This is a no-op at runtime, but inserts a
2861 {#link|safety check|Incorrect Pointer Alignment#}:2861 {#link|safety check|Incorrect Pointer Alignment#}:
2862 </p>2862 </p>
2863 {#code_begin|test_safety|incorrect alignment#}2863 {#code_begin|test_safety|test_incorrect_pointer_alignment|incorrect alignment#}
2864const std = @import("std");2864const std = @import("std");
28652865
2866test "pointer alignment safety" {2866test "pointer alignment safety" {
...@@ -2885,7 +2885,7 @@ fn foo(bytes: []u8) u32 {...@@ -2885,7 +2885,7 @@ fn foo(bytes: []u8) u32 {
2885 did not have the {#syntax#}allowzero{#endsyntax#} attribute, this would be a2885 did not have the {#syntax#}allowzero{#endsyntax#} attribute, this would be a
2886 {#link|Pointer Cast Invalid Null#} panic:2886 {#link|Pointer Cast Invalid Null#} panic:
2887 </p>2887 </p>
2888 {#code_begin|test|allowzero#}2888 {#code_begin|test|test_allowzero#}
2889const std = @import("std");2889const std = @import("std");
2890const expect = std.testing.expect;2890const expect = std.testing.expect;
28912891
...@@ -2903,7 +2903,7 @@ test "allowzero" {...@@ -2903,7 +2903,7 @@ test "allowzero" {
2903 has a length determined by a sentinel value. This provides protection2903 has a length determined by a sentinel value. This provides protection
2904 against buffer overflow and overreads.2904 against buffer overflow and overreads.
2905 </p>2905 </p>
2906 {#code_begin|exe_build_err#}2906 {#code_begin|exe_build_err|sentinel-terminated_pointer#}
2907 {#link_libc#}2907 {#link_libc#}
2908const std = @import("std");2908const std = @import("std");
29092909
...@@ -2923,7 +2923,7 @@ pub fn main() anyerror!void {...@@ -2923,7 +2923,7 @@ pub fn main() anyerror!void {
2923 {#header_close#}2923 {#header_close#}
29242924
2925 {#header_open|Slices#}2925 {#header_open|Slices#}
2926 {#code_begin|test_safety|index out of bounds#}2926 {#code_begin|test_safety|test_basic_slices|index out of bounds#}
2927const expect = @import("std").testing.expect;2927const expect = @import("std").testing.expect;
29282928
2929test "basic slices" {2929test "basic slices" {
...@@ -2958,7 +2958,7 @@ test "basic slices" {...@@ -2958,7 +2958,7 @@ test "basic slices" {
2958}2958}
2959 {#code_end#}2959 {#code_end#}
2960 <p>This is one reason we prefer slices to pointers.</p>2960 <p>This is one reason we prefer slices to pointers.</p>
2961 {#code_begin|test|slices#}2961 {#code_begin|test|test_slices#}
2962const std = @import("std");2962const std = @import("std");
2963const expect = std.testing.expect;2963const expect = std.testing.expect;
2964const mem = std.mem;2964const mem = std.mem;
...@@ -3019,7 +3019,7 @@ test "slice pointer" {...@@ -3019,7 +3019,7 @@ test "slice pointer" {
3019 guarantee that there are no sentinel elements before that. Sentinel-terminated slices allow element3019 guarantee that there are no sentinel elements before that. Sentinel-terminated slices allow element
3020 access to the {#syntax#}len{#endsyntax#} index.3020 access to the {#syntax#}len{#endsyntax#} index.
3021 </p>3021 </p>
3022 {#code_begin|test|null_terminated_slice#}3022 {#code_begin|test|test_null_terminated_slice#}
3023const std = @import("std");3023const std = @import("std");
3024const expect = std.testing.expect;3024const expect = std.testing.expect;
30253025
...@@ -3035,7 +3035,7 @@ test "null terminated slice" {...@@ -3035,7 +3035,7 @@ test "null terminated slice" {
3035 {#syntax#}data[start..end :x]{#endsyntax#}, where {#syntax#}data{#endsyntax#} is a many-item pointer,3035 {#syntax#}data[start..end :x]{#endsyntax#}, where {#syntax#}data{#endsyntax#} is a many-item pointer,
3036 array or slice and {#syntax#}x{#endsyntax#} is the sentinel value.3036 array or slice and {#syntax#}x{#endsyntax#} is the sentinel value.
3037 </p>3037 </p>
3038 {#code_begin|test|null_terminated_slicing#}3038 {#code_begin|test|test_null_terminated_slicing#}
3039const std = @import("std");3039const std = @import("std");
3040const expect = std.testing.expect;3040const expect = std.testing.expect;
30413041
...@@ -3052,7 +3052,7 @@ test "null terminated slicing" {...@@ -3052,7 +3052,7 @@ test "null terminated slicing" {
3052 Sentinel-terminated slicing asserts that the element in the sentinel position of the backing data is3052 Sentinel-terminated slicing asserts that the element in the sentinel position of the backing data is
3053 actually the sentinel value. If this is not the case, safety-protected {#link|Undefined Behavior#} results.3053 actually the sentinel value. If this is not the case, safety-protected {#link|Undefined Behavior#} results.
3054 </p>3054 </p>
3055 {#code_begin|test_safety|sentinel mismatch#}3055 {#code_begin|test_safety|test_sentinel_mismatch|sentinel mismatch#}
3056const std = @import("std");3056const std = @import("std");
3057const expect = std.testing.expect;3057const expect = std.testing.expect;
30583058
...@@ -3074,7 +3074,7 @@ test "sentinel mismatch" {...@@ -3074,7 +3074,7 @@ test "sentinel mismatch" {
3074 {#header_close#}3074 {#header_close#}
30753075
3076 {#header_open|struct#}3076 {#header_open|struct#}
3077 {#code_begin|test|structs#}3077 {#code_begin|test|test_structs#}
3078// Declare a struct.3078// Declare a struct.
3079// Zig gives no guarantees about the order of fields and the size of3079// Zig gives no guarantees about the order of fields and the size of
3080// the struct but the fields are guaranteed to be ABI-aligned.3080// the struct but the fields are guaranteed to be ABI-aligned.
...@@ -3223,7 +3223,7 @@ test "linked list" {...@@ -3223,7 +3223,7 @@ test "linked list" {
3223 Each struct field may have an expression indicating the default field value. Such expressions3223 Each struct field may have an expression indicating the default field value. Such expressions
3224 are executed at {#link|comptime#}, and allow the field to be omitted in a struct literal expression:3224 are executed at {#link|comptime#}, and allow the field to be omitted in a struct literal expression:
3225 </p>3225 </p>
3226 {#code_begin|test|default_field_values#}3226 {#code_begin|test|test_struct_default_field_values#}
3227const Foo = struct {3227const Foo = struct {
3228 a: i32 = 1234,3228 a: i32 = 1234,
3229 b: i32,3229 b: i32,
...@@ -3272,7 +3272,7 @@ test "default struct initialization fields" {...@@ -3272,7 +3272,7 @@ test "default struct initialization fields" {
3272 in a {#link|@bitCast#} or a {#link|@ptrCast#} to reinterpret memory.3272 in a {#link|@bitCast#} or a {#link|@ptrCast#} to reinterpret memory.
3273 This even works at {#link|comptime#}:3273 This even works at {#link|comptime#}:
3274 </p>3274 </p>
3275 {#code_begin|test|packed_structs#}3275 {#code_begin|test|test_packed_structs#}
3276const std = @import("std");3276const std = @import("std");
3277const native_endian = @import("builtin").target.cpu.arch.endian();3277const native_endian = @import("builtin").target.cpu.arch.endian();
3278const expect = std.testing.expect;3278const expect = std.testing.expect;
...@@ -3316,7 +3316,7 @@ fn doTheTest() !void {...@@ -3316,7 +3316,7 @@ fn doTheTest() !void {
3316 <p>3316 <p>
3317 Zig allows the address to be taken of a non-byte-aligned field:3317 Zig allows the address to be taken of a non-byte-aligned field:
3318 </p>3318 </p>
3319 {#code_begin|test|pointer_to_non-byte_aligned_field#}3319 {#code_begin|test|test_pointer_to_non-byte_aligned_field#}
3320const std = @import("std");3320const std = @import("std");
3321const expect = std.testing.expect;3321const expect = std.testing.expect;
33223322
...@@ -3341,7 +3341,7 @@ test "pointer to non-byte-aligned field" {...@@ -3341,7 +3341,7 @@ test "pointer to non-byte-aligned field" {
3341 However, the pointer to a non-byte-aligned field has special properties and cannot3341 However, the pointer to a non-byte-aligned field has special properties and cannot
3342 be passed when a normal pointer is expected:3342 be passed when a normal pointer is expected:
3343 </p>3343 </p>
3344 {#code_begin|test_err|expected type#}3344 {#code_begin|test_err|test_misaligned_pointer|expected type#}
3345const std = @import("std");3345const std = @import("std");
3346const expect = std.testing.expect;3346const expect = std.testing.expect;
33473347
...@@ -3372,7 +3372,7 @@ fn bar(x: *const u3) u3 {...@@ -3372,7 +3372,7 @@ fn bar(x: *const u3) u3 {
3372 <p>3372 <p>
3373 Pointers to non-ABI-aligned fields share the same address as the other fields within their host integer:3373 Pointers to non-ABI-aligned fields share the same address as the other fields within their host integer:
3374 </p>3374 </p>
3375 {#code_begin|test|packed_struct_field_addrs#}3375 {#code_begin|test|test_packed_struct_field_address#}
3376const std = @import("std");3376const std = @import("std");
3377const expect = std.testing.expect;3377const expect = std.testing.expect;
33783378
...@@ -3422,7 +3422,7 @@ test "pointer to non-bit-aligned field" {...@@ -3422,7 +3422,7 @@ test "pointer to non-bit-aligned field" {
3422 Packed structs have the same alignment as their backing integer, however, overaligned3422 Packed structs have the same alignment as their backing integer, however, overaligned
3423 pointers to packed structs can override this:3423 pointers to packed structs can override this:
3424 </p>3424 </p>
3425 {#code_begin|test|overaligned_packed_struct#}3425 {#code_begin|test|test_overaligned_packed_struct#}
3426const std = @import("std");3426const std = @import("std");
3427const expect = std.testing.expect;3427const expect = std.testing.expect;
34283428
...@@ -3501,7 +3501,7 @@ fn List(comptime T: type) type {...@@ -3501,7 +3501,7 @@ fn List(comptime T: type) type {
3501 the struct literal will directly instantiate the {#link|result location|Result Location Semantics#},3501 the struct literal will directly instantiate the {#link|result location|Result Location Semantics#},
3502 with no copy:3502 with no copy:
3503 </p>3503 </p>
3504 {#code_begin|test|struct_result#}3504 {#code_begin|test|test_struct_result#}
3505const std = @import("std");3505const std = @import("std");
3506const expect = std.testing.expect;3506const expect = std.testing.expect;
35073507
...@@ -3520,7 +3520,7 @@ test "anonymous struct literal" {...@@ -3520,7 +3520,7 @@ test "anonymous struct literal" {
3520 The struct type can be inferred. Here the {#link|result location|Result Location Semantics#}3520 The struct type can be inferred. Here the {#link|result location|Result Location Semantics#}
3521 does not include a type, and so Zig infers the type:3521 does not include a type, and so Zig infers the type:
3522 </p>3522 </p>
3523 {#code_begin|test|struct_anon#}3523 {#code_begin|test|test_anonymous_struct#}
3524const std = @import("std");3524const std = @import("std");
3525const expect = std.testing.expect;3525const expect = std.testing.expect;
35263526
...@@ -3557,7 +3557,7 @@ fn dump(args: anytype) !void {...@@ -3557,7 +3557,7 @@ fn dump(args: anytype) !void {
3557 Like arrays, tuples have a .len field, can be indexed (provided the index is comptime-known)3557 Like arrays, tuples have a .len field, can be indexed (provided the index is comptime-known)
3558 and work with the ++ and ** operators. They can also be iterated over with {#link|inline for#}.3558 and work with the ++ and ** operators. They can also be iterated over with {#link|inline for#}.
3559 </p>3559 </p>
3560 {#code_begin|test|tuple#}3560 {#code_begin|test|test_tuples#}
3561const std = @import("std");3561const std = @import("std");
3562const expect = std.testing.expect;3562const expect = std.testing.expect;
35633563
...@@ -3582,7 +3582,7 @@ test "tuple" {...@@ -3582,7 +3582,7 @@ test "tuple" {
3582 {#see_also|comptime|@fieldParentPtr#}3582 {#see_also|comptime|@fieldParentPtr#}
3583 {#header_close#}3583 {#header_close#}
3584 {#header_open|enum#}3584 {#header_open|enum#}
3585 {#code_begin|test|enums#}3585 {#code_begin|test|test_enums#}
3586const expect = @import("std").testing.expect;3586const expect = @import("std").testing.expect;
3587const mem = @import("std").mem;3587const mem = @import("std").mem;
35883588
...@@ -3700,7 +3700,7 @@ test "@tagName" {...@@ -3700,7 +3700,7 @@ test "@tagName" {
3700 <p>3700 <p>
3701 By default, enums are not guaranteed to be compatible with the C ABI:3701 By default, enums are not guaranteed to be compatible with the C ABI:
3702 </p>3702 </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'#}
3704const Foo = enum { a, b, c };3704const Foo = enum { a, b, c };
3705export fn entry(foo: Foo) void { _ = foo; }3705export fn entry(foo: Foo) void { _ = foo; }
3706 {#code_end#}3706 {#code_end#}
...@@ -3708,7 +3708,7 @@ export fn entry(foo: Foo) void { _ = foo; }...@@ -3708,7 +3708,7 @@ export fn entry(foo: Foo) void { _ = foo; }
3708 For a C-ABI-compatible enum, provide an explicit tag type to3708 For a C-ABI-compatible enum, provide an explicit tag type to
3709 the enum:3709 the enum:
3710 </p>3710 </p>
3711 {#code_begin|obj#}3711 {#code_begin|obj|enum_export#}
3712const Foo = enum(c_int) { a, b, c };3712const Foo = enum(c_int) { a, b, c };
3713export fn entry(foo: Foo) void { _ = foo; }3713export fn entry(foo: Foo) void { _ = foo; }
3714 {#code_end#}3714 {#code_end#}
...@@ -3801,7 +3801,7 @@ test "switch on non-exhaustive enum" {...@@ -3801,7 +3801,7 @@ test "switch on non-exhaustive enum" {
3801 {#link|Accessing the non-active field|Wrong Union Field Access#} is3801 {#link|Accessing the non-active field|Wrong Union Field Access#} is
3802 safety-checked {#link|Undefined Behavior#}:3802 safety-checked {#link|Undefined Behavior#}:
3803 </p>3803 </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#}
3805const Payload = union {3805const Payload = union {
3806 int: i64,3806 int: i64,
3807 float: f64,3807 float: f64,
...@@ -3963,7 +3963,7 @@ test "@tagName" {...@@ -3963,7 +3963,7 @@ test "@tagName" {
3963 {#header_open|Anonymous Union Literals#}3963 {#header_open|Anonymous Union Literals#}
3964 <p>{#link|Anonymous Struct Literals#} syntax can be used to initialize unions without specifying3964 <p>{#link|Anonymous Struct Literals#} syntax can be used to initialize unions without specifying
3965 the type:</p>3965 the type:</p>
3966 {#code_begin|test|anon_union#}3966 {#code_begin|test|test_anonymous_union#}
3967const std = @import("std");3967const std = @import("std");
3968const expect = std.testing.expect;3968const expect = std.testing.expect;
39693969
...@@ -3997,7 +3997,7 @@ fn makeNumber() Number {...@@ -3997,7 +3997,7 @@ fn makeNumber() Number {
3997 This is typically used for type safety when interacting with C code that does not expose struct details.3997 This is typically used for type safety when interacting with C code that does not expose struct details.
3998 Example:3998 Example:
3999 </p>3999 </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'#}
4001const Derp = opaque {};4001const Derp = opaque {};
4002const Wat = opaque {};4002const Wat = opaque {};
40034003
...@@ -4016,7 +4016,7 @@ test "call foo" {...@@ -4016,7 +4016,7 @@ test "call foo" {
4016 <p>4016 <p>
4017 Blocks are used to limit the scope of variable declarations:4017 Blocks are used to limit the scope of variable declarations:
4018 </p>4018 </p>
4019 {#code_begin|test_err|use of undeclared identifier 'x'#}4019 {#code_begin|test_err|test_blocks|use of undeclared identifier 'x'#}
4020test "access variable after block scope" {4020test "access variable after block scope" {
4021 {4021 {
4022 var x: i32 = 1;4022 var x: i32 = 1;
...@@ -4048,7 +4048,7 @@ test "labeled break from labeled block expression" {...@@ -4048,7 +4048,7 @@ test "labeled break from labeled block expression" {
40484048
4049 {#header_open|Shadowing#}4049 {#header_open|Shadowing#}
4050 <p>{#link|Identifiers#} are never allowed to "hide" other identifiers by using the same name:</p>4050 <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#}
4052const pi = 3.14;4052const pi = 3.14;
40534053
4054test "inside test block" {4054test "inside test block" {
...@@ -4079,7 +4079,7 @@ test "separate scopes" {...@@ -4079,7 +4079,7 @@ test "separate scopes" {
40794079
4080 {#header_open|Empty Blocks#}4080 {#header_open|Empty Blocks#}
4081 <p>An empty block is equivalent to {#syntax#}void{}{#endsyntax#}:</p>4081 <p>An empty block is equivalent to {#syntax#}void{}{#endsyntax#}:</p>
4082 {#code_begin|test|empty_block#}4082 {#code_begin|test|test_empty_block#}
4083const std = @import("std");4083const std = @import("std");
4084const expect = std.testing.expect;4084const expect = std.testing.expect;
40854085
...@@ -4095,7 +4095,7 @@ test {...@@ -4095,7 +4095,7 @@ test {
4095 {#header_close#}4095 {#header_close#}
40964096
4097 {#header_open|switch#}4097 {#header_open|switch#}
4098 {#code_begin|test|switch#}4098 {#code_begin|test|test_switch#}
4099const std = @import("std");4099const std = @import("std");
4100const builtin = @import("builtin");4100const builtin = @import("builtin");
4101const expect = std.testing.expect;4101const expect = std.testing.expect;
...@@ -4212,7 +4212,7 @@ test "switch on tagged union" {...@@ -4212,7 +4212,7 @@ test "switch on tagged union" {
4212 When a {#syntax#}switch{#endsyntax#} expression does not have an {#syntax#}else{#endsyntax#} clause,4212 When a {#syntax#}switch{#endsyntax#} expression does not have an {#syntax#}else{#endsyntax#} clause,
4213 it must exhaustively list all the possible values. Failure to do so is a compile error:4213 it must exhaustively list all the possible values. Failure to do so is a compile error:
4214 </p>4214 </p>
4215 {#code_begin|test_err|unhandled enumeration value#}4215 {#code_begin|test_err|test_unhandled_enumeration_value|unhandled enumeration value#}
4216const Color = enum {4216const Color = enum {
4217 auto,4217 auto,
4218 off,4218 off,
...@@ -4390,7 +4390,7 @@ test "test" {...@@ -4390,7 +4390,7 @@ test "test" {
4390 A while loop is used to repeatedly execute an expression until4390 A while loop is used to repeatedly execute an expression until
4391 some condition is no longer true.4391 some condition is no longer true.
4392 </p>4392 </p>
4393 {#code_begin|test|while#}4393 {#code_begin|test|test_while#}
4394const expect = @import("std").testing.expect;4394const expect = @import("std").testing.expect;
43954395
4396test "while basic" {4396test "while basic" {
...@@ -4404,7 +4404,7 @@ test "while basic" {...@@ -4404,7 +4404,7 @@ test "while basic" {
4404 <p>4404 <p>
4405 Use {#syntax#}break{#endsyntax#} to exit a while loop early.4405 Use {#syntax#}break{#endsyntax#} to exit a while loop early.
4406 </p>4406 </p>
4407 {#code_begin|test|while#}4407 {#code_begin|test|test_while_break#}
4408const expect = @import("std").testing.expect;4408const expect = @import("std").testing.expect;
44094409
4410test "while break" {4410test "while break" {
...@@ -4420,7 +4420,7 @@ test "while break" {...@@ -4420,7 +4420,7 @@ test "while break" {
4420 <p>4420 <p>
4421 Use {#syntax#}continue{#endsyntax#} to jump back to the beginning of the loop.4421 Use {#syntax#}continue{#endsyntax#} to jump back to the beginning of the loop.
4422 </p>4422 </p>
4423 {#code_begin|test|while#}4423 {#code_begin|test|test_while_continue#}
4424const expect = @import("std").testing.expect;4424const expect = @import("std").testing.expect;
44254425
4426test "while continue" {4426test "while continue" {
...@@ -4438,7 +4438,7 @@ test "while continue" {...@@ -4438,7 +4438,7 @@ test "while continue" {
4438 While loops support a continue expression which is executed when the loop4438 While loops support a continue expression which is executed when the loop
4439 is continued. The {#syntax#}continue{#endsyntax#} keyword respects this expression.4439 is continued. The {#syntax#}continue{#endsyntax#} keyword respects this expression.
4440 </p>4440 </p>
4441 {#code_begin|test|while#}4441 {#code_begin|test|test_while_continue_expression#}
4442const expect = @import("std").testing.expect;4442const expect = @import("std").testing.expect;
44434443
4444test "while loop continue expression" {4444test "while loop continue expression" {
...@@ -4467,7 +4467,7 @@ test "while loop continue expression, more complicated" {...@@ -4467,7 +4467,7 @@ test "while loop continue expression, more complicated" {
4467 When you {#syntax#}break{#endsyntax#} from a while loop, the {#syntax#}else{#endsyntax#} branch is not4467 When you {#syntax#}break{#endsyntax#} from a while loop, the {#syntax#}else{#endsyntax#} branch is not
4468 evaluated.4468 evaluated.
4469 </p>4469 </p>
4470 {#code_begin|test|while#}4470 {#code_begin|test|test_while_else#}
4471const expect = @import("std").testing.expect;4471const expect = @import("std").testing.expect;
44724472
4473test "while else" {4473test "while else" {
...@@ -4487,7 +4487,7 @@ fn rangeHasNumber(begin: usize, end: usize, number: usize) bool {...@@ -4487,7 +4487,7 @@ fn rangeHasNumber(begin: usize, end: usize, number: usize) bool {
4487 {#header_open|Labeled while#}4487 {#header_open|Labeled while#}
4488 <p>When a {#syntax#}while{#endsyntax#} loop is labeled, it can be referenced from a {#syntax#}break{#endsyntax#}4488 <p>When a {#syntax#}while{#endsyntax#} loop is labeled, it can be referenced from a {#syntax#}break{#endsyntax#}
4489 or {#syntax#}continue{#endsyntax#} from within a nested loop:</p>4489 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#}
4491test "nested break" {4491test "nested break" {
4492 outer: while (true) {4492 outer: while (true) {
4493 while (true) {4493 while (true) {
...@@ -4520,7 +4520,7 @@ test "nested continue" {...@@ -4520,7 +4520,7 @@ test "nested continue" {
4520 The {#syntax#}else{#endsyntax#} branch is allowed on optional iteration. In this case, it will4520 The {#syntax#}else{#endsyntax#} branch is allowed on optional iteration. In this case, it will
4521 be executed on the first null value encountered.4521 be executed on the first null value encountered.
4522 </p>4522 </p>
4523 {#code_begin|test|while#}4523 {#code_begin|test|test_while_null_capture#}
4524const expect = @import("std").testing.expect;4524const expect = @import("std").testing.expect;
45254525
4526test "while null capture" {4526test "while null capture" {
...@@ -4562,7 +4562,7 @@ fn eventuallyNullSequence() ?u32 {...@@ -4562,7 +4562,7 @@ fn eventuallyNullSequence() ?u32 {
4562 When the {#syntax#}else |x|{#endsyntax#} syntax is present on a {#syntax#}while{#endsyntax#} expression,4562 When the {#syntax#}else |x|{#endsyntax#} syntax is present on a {#syntax#}while{#endsyntax#} expression,
4563 the while condition must have an {#link|Error Union Type#}.4563 the while condition must have an {#link|Error Union Type#}.
4564 </p>4564 </p>
4565 {#code_begin|test|while#}4565 {#code_begin|test|test_while_error_capture#}
4566const expect = @import("std").testing.expect;4566const expect = @import("std").testing.expect;
45674567
4568test "while error union capture" {4568test "while error union capture" {
...@@ -4627,7 +4627,7 @@ fn typeNameLength(comptime T: type) usize {...@@ -4627,7 +4627,7 @@ fn typeNameLength(comptime T: type) usize {
4627 {#see_also|if|Optionals|Errors|comptime|unreachable#}4627 {#see_also|if|Optionals|Errors|comptime|unreachable#}
4628 {#header_close#}4628 {#header_close#}
4629 {#header_open|for#}4629 {#header_open|for#}
4630 {#code_begin|test|for#}4630 {#code_begin|test|test_for#}
4631const expect = @import("std").testing.expect;4631const expect = @import("std").testing.expect;
46324632
4633test "for basics" {4633test "for basics" {
...@@ -4695,7 +4695,7 @@ test "for else" {...@@ -4695,7 +4695,7 @@ test "for else" {
4695 {#header_open|Labeled for#}4695 {#header_open|Labeled for#}
4696 <p>When a {#syntax#}for{#endsyntax#} loop is labeled, it can be referenced from a {#syntax#}break{#endsyntax#}4696 <p>When a {#syntax#}for{#endsyntax#} loop is labeled, it can be referenced from a {#syntax#}break{#endsyntax#}
4697 or {#syntax#}continue{#endsyntax#} from within a nested loop:</p>4697 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#}
4699const std = @import("std");4699const std = @import("std");
4700const expect = std.testing.expect;4700const expect = std.testing.expect;
47014701
...@@ -4731,7 +4731,7 @@ test "nested continue" {...@@ -4731,7 +4731,7 @@ test "nested continue" {
4731 The capture value and iterator value of inlined for loops are4731 The capture value and iterator value of inlined for loops are
4732 compile-time known.4732 compile-time known.
4733 </p>4733 </p>
4734 {#code_begin|test|test_inline_loop#}4734 {#code_begin|test|test_inline_for#}
4735const expect = @import("std").testing.expect;4735const expect = @import("std").testing.expect;
47364736
4737test "inline for loop" {4737test "inline for loop" {
...@@ -4766,7 +4766,7 @@ fn typeNameLength(comptime T: type) usize {...@@ -4766,7 +4766,7 @@ fn typeNameLength(comptime T: type) usize {
4766 {#see_also|while|comptime|Arrays|Slices#}4766 {#see_also|while|comptime|Arrays|Slices#}
4767 {#header_close#}4767 {#header_close#}
4768 {#header_open|if#}4768 {#header_open|if#}
4769 {#code_begin|test|if#}4769 {#code_begin|test|test_if#}
4770// If expressions have three uses, corresponding to the three types:4770// If expressions have three uses, corresponding to the three types:
4771// * bool4771// * bool
4772// * ?T4772// * ?T
...@@ -4927,7 +4927,7 @@ test "if error union with optional" {...@@ -4927,7 +4927,7 @@ test "if error union with optional" {
4927 {#see_also|Optionals|Errors#}4927 {#see_also|Optionals|Errors#}
4928 {#header_close#}4928 {#header_close#}
4929 {#header_open|defer#}4929 {#header_open|defer#}
4930 {#code_begin|test|defer#}4930 {#code_begin|test|test_defer#}
4931const std = @import("std");4931const std = @import("std");
4932const expect = std.testing.expect;4932const expect = std.testing.expect;
4933const print = std.debug.print;4933const print = std.debug.print;
...@@ -4973,7 +4973,7 @@ test "defer unwinding" {...@@ -4973,7 +4973,7 @@ test "defer unwinding" {
4973 deferUnwindExample();4973 deferUnwindExample();
4974}4974}
4975 {#code_end#}4975 {#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#}
4977// Inside a defer expression the return statement is not allowed.4977// Inside a defer expression the return statement is not allowed.
4978fn deferInvalidExample() !void {4978fn deferInvalidExample() !void {
4979 defer {4979 defer {
...@@ -4983,7 +4983,7 @@ fn deferInvalidExample() !void {...@@ -4983,7 +4983,7 @@ fn deferInvalidExample() !void {
4983 return error.DeferError;4983 return error.DeferError;
4984}4984}
4985 {#code_end#}4985 {#code_end#}
4986 {#code_begin|test|errdefer#}4986 {#code_begin|test|test_errdefer#}
4987const std = @import("std");4987const std = @import("std");
4988const print = std.debug.print;4988const print = std.debug.print;
49894989
...@@ -5052,7 +5052,7 @@ test "basic math" {...@@ -5052,7 +5052,7 @@ test "basic math" {
5052}5052}
5053 {#code_end#}5053 {#code_end#}
5054 <p>In fact, this is how {#syntax#}std.debug.assert{#endsyntax#} is implemented:</p>5054 <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#}
5056// This is how std.debug.assert is implemented5056// This is how std.debug.assert is implemented
5057fn assert(ok: bool) void {5057fn assert(ok: bool) void {
5058 if (!ok) unreachable; // assertion failure5058 if (!ok) unreachable; // assertion failure
...@@ -5065,7 +5065,7 @@ test "this will fail" {...@@ -5065,7 +5065,7 @@ test "this will fail" {
5065 {#code_end#}5065 {#code_end#}
5066 {#header_close#}5066 {#header_close#}
5067 {#header_open|At Compile-Time#}5067 {#header_open|At Compile-Time#}
5068 {#code_begin|test_err|unreachable code#}5068 {#code_begin|test_err|test_comptime_unreachable|unreachable code#}
5069const assert = @import("std").debug.assert;5069const assert = @import("std").debug.assert;
50705070
5071test "type of unreachable" {5071test "type of unreachable" {
...@@ -5107,7 +5107,7 @@ test "noreturn" {...@@ -5107,7 +5107,7 @@ test "noreturn" {
5107}5107}
5108 {#code_end#}5108 {#code_end#}
5109 <p>Another use case for {#syntax#}noreturn{#endsyntax#} is the {#syntax#}exit{#endsyntax#} function:</p>5109 <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#}
5111 {#target_windows#}5111 {#target_windows#}
5112const std = @import("std");5112const std = @import("std");
5113const builtin = @import("builtin");5113const builtin = @import("builtin");
...@@ -5130,7 +5130,7 @@ fn bar() anyerror!u32 {...@@ -5130,7 +5130,7 @@ fn bar() anyerror!u32 {
5130 {#header_close#}5130 {#header_close#}
51315131
5132 {#header_open|Functions#}5132 {#header_open|Functions#}
5133 {#code_begin|test|functions#}5133 {#code_begin|test|test_functions#}
5134const std = @import("std");5134const std = @import("std");
5135const builtin = @import("builtin");5135const builtin = @import("builtin");
5136const native_arch = builtin.cpu.arch;5136const native_arch = builtin.cpu.arch;
...@@ -5206,7 +5206,7 @@ test "function" {...@@ -5206,7 +5206,7 @@ test "function" {
5206 as parameters, Zig may choose to copy and pass by value, or pass by reference, whichever way5206 as parameters, Zig may choose to copy and pass by value, or pass by reference, whichever way
5207 Zig decides will be faster. This is made possible, in part, by the fact that parameters are immutable.5207 Zig decides will be faster. This is made possible, in part, by the fact that parameters are immutable.
5208 </p>5208 </p>
5209 {#code_begin|test|pass_by_reference_or_value#}5209 {#code_begin|test|test_pass_by_reference_or_value#}
5210const Point = struct {5210const Point = struct {
5211 x: i32,5211 x: i32,
5212 y: i32,5212 y: i32,
...@@ -5283,7 +5283,7 @@ test "fn reflection" {...@@ -5283,7 +5283,7 @@ test "fn reflection" {
5283 <p>5283 <p>
5284 You can {#link|coerce|Type Coercion#} an error from a subset to a superset:5284 You can {#link|coerce|Type Coercion#} an error from a subset to a superset:
5285 </p>5285 </p>
5286 {#code_begin|test|coercing_subset_to_superset#}5286 {#code_begin|test|test_coerce_error_subset_to_superset#}
5287const std = @import("std");5287const std = @import("std");
52885288
5289const FileOpenError = error {5289const FileOpenError = error {
...@@ -5308,7 +5308,7 @@ fn foo(err: AllocationError) FileOpenError {...@@ -5308,7 +5308,7 @@ fn foo(err: AllocationError) FileOpenError {
5308 <p>5308 <p>
5309 But you cannot {#link|coerce|Type Coercion#} an error from a superset to a subset:5309 But you cannot {#link|coerce|Type Coercion#} an error from a superset to a subset:
5310 </p>5310 </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#}
5312const FileOpenError = error {5312const FileOpenError = error {
5313 AccessDenied,5313 AccessDenied,
5314 OutOfMemory,5314 OutOfMemory,
...@@ -5330,11 +5330,11 @@ fn foo(err: FileOpenError) AllocationError {...@@ -5330,11 +5330,11 @@ fn foo(err: FileOpenError) AllocationError {
5330 <p>5330 <p>
5331 There is a shortcut for declaring an error set with only 1 value, and then getting that value:5331 There is a shortcut for declaring an error set with only 1 value, and then getting that value:
5332 </p>5332 </p>
5333 {#code_begin|syntax#}5333 {#code_begin|syntax|single_value_error_set_shortcut#}
5334const err = error.FileNotFound;5334const err = error.FileNotFound;
5335 {#code_end#}5335 {#code_end#}
5336 <p>This is equivalent to:</p>5336 <p>This is equivalent to:</p>
5337 {#code_begin|syntax#}5337 {#code_begin|syntax|single_value_error_set#}
5338const err = (error {FileNotFound}).FileNotFound;5338const err = (error {FileNotFound}).FileNotFound;
5339 {#code_end#}5339 {#code_end#}
5340 <p>5340 <p>
...@@ -5431,7 +5431,7 @@ test "parse u64" {...@@ -5431,7 +5431,7 @@ test "parse u64" {
5431 </ul>5431 </ul>
5432 {#header_open|catch#}5432 {#header_open|catch#}
5433 <p>If you want to provide a default value, you can use the {#syntax#}catch{#endsyntax#} binary operator:</p>5433 <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#}
5435const parseU64 = @import("error_union_parsing_u64.zig").parseU64;5435const parseU64 = @import("error_union_parsing_u64.zig").parseU64;
54365436
5437fn doAThing(str: []u8) void {5437fn doAThing(str: []u8) void {
...@@ -5448,7 +5448,7 @@ fn doAThing(str: []u8) void {...@@ -5448,7 +5448,7 @@ fn doAThing(str: []u8) void {
5448 {#header_open|try#}5448 {#header_open|try#}
5449 <p>Let's say you wanted to return the error if you got one, otherwise continue with the5449 <p>Let's say you wanted to return the error if you got one, otherwise continue with the
5450 function logic:</p>5450 function logic:</p>
5451 {#code_begin|syntax#}5451 {#code_begin|syntax|catch_err_return#}
5452const parseU64 = @import("error_union_parsing_u64.zig").parseU64;5452const parseU64 = @import("error_union_parsing_u64.zig").parseU64;
54535453
5454fn doAThing(str: []u8) !void {5454fn doAThing(str: []u8) !void {
...@@ -5459,7 +5459,7 @@ fn doAThing(str: []u8) !void {...@@ -5459,7 +5459,7 @@ fn doAThing(str: []u8) !void {
5459 <p>5459 <p>
5460 There is a shortcut for this. The {#syntax#}try{#endsyntax#} expression:5460 There is a shortcut for this. The {#syntax#}try{#endsyntax#} expression:
5461 </p>5461 </p>
5462 {#code_begin|syntax#}5462 {#code_begin|syntax|try#}
5463const parseU64 = @import("error_union_parsing_u64.zig").parseU64;5463const parseU64 = @import("error_union_parsing_u64.zig").parseU64;
54645464
5465fn doAThing(str: []u8) !void {5465fn doAThing(str: []u8) !void {
...@@ -5543,7 +5543,7 @@ fn createFoo(param: i32) !Foo {...@@ -5543,7 +5543,7 @@ fn createFoo(param: i32) !Foo {
5543 It should be noted that {#syntax#}errdefer{#endsyntax#} statements only last until the end of the block5543 It should be noted that {#syntax#}errdefer{#endsyntax#} statements only last until the end of the block
5544 they are written in, and therefore are not run if an error is returned outside of that block:5544 they are written in, and therefore are not run if an error is returned outside of that block:
5545 </p>5545 </p>
5546 {#code_begin|test_err|1 tests leaked memory#}5546 {#code_begin|test_err|test_errdefer_slip_ups|1 tests leaked memory#}
5547const std = @import("std");5547const std = @import("std");
5548const Allocator = std.mem.Allocator;5548const Allocator = std.mem.Allocator;
55495549
...@@ -5635,7 +5635,7 @@ test "createFoo" {...@@ -5635,7 +5635,7 @@ test "createFoo" {
5635 The fact that errdefers only last for the block they are declared in is5635 The fact that errdefers only last for the block they are declared in is
5636 especially important when using loops:5636 especially important when using loops:
5637 </p>5637 </p>
5638 {#code_begin|test_err|3 errors were logged#}5638 {#code_begin|test_err|test_errdefer_loop_leak|3 errors were logged#}
5639const std = @import("std");5639const std = @import("std");
5640const Allocator = std.mem.Allocator;5640const Allocator = std.mem.Allocator;
56415641
...@@ -5799,7 +5799,7 @@ test "merge error sets" {...@@ -5799,7 +5799,7 @@ test "merge error sets" {
5799 Because many functions in Zig return a possible error, Zig supports inferring the error set.5799 Because many functions in Zig return a possible error, Zig supports inferring the error set.
5800 To infer the error set for a function, prepend the {#syntax#}!{#endsyntax#} operator to the function’s return type, like {#syntax#}!T{#endsyntax#}:5800 To infer the error set for a function, prepend the {#syntax#}!{#endsyntax#} operator to the function’s return type, like {#syntax#}!T{#endsyntax#}:
5801 </p>5801 </p>
5802{#code_begin|test|inferred_error_sets#}5802 {#code_begin|test|test_inferred_error_sets#}
5803// With an inferred error set5803// With an inferred error set
5804pub fn add_inferred(comptime T: type, a: T, b: T) !T {5804pub fn add_inferred(comptime T: type, a: T, b: T) !T {
5805 const ov = @addWithOverflow(a, b);5805 const ov = @addWithOverflow(a, b);
...@@ -5825,7 +5825,7 @@ test "inferred error set" {...@@ -5825,7 +5825,7 @@ test "inferred error set" {
5825 error.Overflow => {}, // ok5825 error.Overflow => {}, // ok
5826 }5826 }
5827}5827}
5828{#code_end#}5828 {#code_end#}
5829 <p>5829 <p>
5830 When a function has an inferred error set, that function becomes generic and thus it becomes5830 When a function has an inferred error set, that function becomes generic and thus it becomes
5831 trickier to do certain things with it, such as obtain a function pointer, or have an error5831 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" {...@@ -5845,7 +5845,7 @@ test "inferred error set" {
5845 <p>5845 <p>
5846 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.5846 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.
5847 </p>5847 </p>
5848 {#code_begin|exe_err#}5848 {#code_begin|exe_err|error_return_trace#}
5849pub fn main() !void {5849pub fn main() !void {
5850 try foo(12);5850 try foo(12);
5851}5851}
...@@ -5894,7 +5894,7 @@ fn bang2() !void {...@@ -5894,7 +5894,7 @@ fn bang2() !void {
5894 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,5894 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,
5895 and then returns another one, from the switch statement. Error Return Traces make this clear, whereas a stack trace would look like this:5895 and then returns another one, from the switch statement. Error Return Traces make this clear, whereas a stack trace would look like this:
5896 </p>5896 </p>
5897 {#code_begin|exe_err#}5897 {#code_begin|exe_err|stack_trace#}
5898pub fn main() void {5898pub fn main() void {
5899 foo(12);5899 foo(12);
5900}5900}
...@@ -6016,7 +6016,7 @@ fn __zig_return_error(stack_trace: *StackTrace) void {...@@ -6016,7 +6016,7 @@ fn __zig_return_error(stack_trace: *StackTrace) void {
6016 The question mark symbolizes the optional type. You can convert a type to an optional6016 The question mark symbolizes the optional type. You can convert a type to an optional
6017 type by putting a question mark in front of it, like this:6017 type by putting a question mark in front of it, like this:
6018 </p>6018 </p>
6019 {#code_begin|syntax#}6019 {#code_begin|syntax|optional_integer#}
6020// normal integer6020// normal integer
6021const normal_int: i32 = 1234;6021const normal_int: i32 = 1234;
60226022
...@@ -6137,7 +6137,7 @@ test "optional type" {...@@ -6137,7 +6137,7 @@ test "optional type" {
6137 Just like {#link|undefined#}, {#syntax#}null{#endsyntax#} has its own type, and the only way to use it is to6137 Just like {#link|undefined#}, {#syntax#}null{#endsyntax#} has its own type, and the only way to use it is to
6138 cast it to a different type:6138 cast it to a different type:
6139 </p>6139 </p>
6140 {#code_begin|syntax#}6140 {#code_begin|syntax|null#}
6141const optional_value: ?i32 = null;6141const optional_value: ?i32 = null;
6142 {#code_end#}6142 {#code_end#}
6143 {#header_close#}6143 {#header_close#}
...@@ -6176,7 +6176,7 @@ test "optional pointers" {...@@ -6176,7 +6176,7 @@ test "optional pointers" {
6176 <p>6176 <p>
6177 Type coercion occurs when one type is expected, but different type is provided:6177 Type coercion occurs when one type is expected, but different type is provided:
6178 </p>6178 </p>
6179 {#code_begin|test|type_coercion#}6179 {#code_begin|test|test_type_coercion#}
6180test "type coercion - variable declaration" {6180test "type coercion - variable declaration" {
6181 var a: u8 = 1;6181 var a: u8 = 1;
6182 var b: u16 = a;6182 var b: u16 = a;
...@@ -6216,7 +6216,7 @@ test "type coercion - @as builtin" {...@@ -6216,7 +6216,7 @@ test "type coercion - @as builtin" {
6216 <p>6216 <p>
6217 These casts are no-ops at runtime since the value representation does not change.6217 These casts are no-ops at runtime since the value representation does not change.
6218 </p>6218 </p>
6219 {#code_begin|test|no_op_casts#}6219 {#code_begin|test|test_no_op_casts#}
6220test "type coercion - const qualification" {6220test "type coercion - const qualification" {
6221 var a: i32 = 1;6221 var a: i32 = 1;
6222 var b: *i32 = &a;6222 var b: *i32 = &a;
...@@ -6228,7 +6228,7 @@ fn foo(_: *const i32) void {}...@@ -6228,7 +6228,7 @@ fn foo(_: *const i32) void {}
6228 <p>6228 <p>
6229 In addition, pointers coerce to const optional pointers:6229 In addition, pointers coerce to const optional pointers:
6230 </p>6230 </p>
6231 {#code_begin|test|pointer_coerce_const_optional#}6231 {#code_begin|test|test_pointer_coerce_const_optional#}
6232const std = @import("std");6232const std = @import("std");
6233const expect = std.testing.expect;6233const expect = std.testing.expect;
6234const mem = std.mem;6234const mem = std.mem;
...@@ -6285,7 +6285,7 @@ test "float widening" {...@@ -6285,7 +6285,7 @@ test "float widening" {
6285 <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>6285 <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>
6286 <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>6286 <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>
6287 </ul>6287 </ul>
6288 {#code_begin|test_err#}6288 {#code_begin|test_err|test_ambiguous_coercion#}
6289// Compile time coercion of float to int6289// Compile time coercion of float to int
6290test "implicit cast to comptime_int" {6290test "implicit cast to comptime_int" {
6291 var f: f32 = 54.0 / 5;6291 var f: f32 = 54.0 / 5;
...@@ -6294,7 +6294,7 @@ test "implicit cast to comptime_int" {...@@ -6294,7 +6294,7 @@ test "implicit cast to comptime_int" {
6294 {#code_end#}6294 {#code_end#}
6295 {#header_close#}6295 {#header_close#}
6296 {#header_open|Type Coercion: Slices, Arrays and Pointers#}6296 {#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#}
6298const std = @import("std");6298const std = @import("std");
6299const expect = std.testing.expect;6299const expect = std.testing.expect;
63006300
...@@ -6522,7 +6522,7 @@ test "coercion from homogenous tuple to array" {...@@ -6522,7 +6522,7 @@ test "coercion from homogenous tuple to array" {
6522 This kind of type resolution chooses a type that all peer types can coerce into. Here are6522 This kind of type resolution chooses a type that all peer types can coerce into. Here are
6523 some examples:6523 some examples:
6524 </p>6524 </p>
6525 {#code_begin|test|peer_type_resolution#}6525 {#code_begin|test|test_peer_type_resolution#}
6526const std = @import("std");6526const std = @import("std");
6527const expect = std.testing.expect;6527const expect = std.testing.expect;
6528const mem = std.mem;6528const mem = std.mem;
...@@ -6634,7 +6634,7 @@ test "peer type resolution: *const T and ?*T" {...@@ -6634,7 +6634,7 @@ test "peer type resolution: *const T and ?*T" {
6634 require 0 bits to represent. Code that makes use of these types is6634 require 0 bits to represent. Code that makes use of these types is
6635 not included in the final generated code:6635 not included in the final generated code:
6636 </p>6636 </p>
6637 {#code_begin|syntax#}6637 {#code_begin|syntax|zero_bit_types#}
6638export fn entry() void {6638export fn entry() void {
6639 var x: void = {};6639 var x: void = {};
6640 var y: void = {};6640 var y: void = {};
...@@ -6657,7 +6657,7 @@ export fn entry() void {...@@ -6657,7 +6657,7 @@ export fn entry() void {
6657 {#syntax#}Map(Key, Value){#endsyntax#}, one can pass {#syntax#}void{#endsyntax#} for the {#syntax#}Value{#endsyntax#}6657 {#syntax#}Map(Key, Value){#endsyntax#}, one can pass {#syntax#}void{#endsyntax#} for the {#syntax#}Value{#endsyntax#}
6658 type to make it into a {#syntax#}Set{#endsyntax#}:6658 type to make it into a {#syntax#}Set{#endsyntax#}:
6659 </p>6659 </p>
6660 {#code_begin|test|void_in_hashmap#}6660 {#code_begin|test|test_void_in_hashmap#}
6661const std = @import("std");6661const std = @import("std");
6662const expect = std.testing.expect;6662const expect = std.testing.expect;
66636663
...@@ -6687,7 +6687,7 @@ test "turn HashMap into a set with void" {...@@ -6687,7 +6687,7 @@ test "turn HashMap into a set with void" {
6687 <p>6687 <p>
6688 Expressions of type {#syntax#}void{#endsyntax#} are the only ones whose value can be ignored. For example:6688 Expressions of type {#syntax#}void{#endsyntax#} are the only ones whose value can be ignored. For example:
6689 </p>6689 </p>
6690 {#code_begin|test_err|ignored#}6690 {#code_begin|test_err|test_expression_ignored|ignored#}
6691test "ignoring expression value" {6691test "ignoring expression value" {
6692 foo();6692 foo();
6693}6693}
...@@ -6697,7 +6697,7 @@ fn foo() i32 {...@@ -6697,7 +6697,7 @@ fn foo() i32 {
6697}6697}
6698 {#code_end#}6698 {#code_end#}
6699 <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>6699 <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#}
6701test "void is ignored" {6701test "void is ignored" {
6702 returnsVoid();6702 returnsVoid();
6703}6703}
...@@ -6727,7 +6727,7 @@ fn foo() i32 {...@@ -6727,7 +6727,7 @@ fn foo() i32 {
6727 declarations of the operand, which must be a {#link|struct#}, {#link|union#}, {#link|enum#},6727 declarations of the operand, which must be a {#link|struct#}, {#link|union#}, {#link|enum#},
6728 or {#link|opaque#}, into the namespace:6728 or {#link|opaque#}, into the namespace:
6729 </p>6729 </p>
6730 {#code_begin|test|usingnamespace#}6730 {#code_begin|test|test_usingnamespace#}
6731test "using std namespace" {6731test "using std namespace" {
6732 const S = struct {6732 const S = struct {
6733 usingnamespace @import("std");6733 usingnamespace @import("std");
...@@ -6769,7 +6769,7 @@ pub usingnamespace @cImport({...@@ -6769,7 +6769,7 @@ pub usingnamespace @cImport({
6769 <p>6769 <p>
6770 Compile-time parameters is how Zig implements generics. It is compile-time duck typing.6770 Compile-time parameters is how Zig implements generics. It is compile-time duck typing.
6771 </p>6771 </p>
6772 {#code_begin|syntax#}6772 {#code_begin|syntax|compile-time_duck_typing#}
6773fn max(comptime T: type, a: T, b: T) T {6773fn max(comptime T: type, a: T, b: T) T {
6774 return if (a > b) a else b;6774 return if (a > b) a else b;
6775}6775}
...@@ -6795,7 +6795,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {...@@ -6795,7 +6795,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
6795 <p>6795 <p>
6796 For example, if we were to introduce another function to the above snippet:6796 For example, if we were to introduce another function to the above snippet:
6797 </p>6797 </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#}
6799fn max(comptime T: type, a: T, b: T) T {6799fn max(comptime T: type, a: T, b: T) T {
6800 return if (a > b) a else b;6800 return if (a > b) a else b;
6801}6801}
...@@ -6821,7 +6821,7 @@ fn foo(condition: bool) void {...@@ -6821,7 +6821,7 @@ fn foo(condition: bool) void {
6821 <p>6821 <p>
6822 For example:6822 For example:
6823 </p>6823 </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'#}
6825fn max(comptime T: type, a: T, b: T) T {6825fn max(comptime T: type, a: T, b: T) T {
6826 return if (a > b) a else b;6826 return if (a > b) a else b;
6827}6827}
...@@ -6834,7 +6834,7 @@ test "try to compare bools" {...@@ -6834,7 +6834,7 @@ test "try to compare bools" {
6834 value is known at compile-time. This means that we actually could make this work for the bool type6834 value is known at compile-time. This means that we actually could make this work for the bool type
6835 if we wanted to:6835 if we wanted to:
6836 </p>6836 </p>
6837 {#code_begin|test|comptime_max_with_bool#}6837 {#code_begin|test|test_comptime_max_with_bool#}
6838fn max(comptime T: type, a: T, b: T) T {6838fn max(comptime T: type, a: T, b: T) T {
6839 if (T == bool) {6839 if (T == bool) {
6840 return a or b;6840 return a or b;
...@@ -6857,7 +6857,7 @@ test "try to compare bools" {...@@ -6857,7 +6857,7 @@ test "try to compare bools" {
6857 This means that the actual function generated for {#syntax#}max{#endsyntax#} in this situation looks like6857 This means that the actual function generated for {#syntax#}max{#endsyntax#} in this situation looks like
6858 this:6858 this:
6859 </p>6859 </p>
6860 {#code_begin|syntax#}6860 {#code_begin|syntax|compiler_generated_function#}
6861fn max(a: bool, b: bool) bool {6861fn max(a: bool, b: bool) bool {
6862 return a or b;6862 return a or b;
6863}6863}
...@@ -6884,7 +6884,7 @@ fn max(a: bool, b: bool) bool {...@@ -6884,7 +6884,7 @@ fn max(a: bool, b: bool) bool {
6884 <p>6884 <p>
6885 For example:6885 For example:
6886 </p>6886 </p>
6887 {#code_begin|test|comptime_vars#}6887 {#code_begin|test|test_comptime_evaluation#}
6888const expect = @import("std").testing.expect;6888const expect = @import("std").testing.expect;
68896889
6890const CmdFn = struct {6890const CmdFn = struct {
...@@ -6966,7 +6966,7 @@ fn performFn(start_value: i32) i32 {...@@ -6966,7 +6966,7 @@ fn performFn(start_value: i32) i32 {
6966 use a {#syntax#}comptime{#endsyntax#} expression to guarantee that the expression will be evaluated at compile-time.6966 use a {#syntax#}comptime{#endsyntax#} expression to guarantee that the expression will be evaluated at compile-time.
6967 If this cannot be accomplished, the compiler will emit an error. For example:6967 If this cannot be accomplished, the compiler will emit an error. For example:
6968 </p>6968 </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#}
6970extern fn exit() noreturn;6970extern fn exit() noreturn;
69716971
6972test "foo" {6972test "foo" {
...@@ -6997,7 +6997,7 @@ test "foo" {...@@ -6997,7 +6997,7 @@ test "foo" {
6997 <p>6997 <p>
6998 Let's look at an example:6998 Let's look at an example:
6999 </p>6999 </p>
7000 {#code_begin|test|fibonacci_recursion#}7000 {#code_begin|test|test_fibonacci_recursion#}
7001const expect = @import("std").testing.expect;7001const expect = @import("std").testing.expect;
70027002
7003fn fibonacci(index: u32) u32 {7003fn fibonacci(index: u32) u32 {
...@@ -7018,7 +7018,7 @@ test "fibonacci" {...@@ -7018,7 +7018,7 @@ test "fibonacci" {
7018 <p>7018 <p>
7019 Imagine if we had forgotten the base case of the recursive function and tried to run the tests:7019 Imagine if we had forgotten the base case of the recursive function and tried to run the tests:
7020 </p>7020 </p>
7021 {#code_begin|test_err|overflow of integer type#}7021 {#code_begin|test_err|test_fibonacci_comptime_overflow|overflow of integer type#}
7022const expect = @import("std").testing.expect;7022const expect = @import("std").testing.expect;
70237023
7024fn fibonacci(index: u32) u32 {7024fn fibonacci(index: u32) u32 {
...@@ -7041,7 +7041,7 @@ test "fibonacci" {...@@ -7041,7 +7041,7 @@ test "fibonacci" {
7041 undefined behavior, which is always a compile error if the compiler knows it happened.7041 undefined behavior, which is always a compile error if the compiler knows it happened.
7042 But what would have happened if we used a signed integer?7042 But what would have happened if we used a signed integer?
7043 </p>7043 </p>
7044 {#code_begin|syntax#}7044 {#code_begin|syntax|fibonacci_comptime_infinite_recursion#}
7045const assert = @import("std").debug.assert;7045const assert = @import("std").debug.assert;
70467046
7047fn fibonacci(index: i32) i32 {7047fn fibonacci(index: i32) i32 {
...@@ -7073,7 +7073,7 @@ test "fibonacci" {...@@ -7073,7 +7073,7 @@ test "fibonacci" {
7073 What if we fix the base case, but put the wrong value in the7073 What if we fix the base case, but put the wrong value in the
7074 {#syntax#}expect{#endsyntax#} line?7074 {#syntax#}expect{#endsyntax#} line?
7075 </p>7075 </p>
7076 {#code_begin|test_err|reached unreachable#}7076 {#code_begin|test_err|test_fibonacci_comptime_unreachable|reached unreachable#}
7077const assert = @import("std").debug.assert;7077const assert = @import("std").debug.assert;
70787078
7079fn fibonacci(index: i32) i32 {7079fn fibonacci(index: i32) i32 {
...@@ -7093,7 +7093,7 @@ test "fibonacci" {...@@ -7093,7 +7093,7 @@ test "fibonacci" {
7093 {#syntax#}comptime{#endsyntax#} expressions. This means that we can use functions to7093 {#syntax#}comptime{#endsyntax#} expressions. This means that we can use functions to
7094 initialize complex static data. For example:7094 initialize complex static data. For example:
7095 </p>7095 </p>
7096 {#code_begin|test|N_primes#}7096 {#code_begin|test|test_container-level_comptime_expressions#}
7097const first_25_primes = firstNPrimes(25);7097const first_25_primes = firstNPrimes(25);
7098const sum_of_first_25_primes = sum(&first_25_primes);7098const sum_of_first_25_primes = sum(&first_25_primes);
70997099
...@@ -7152,7 +7152,7 @@ test "variable values" {...@@ -7152,7 +7152,7 @@ test "variable values" {
7152 <p>7152 <p>
7153 Here is an example of a generic {#syntax#}List{#endsyntax#} data structure.7153 Here is an example of a generic {#syntax#}List{#endsyntax#} data structure.
7154 </p>7154 </p>
7155 {#code_begin|syntax#}7155 {#code_begin|syntax|generic_data_structure#}
7156fn List(comptime T: type) type {7156fn List(comptime T: type) type {
7157 return struct {7157 return struct {
7158 items: []T,7158 items: []T,
...@@ -7177,7 +7177,7 @@ var list = List(i32){...@@ -7177,7 +7177,7 @@ var list = List(i32){
7177 <p>7177 <p>
7178 To explicitly give a type a name, we assign it to a constant.7178 To explicitly give a type a name, we assign it to a constant.
7179 </p>7179 </p>
7180 {#code_begin|syntax#}7180 {#code_begin|syntax|anonymous_struct_name#}
7181const Node = struct {7181const Node = struct {
7182 next: ?*Node,7182 next: ?*Node,
7183 name: []const u8,7183 name: []const u8,
...@@ -7360,7 +7360,7 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void {...@@ -7360,7 +7360,7 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void {
7360 <p>7360 <p>
7361 And now, what happens if we give too many arguments to {#syntax#}print{#endsyntax#}?7361 And now, what happens if we give too many arguments to {#syntax#}print{#endsyntax#}?
7362 </p>7362 </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: {}#}
7364const print = @import("std").debug.print;7364const print = @import("std").debug.print;
73657365
7366const a_number: i32 = 1234;7366const a_number: i32 = 1234;
...@@ -7381,7 +7381,7 @@ test "print too many arguments" {...@@ -7381,7 +7381,7 @@ test "print too many arguments" {
7381 Zig doesn't care whether the format argument is a string literal,7381 Zig doesn't care whether the format argument is a string literal,
7382 only that it is a compile-time known value that can be coerced to a {#syntax#}[]const u8{#endsyntax#}:7382 only that it is a compile-time known value that can be coerced to a {#syntax#}[]const u8{#endsyntax#}:
7383 </p>7383 </p>
7384 {#code_begin|exe|print#}7384 {#code_begin|exe|print_comptime-known_format#}
7385const print = @import("std").debug.print;7385const print = @import("std").debug.print;
73867386
7387const a_number: i32 = 1234;7387const a_number: i32 = 1234;
...@@ -7410,7 +7410,7 @@ pub fn main() void {...@@ -7410,7 +7410,7 @@ pub fn main() void {
7410 can use inline assembly. Here is an example of implementing Hello, World on x86_64 Linux7410 can use inline assembly. Here is an example of implementing Hello, World on x86_64 Linux
7411 using inline assembly:7411 using inline assembly:
7412 </p>7412 </p>
7413 {#code_begin|exe#}7413 {#code_begin|exe|inline_assembly#}
7414 {#target_linux_x86_64#}7414 {#target_linux_x86_64#}
7415pub fn main() noreturn {7415pub fn main() noreturn {
7416 const msg = "hello world\n";7416 const msg = "hello world\n";
...@@ -7572,7 +7572,7 @@ volatile (...@@ -7572,7 +7572,7 @@ volatile (
7572 verbatim into one long string and assembled together. There are no template substitution rules regarding7572 verbatim into one long string and assembled together. There are no template substitution rules regarding
7573 <code>%</code> as there are in inline assembly expressions.7573 <code>%</code> as there are in inline assembly expressions.
7574 </p>7574 </p>
7575 {#code_begin|test|global-asm#}7575 {#code_begin|test|test_global_assembly#}
7576 {#target_linux_x86_64#}7576 {#target_linux_x86_64#}
7577const std = @import("std");7577const std = @import("std");
7578const expect = std.testing.expect;7578const expect = std.testing.expect;
...@@ -7845,7 +7845,7 @@ comptime {...@@ -7845,7 +7845,7 @@ comptime {
7845 <p>7845 <p>
7846 Calls a function, in the same way that invoking an expression with parentheses does:7846 Calls a function, in the same way that invoking an expression with parentheses does:
7847 </p>7847 </p>
7848 {#code_begin|test|call#}7848 {#code_begin|test|test_call_builtin#}
7849const expect = @import("std").testing.expect;7849const expect = @import("std").testing.expect;
78507850
7851test "noinline function call" {7851test "noinline function call" {
...@@ -7979,7 +7979,7 @@ pub const CallModifier = enum {...@@ -7979,7 +7979,7 @@ pub const CallModifier = enum {
7979 This function performs a strong atomic compare exchange operation. It's the equivalent of this code,7979 This function performs a strong atomic compare exchange operation. It's the equivalent of this code,
7980 except atomic:7980 except atomic:
7981 </p>7981 </p>
7982 {#code_begin|syntax#}7982 {#code_begin|syntax|not_atomic_cmpxchgStrong#}
7983fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_value: T) ?T {7983fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_value: T) ?T {
7984 const old_value = ptr.*;7984 const old_value = ptr.*;
7985 if (old_value == expected_value) {7985 if (old_value == expected_value) {
...@@ -8060,7 +8060,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -8060,7 +8060,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
8060 This function can be used to do "printf debugging" on8060 This function can be used to do "printf debugging" on
8061 compile-time executing code.8061 compile-time executing code.
8062 </p>8062 </p>
8063 {#code_begin|test_err|found compile log statement#}8063 {#code_begin|test_err|test_compileLog_builtin|found compile log statement#}
8064const print = @import("std").debug.print;8064const print = @import("std").debug.print;
80658065
8066const num1 = blk: {8066const num1 = blk: {
...@@ -8081,7 +8081,7 @@ test "main" {...@@ -8081,7 +8081,7 @@ test "main" {
8081 not encountered by analysis, the8081 not encountered by analysis, the
8082 program compiles successfully and the generated executable prints:8082 program compiles successfully and the generated executable prints:
8083 </p>8083 </p>
8084 {#code_begin|test|without_compileLog#}8084 {#code_begin|test|test_without_compileLog_builtin#}
8085const print = @import("std").debug.print;8085const print = @import("std").debug.print;
80868086
8087const num1 = blk: {8087const num1 = blk: {
...@@ -8296,7 +8296,7 @@ test "main" {...@@ -8296,7 +8296,7 @@ test "main" {
8296 {#syntax#}options.linkage{#endsyntax#} is {#syntax#}Strong{#endsyntax#}, this is equivalent to8296 {#syntax#}options.linkage{#endsyntax#} is {#syntax#}Strong{#endsyntax#}, this is equivalent to
8297 the {#syntax#}export{#endsyntax#} keyword used on a function:8297 the {#syntax#}export{#endsyntax#} keyword used on a function:
8298 </p>8298 </p>
8299 {#code_begin|obj#}8299 {#code_begin|obj|export_builtin#}
8300comptime {8300comptime {
8301 @export(internalName, .{ .name = "foo", .linkage = .Strong });8301 @export(internalName, .{ .name = "foo", .linkage = .Strong });
8302}8302}
...@@ -8304,12 +8304,12 @@ comptime {...@@ -8304,12 +8304,12 @@ comptime {
8304fn internalName() callconv(.C) void {}8304fn internalName() callconv(.C) void {}
8305 {#code_end#}8305 {#code_end#}
8306 <p>This is equivalent to:</p>8306 <p>This is equivalent to:</p>
8307 {#code_begin|obj#}8307 {#code_begin|obj|export_builtin_equivalent_code#}
8308export fn foo() void {}8308export fn foo() void {}
8309 {#code_end#}8309 {#code_end#}
8310 <p>Note that even when using {#syntax#}export{#endsyntax#}, the {#syntax#}@"foo"{#endsyntax#} syntax for8310 <p>Note that even when using {#syntax#}export{#endsyntax#}, the {#syntax#}@"foo"{#endsyntax#} syntax for
8311 {#link|identifiers|Identifiers#} can be used to choose any string for the symbol name:</p>8311 {#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#}
8313export fn @"A function name that is a complete sentence."() void {}8313export fn @"A function name that is a complete sentence."() void {}
8314 {#code_end#}8314 {#code_end#}
8315 <p>8315 <p>
...@@ -8342,7 +8342,7 @@ export fn @"A function name that is a complete sentence."() void {}...@@ -8342,7 +8342,7 @@ export fn @"A function name that is a complete sentence."() void {}
8342 <pre>{#syntax#}@field(lhs: anytype, comptime field_name: []const u8) (field){#endsyntax#}</pre>8342 <pre>{#syntax#}@field(lhs: anytype, comptime field_name: []const u8) (field){#endsyntax#}</pre>
8343 <p>Performs field access by a compile-time string. Works on both fields and declarations.8343 <p>Performs field access by a compile-time string. Works on both fields and declarations.
8344 </p>8344 </p>
8345 {#code_begin|test|field_decl_access_by_string#}8345 {#code_begin|test|test_field_builtin#}
8346const std = @import("std");8346const std = @import("std");
83478347
8348const Point = struct {8348const Point = struct {
...@@ -8424,7 +8424,7 @@ test "decl access by string" {...@@ -8424,7 +8424,7 @@ test "decl access by string" {
8424 Returns whether or not a {#link|container|Containers#} has a declaration8424 Returns whether or not a {#link|container|Containers#} has a declaration
8425 matching {#syntax#}name{#endsyntax#}.8425 matching {#syntax#}name{#endsyntax#}.
8426 </p>8426 </p>
8427 {#code_begin|test|hasDecl#}8427 {#code_begin|test|test_hasDecl_builtin#}
8428const std = @import("std");8428const std = @import("std");
8429const expect = std.testing.expect;8429const expect = std.testing.expect;
84308430
...@@ -8504,7 +8504,7 @@ test "@hasDecl" {...@@ -8504,7 +8504,7 @@ test "@hasDecl" {
8504 Attempting to convert a number which is out of range of the destination type results in8504 Attempting to convert a number which is out of range of the destination type results in
8505 safety-protected {#link|Undefined Behavior#}.8505 safety-protected {#link|Undefined Behavior#}.
8506 </p>8506 </p>
8507 {#code_begin|test_err|cast truncated bits#}8507 {#code_begin|test_err|test_intCast_builtin|cast truncated bits#}
8508test "integer cast panic" {8508test "integer cast panic" {
8509 var a: u16 = 0xabcd;8509 var a: u16 = 0xabcd;
8510 var b: u8 = @intCast(u8, a);8510 var b: u8 = @intCast(u8, a);
...@@ -8654,7 +8654,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>...@@ -8654,7 +8654,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
8654 designers targeting Wasm. So unless you are writing a new allocator from scratch, you should use8654 designers targeting Wasm. So unless you are writing a new allocator from scratch, you should use
8655 something like {#syntax#}@import("std").heap.WasmPageAllocator{#endsyntax#}.8655 something like {#syntax#}@import("std").heap.WasmPageAllocator{#endsyntax#}.
8656 </p>8656 </p>
8657 {#code_begin|test|wasmMemoryGrow#}8657 {#code_begin|test|test_wasmMemoryGrow_builtin#}
8658const std = @import("std");8658const std = @import("std");
8659const native_arch = @import("builtin").target.cpu.arch;8659const native_arch = @import("builtin").target.cpu.arch;
8660const expect = std.testing.expect;8660const expect = std.testing.expect;
...@@ -8855,7 +8855,7 @@ pub const PrefetchOptions = struct {...@@ -8855,7 +8855,7 @@ pub const PrefetchOptions = struct {
8855 <p>8855 <p>
8856 Example:8856 Example:
8857 </p>8857 </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#}
8859test "foo" {8859test "foo" {
8860 comptime {8860 comptime {
8861 var i = 0;8861 var i = 0;
...@@ -8864,7 +8864,7 @@ test "foo" {...@@ -8864,7 +8864,7 @@ test "foo" {
8864}8864}
8865 {#code_end#}8865 {#code_end#}
8866 <p>Now we use {#syntax#}@setEvalBranchQuota{#endsyntax#}:</p>8866 <p>Now we use {#syntax#}@setEvalBranchQuota{#endsyntax#}:</p>
8867 {#code_begin|test|setEvalBranchQuota#}8867 {#code_begin|test|test_setEvalBranchQuota_builtin#}
8868test "foo" {8868test "foo" {
8869 comptime {8869 comptime {
8870 @setEvalBranchQuota(1001);8870 @setEvalBranchQuota(1001);
...@@ -8882,7 +8882,7 @@ test "foo" {...@@ -8882,7 +8882,7 @@ test "foo" {
8882 <p>8882 <p>
8883 Sets the floating point mode of the current scope. Possible values are:8883 Sets the floating point mode of the current scope. Possible values are:
8884 </p>8884 </p>
8885 {#code_begin|syntax#}8885 {#code_begin|syntax|FloatMode#}
8886pub const FloatMode = enum {8886pub const FloatMode = enum {
8887 Strict,8887 Strict,
8888 Optimized,8888 Optimized,
...@@ -8917,7 +8917,7 @@ pub const FloatMode = enum {...@@ -8917,7 +8917,7 @@ pub const FloatMode = enum {
8917 <p>8917 <p>
8918 Sets whether runtime safety checks are enabled for the scope that contains the function call.8918 Sets whether runtime safety checks are enabled for the scope that contains the function call.
8919 </p>8919 </p>
8920 {#code_begin|test_safety|integer overflow#}8920 {#code_begin|test_safety|test_setRuntimeSafety_builtin|integer overflow#}
8921 {#code_release_fast#}8921 {#code_release_fast#}
8922test "@setRuntimeSafety" {8922test "@setRuntimeSafety" {
8923 // The builtin applies to the scope that it is called in. So here, integer overflow8923 // The builtin applies to the scope that it is called in. So here, integer overflow
...@@ -9020,7 +9020,7 @@ test "@setRuntimeSafety" {...@@ -9020,7 +9020,7 @@ test "@setRuntimeSafety" {
9020 {#link|pointer|Pointers#}, or {#syntax#}bool{#endsyntax#}. The mask may be any vector length, and its9020 {#link|pointer|Pointers#}, or {#syntax#}bool{#endsyntax#}. The mask may be any vector length, and its
9021 length determines the result length.9021 length determines the result length.
9022 </p>9022 </p>
9023 {#code_begin|test|vector_shuffle#}9023 {#code_begin|test|test_shuffle_builtin#}
9024const std = @import("std");9024const std = @import("std");
9025const expect = std.testing.expect;9025const expect = std.testing.expect;
90269026
...@@ -9068,7 +9068,7 @@ test "vector @shuffle" {...@@ -9068,7 +9068,7 @@ test "vector @shuffle" {
9068 Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value9068 Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value
9069 {#syntax#}scalar{#endsyntax#}:9069 {#syntax#}scalar{#endsyntax#}:
9070 </p>9070 </p>
9071 {#code_begin|test|vector_splat#}9071 {#code_begin|test|test_splat_builtin#}
9072const std = @import("std");9072const std = @import("std");
9073const expect = std.testing.expect;9073const expect = std.testing.expect;
90749074
...@@ -9111,7 +9111,7 @@ test "vector @splat" {...@@ -9111,7 +9111,7 @@ test "vector @splat" {
9111 types the operation associativity is preserved, unless the float mode is9111 types the operation associativity is preserved, unless the float mode is
9112 set to {#syntax#}Optimized{#endsyntax#}.9112 set to {#syntax#}Optimized{#endsyntax#}.
9113 </p>9113 </p>
9114 {#code_begin|test|vector_reduce#}9114 {#code_begin|test|test_reduce_builtin#}
9115const std = @import("std");9115const std = @import("std");
9116const expect = std.testing.expect;9116const expect = std.testing.expect;
91179117
...@@ -9133,7 +9133,7 @@ test "vector @reduce" {...@@ -9133,7 +9133,7 @@ test "vector @reduce" {
9133 <p>9133 <p>
9134 Returns a {#syntax#}SourceLocation{#endsyntax#} struct representing the function's name and location in the source code. This must be called in a function.9134 Returns a {#syntax#}SourceLocation{#endsyntax#} struct representing the function's name and location in the source code. This must be called in a function.
9135 </p>9135 </p>
9136 {#code_begin|test|source_location#}9136 {#code_begin|test|test_src_builtin#}
9137const std = @import("std");9137const std = @import("std");
9138const expect = std.testing.expect;9138const expect = std.testing.expect;
91399139
...@@ -9147,7 +9147,7 @@ fn doTheTest() !void {...@@ -9147,7 +9147,7 @@ fn doTheTest() !void {
9147 try expect(src.line == 9);9147 try expect(src.line == 9);
9148 try expect(src.column == 17);9148 try expect(src.column == 17);
9149 try expect(std.mem.endsWith(u8, src.fn_name, "doTheTest"));9149 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"));
9151}9151}
9152 {#code_end#}9152 {#code_end#}
9153 {#header_close#}9153 {#header_close#}
...@@ -9329,7 +9329,7 @@ fn doTheTest() !void {...@@ -9329,7 +9329,7 @@ fn doTheTest() !void {
9329 Returns the innermost struct, enum, or union that this function call is inside.9329 Returns the innermost struct, enum, or union that this function call is inside.
9330 This can be useful for an anonymous struct that needs to refer to itself:9330 This can be useful for an anonymous struct that needs to refer to itself:
9331 </p>9331 </p>
9332 {#code_begin|test|this_innermost#}9332 {#code_begin|test|test_this_builtin#}
9333const std = @import("std");9333const std = @import("std");
9334const expect = std.testing.expect;9334const expect = std.testing.expect;
93359335
...@@ -9370,7 +9370,7 @@ fn List(comptime T: type) type {...@@ -9370,7 +9370,7 @@ fn List(comptime T: type) type {
9370 <p>9370 <p>
9371 Calling {#syntax#}@truncate{#endsyntax#} on a number out of range of the destination type is well defined and working code:9371 Calling {#syntax#}@truncate{#endsyntax#} on a number out of range of the destination type is well defined and working code:
9372 </p>9372 </p>
9373 {#code_begin|test|truncate#}9373 {#code_begin|test|test_truncate_builtin#}
9374const std = @import("std");9374const std = @import("std");
9375const expect = std.testing.expect;9375const expect = std.testing.expect;
93769376
...@@ -9458,7 +9458,7 @@ test "integer truncation" {...@@ -9458,7 +9458,7 @@ test "integer truncation" {
9458 <p>9458 <p>
9459 The expressions are evaluated, however they are guaranteed to have no <em>runtime</em> side-effects:9459 The expressions are evaluated, however they are guaranteed to have no <em>runtime</em> side-effects:
9460 </p>9460 </p>
9461 {#code_begin|test|no_runtime_side_effects#}9461 {#code_begin|test|test_TypeOf_builtin#}
9462const std = @import("std");9462const std = @import("std");
9463const expect = std.testing.expect;9463const expect = std.testing.expect;
94649464
...@@ -9592,14 +9592,14 @@ pub fn build(b: *Builder) void {...@@ -9592,14 +9592,14 @@ pub fn build(b: *Builder) void {
9592 <p>9592 <p>
9593 When a safety check fails, Zig crashes with a stack trace, like this:9593 When a safety check fails, Zig crashes with a stack trace, like this:
9594 </p>9594 </p>
9595 {#code_begin|test_err|reached unreachable code#}9595 {#code_begin|test_err|test_undefined_behavior|reached unreachable code#}
9596test "safety check" {9596test "safety check" {
9597 unreachable;9597 unreachable;
9598}9598}
9599 {#code_end#}9599 {#code_end#}
9600 {#header_open|Reaching Unreachable Code#}9600 {#header_open|Reaching Unreachable Code#}
9601 <p>At compile-time:</p>9601 <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#}
9603comptime {9603comptime {
9604 assert(false);9604 assert(false);
9605}9605}
...@@ -9608,7 +9608,7 @@ fn assert(ok: bool) void {...@@ -9608,7 +9608,7 @@ fn assert(ok: bool) void {
9608}9608}
9609 {#code_end#}9609 {#code_end#}
9610 <p>At runtime:</p>9610 <p>At runtime:</p>
9611 {#code_begin|exe_err#}9611 {#code_begin|exe_err|runtime_reaching_unreachable#}
9612const std = @import("std");9612const std = @import("std");
96139613
9614pub fn main() void {9614pub fn main() void {
...@@ -9618,7 +9618,7 @@ pub fn main() void {...@@ -9618,7 +9618,7 @@ pub fn main() void {
9618 {#header_close#}9618 {#header_close#}
9619 {#header_open|Index out of Bounds#}9619 {#header_open|Index out of Bounds#}
9620 <p>At compile-time:</p>9620 <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#}
9622comptime {9622comptime {
9623 const array: [5]u8 = "hello".*;9623 const array: [5]u8 = "hello".*;
9624 const garbage = array[5];9624 const garbage = array[5];
...@@ -9626,7 +9626,7 @@ comptime {...@@ -9626,7 +9626,7 @@ comptime {
9626}9626}
9627 {#code_end#}9627 {#code_end#}
9628 <p>At runtime:</p>9628 <p>At runtime:</p>
9629 {#code_begin|exe_err#}9629 {#code_begin|exe_err|runtime_index_out_of_bounds#}
9630pub fn main() void {9630pub fn main() void {
9631 var x = foo("hello");9631 var x = foo("hello");
9632 _ = x;9632 _ = x;
...@@ -9639,7 +9639,7 @@ fn foo(x: []const u8) u8 {...@@ -9639,7 +9639,7 @@ fn foo(x: []const u8) u8 {
9639 {#header_close#}9639 {#header_close#}
9640 {#header_open|Cast Negative Number to Unsigned Integer#}9640 {#header_open|Cast Negative Number to Unsigned Integer#}
9641 <p>At compile-time:</p>9641 <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'#}
9643comptime {9643comptime {
9644 var value: i32 = -1;9644 var value: i32 = -1;
9645 const unsigned = @intCast(u32, value);9645 const unsigned = @intCast(u32, value);
...@@ -9647,7 +9647,7 @@ comptime {...@@ -9647,7 +9647,7 @@ comptime {
9647}9647}
9648 {#code_end#}9648 {#code_end#}
9649 <p>At runtime:</p>9649 <p>At runtime:</p>
9650 {#code_begin|exe_err#}9650 {#code_begin|exe_err|runtime_invalid_cast#}
9651const std = @import("std");9651const std = @import("std");
96529652
9653pub fn main() void {9653pub fn main() void {
...@@ -9662,7 +9662,7 @@ pub fn main() void {...@@ -9662,7 +9662,7 @@ pub fn main() void {
9662 {#header_close#}9662 {#header_close#}
9663 {#header_open|Cast Truncates Data#}9663 {#header_open|Cast Truncates Data#}
9664 <p>At compile-time:</p>9664 <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'#}
9666comptime {9666comptime {
9667 const spartan_count: u16 = 300;9667 const spartan_count: u16 = 300;
9668 const byte = @intCast(u8, spartan_count);9668 const byte = @intCast(u8, spartan_count);
...@@ -9670,7 +9670,7 @@ comptime {...@@ -9670,7 +9670,7 @@ comptime {
9670}9670}
9671 {#code_end#}9671 {#code_end#}
9672 <p>At runtime:</p>9672 <p>At runtime:</p>
9673 {#code_begin|exe_err#}9673 {#code_begin|exe_err|runtime_invalid_cast_truncate#}
9674const std = @import("std");9674const std = @import("std");
96759675
9676pub fn main() void {9676pub fn main() void {
...@@ -9697,14 +9697,14 @@ pub fn main() void {...@@ -9697,14 +9697,14 @@ pub fn main() void {
9697 <li>{#link|@divExact#} (division)</li>9697 <li>{#link|@divExact#} (division)</li>
9698 </ul>9698 </ul>
9699 <p>Example with addition at compile-time:</p>9699 <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'#}
9701comptime {9701comptime {
9702 var byte: u8 = 255;9702 var byte: u8 = 255;
9703 byte += 1;9703 byte += 1;
9704}9704}
9705 {#code_end#}9705 {#code_end#}
9706 <p>At runtime:</p>9706 <p>At runtime:</p>
9707 {#code_begin|exe_err#}9707 {#code_begin|exe_err|runtime_overflow#}
9708const std = @import("std");9708const std = @import("std");
97099709
9710pub fn main() void {9710pub fn main() void {
...@@ -9726,7 +9726,7 @@ pub fn main() void {...@@ -9726,7 +9726,7 @@ pub fn main() void {
9726 <li>{#syntax#}@import("std").math.shl{#endsyntax#}</li>9726 <li>{#syntax#}@import("std").math.shl{#endsyntax#}</li>
9727 </ul>9727 </ul>
9728 <p>Example of catching an overflow for addition:</p>9728 <p>Example of catching an overflow for addition:</p>
9729 {#code_begin|exe_err#}9729 {#code_begin|exe_err|math_add#}
9730const math = @import("std").math;9730const math = @import("std").math;
9731const print = @import("std").debug.print;9731const print = @import("std").debug.print;
9732pub fn main() !void {9732pub fn main() !void {
...@@ -9755,7 +9755,7 @@ pub fn main() !void {...@@ -9755,7 +9755,7 @@ pub fn main() !void {
9755 <p>9755 <p>
9756 Example of {#link|@addWithOverflow#}:9756 Example of {#link|@addWithOverflow#}:
9757 </p>9757 </p>
9758 {#code_begin|exe#}9758 {#code_begin|exe|addWithOverflow_builtin#}
9759const print = @import("std").debug.print;9759const print = @import("std").debug.print;
9760pub fn main() void {9760pub fn main() void {
9761 var byte: u8 = 255;9761 var byte: u8 = 255;
...@@ -9779,7 +9779,7 @@ pub fn main() void {...@@ -9779,7 +9779,7 @@ pub fn main() void {
9779 <li>{#syntax#}-%{#endsyntax#} (wraparound negation)</li>9779 <li>{#syntax#}-%{#endsyntax#} (wraparound negation)</li>
9780 <li>{#syntax#}*%{#endsyntax#} (wraparound multiplication)</li>9780 <li>{#syntax#}*%{#endsyntax#} (wraparound multiplication)</li>
9781 </ul>9781 </ul>
9782 {#code_begin|test|wraparound_semantics#}9782 {#code_begin|test|test_wraparound_semantics#}
9783const std = @import("std");9783const std = @import("std");
9784const expect = std.testing.expect;9784const expect = std.testing.expect;
9785const minInt = std.math.minInt;9785const minInt = std.math.minInt;
...@@ -9797,14 +9797,14 @@ test "wraparound addition and subtraction" {...@@ -9797,14 +9797,14 @@ test "wraparound addition and subtraction" {
9797 {#header_close#}9797 {#header_close#}
9798 {#header_open|Exact Left Shift Overflow#}9798 {#header_open|Exact Left Shift Overflow#}
9799 <p>At compile-time:</p>9799 <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#}
9801comptime {9801comptime {
9802 const x = @shlExact(@as(u8, 0b01010101), 2);9802 const x = @shlExact(@as(u8, 0b01010101), 2);
9803 _ = x;9803 _ = x;
9804}9804}
9805 {#code_end#}9805 {#code_end#}
9806 <p>At runtime:</p>9806 <p>At runtime:</p>
9807 {#code_begin|exe_err#}9807 {#code_begin|exe_err|runtime_shlExact_overflow#}
9808const std = @import("std");9808const std = @import("std");
98099809
9810pub fn main() void {9810pub fn main() void {
...@@ -9816,14 +9816,14 @@ pub fn main() void {...@@ -9816,14 +9816,14 @@ pub fn main() void {
9816 {#header_close#}9816 {#header_close#}
9817 {#header_open|Exact Right Shift Overflow#}9817 {#header_open|Exact Right Shift Overflow#}
9818 <p>At compile-time:</p>9818 <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#}
9820comptime {9820comptime {
9821 const x = @shrExact(@as(u8, 0b10101010), 2);9821 const x = @shrExact(@as(u8, 0b10101010), 2);
9822 _ = x;9822 _ = x;
9823}9823}
9824 {#code_end#}9824 {#code_end#}
9825 <p>At runtime:</p>9825 <p>At runtime:</p>
9826 {#code_begin|exe_err#}9826 {#code_begin|exe_err|runtime_shrExact_overflow#}
9827const std = @import("std");9827const std = @import("std");
98289828
9829pub fn main() void {9829pub fn main() void {
...@@ -9835,7 +9835,7 @@ pub fn main() void {...@@ -9835,7 +9835,7 @@ pub fn main() void {
9835 {#header_close#}9835 {#header_close#}
9836 {#header_open|Division by Zero#}9836 {#header_open|Division by Zero#}
9837 <p>At compile-time:</p>9837 <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#}
9839comptime {9839comptime {
9840 const a: i32 = 1;9840 const a: i32 = 1;
9841 const b: i32 = 0;9841 const b: i32 = 0;
...@@ -9844,7 +9844,7 @@ comptime {...@@ -9844,7 +9844,7 @@ comptime {
9844}9844}
9845 {#code_end#}9845 {#code_end#}
9846 <p>At runtime:</p>9846 <p>At runtime:</p>
9847 {#code_begin|exe_err#}9847 {#code_begin|exe_err|runtime_division_by_zero#}
9848const std = @import("std");9848const std = @import("std");
98499849
9850pub fn main() void {9850pub fn main() void {
...@@ -9857,7 +9857,7 @@ pub fn main() void {...@@ -9857,7 +9857,7 @@ pub fn main() void {
9857 {#header_close#}9857 {#header_close#}
9858 {#header_open|Remainder Division by Zero#}9858 {#header_open|Remainder Division by Zero#}
9859 <p>At compile-time:</p>9859 <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#}
9861comptime {9861comptime {
9862 const a: i32 = 10;9862 const a: i32 = 10;
9863 const b: i32 = 0;9863 const b: i32 = 0;
...@@ -9866,7 +9866,7 @@ comptime {...@@ -9866,7 +9866,7 @@ comptime {
9866}9866}
9867 {#code_end#}9867 {#code_end#}
9868 <p>At runtime:</p>9868 <p>At runtime:</p>
9869 {#code_begin|exe_err#}9869 {#code_begin|exe_err|runtime_remainder_division_by_zero#}
9870const std = @import("std");9870const std = @import("std");
98719871
9872pub fn main() void {9872pub fn main() void {
...@@ -9879,7 +9879,7 @@ pub fn main() void {...@@ -9879,7 +9879,7 @@ pub fn main() void {
9879 {#header_close#}9879 {#header_close#}
9880 {#header_open|Exact Division Remainder#}9880 {#header_open|Exact Division Remainder#}
9881 <p>At compile-time:</p>9881 <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#}
9883comptime {9883comptime {
9884 const a: u32 = 10;9884 const a: u32 = 10;
9885 const b: u32 = 3;9885 const b: u32 = 3;
...@@ -9888,7 +9888,7 @@ comptime {...@@ -9888,7 +9888,7 @@ comptime {
9888}9888}
9889 {#code_end#}9889 {#code_end#}
9890 <p>At runtime:</p>9890 <p>At runtime:</p>
9891 {#code_begin|exe_err#}9891 {#code_begin|exe_err|runtime_divExact_remainder#}
9892const std = @import("std");9892const std = @import("std");
98939893
9894pub fn main() void {9894pub fn main() void {
...@@ -9901,7 +9901,7 @@ pub fn main() void {...@@ -9901,7 +9901,7 @@ pub fn main() void {
9901 {#header_close#}9901 {#header_close#}
9902 {#header_open|Attempt to Unwrap Null#}9902 {#header_open|Attempt to Unwrap Null#}
9903 <p>At compile-time:</p>9903 <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#}
9905comptime {9905comptime {
9906 const optional_number: ?i32 = null;9906 const optional_number: ?i32 = null;
9907 const number = optional_number.?;9907 const number = optional_number.?;
...@@ -9909,7 +9909,7 @@ comptime {...@@ -9909,7 +9909,7 @@ comptime {
9909}9909}
9910 {#code_end#}9910 {#code_end#}
9911 <p>At runtime:</p>9911 <p>At runtime:</p>
9912 {#code_begin|exe_err#}9912 {#code_begin|exe_err|runtime_unwrap_null#}
9913const std = @import("std");9913const std = @import("std");
99149914
9915pub fn main() void {9915pub fn main() void {
...@@ -9920,7 +9920,7 @@ pub fn main() void {...@@ -9920,7 +9920,7 @@ pub fn main() void {
9920 {#code_end#}9920 {#code_end#}
9921 <p>One way to avoid this crash is to test for null instead of assuming non-null, with9921 <p>One way to avoid this crash is to test for null instead of assuming non-null, with
9922 the {#syntax#}if{#endsyntax#} expression:</p>9922 the {#syntax#}if{#endsyntax#} expression:</p>
9923 {#code_begin|exe|test#}9923 {#code_begin|exe|testing_null_with_if#}
9924const print = @import("std").debug.print;9924const print = @import("std").debug.print;
9925pub fn main() void {9925pub fn main() void {
9926 const optional_number: ?i32 = null;9926 const optional_number: ?i32 = null;
...@@ -9936,7 +9936,7 @@ pub fn main() void {...@@ -9936,7 +9936,7 @@ pub fn main() void {
9936 {#header_close#}9936 {#header_close#}
9937 {#header_open|Attempt to Unwrap Error#}9937 {#header_open|Attempt to Unwrap Error#}
9938 <p>At compile-time:</p>9938 <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'#}
9940comptime {9940comptime {
9941 const number = getNumberOrFail() catch unreachable;9941 const number = getNumberOrFail() catch unreachable;
9942 _ = number;9942 _ = number;
...@@ -9947,7 +9947,7 @@ fn getNumberOrFail() !i32 {...@@ -9947,7 +9947,7 @@ fn getNumberOrFail() !i32 {
9947}9947}
9948 {#code_end#}9948 {#code_end#}
9949 <p>At runtime:</p>9949 <p>At runtime:</p>
9950 {#code_begin|exe_err#}9950 {#code_begin|exe_err|runtime_unwrap_error#}
9951const std = @import("std");9951const std = @import("std");
99529952
9953pub fn main() void {9953pub fn main() void {
...@@ -9961,7 +9961,7 @@ fn getNumberOrFail() !i32 {...@@ -9961,7 +9961,7 @@ fn getNumberOrFail() !i32 {
9961 {#code_end#}9961 {#code_end#}
9962 <p>One way to avoid this crash is to test for an error instead of assuming a successful result, with9962 <p>One way to avoid this crash is to test for an error instead of assuming a successful result, with
9963 the {#syntax#}if{#endsyntax#} expression:</p>9963 the {#syntax#}if{#endsyntax#} expression:</p>
9964 {#code_begin|exe#}9964 {#code_begin|exe|testing_error_with_if#}
9965const print = @import("std").debug.print;9965const print = @import("std").debug.print;
99669966
9967pub fn main() void {9967pub fn main() void {
...@@ -9982,7 +9982,7 @@ fn getNumberOrFail() !i32 {...@@ -9982,7 +9982,7 @@ fn getNumberOrFail() !i32 {
9982 {#header_close#}9982 {#header_close#}
9983 {#header_open|Invalid Error Code#}9983 {#header_open|Invalid Error Code#}
9984 <p>At compile-time:</p>9984 <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#}
9986comptime {9986comptime {
9987 const err = error.AnError;9987 const err = error.AnError;
9988 const number = @errorToInt(err) + 10;9988 const number = @errorToInt(err) + 10;
...@@ -9991,7 +9991,7 @@ comptime {...@@ -9991,7 +9991,7 @@ comptime {
9991}9991}
9992 {#code_end#}9992 {#code_end#}
9993 <p>At runtime:</p>9993 <p>At runtime:</p>
9994 {#code_begin|exe_err#}9994 {#code_begin|exe_err|runtime_invalid_error_code#}
9995const std = @import("std");9995const std = @import("std");
99969996
9997pub fn main() void {9997pub fn main() void {
...@@ -10004,7 +10004,7 @@ pub fn main() void {...@@ -10004,7 +10004,7 @@ pub fn main() void {
10004 {#header_close#}10004 {#header_close#}
10005 {#header_open|Invalid Enum Cast#}10005 {#header_open|Invalid Enum Cast#}
10006 <p>At compile-time:</p>10006 <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'#}
10008const Foo = enum {10008const Foo = enum {
10009 a,10009 a,
10010 b,10010 b,
...@@ -10017,7 +10017,7 @@ comptime {...@@ -10017,7 +10017,7 @@ comptime {
10017}10017}
10018 {#code_end#}10018 {#code_end#}
10019 <p>At runtime:</p>10019 <p>At runtime:</p>
10020 {#code_begin|exe_err#}10020 {#code_begin|exe_err|runtime_invalid_enum_cast#}
10021const std = @import("std");10021const std = @import("std");
1002210022
10023const Foo = enum {10023const Foo = enum {
...@@ -10036,7 +10036,7 @@ pub fn main() void {...@@ -10036,7 +10036,7 @@ pub fn main() void {
1003610036
10037 {#header_open|Invalid Error Set Cast#}10037 {#header_open|Invalid Error Set Cast#}
10038 <p>At compile-time:</p>10038 <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}'#}
10040const Set1 = error{10040const Set1 = error{
10041 A,10041 A,
10042 B,10042 B,
...@@ -10050,7 +10050,7 @@ comptime {...@@ -10050,7 +10050,7 @@ comptime {
10050}10050}
10051 {#code_end#}10051 {#code_end#}
10052 <p>At runtime:</p>10052 <p>At runtime:</p>
10053 {#code_begin|exe_err#}10053 {#code_begin|exe_err|runtime_invalid_error_set_cast#}
10054const std = @import("std");10054const std = @import("std");
1005510055
10056const Set1 = error{10056const Set1 = error{
...@@ -10073,7 +10073,7 @@ fn foo(set1: Set1) void {...@@ -10073,7 +10073,7 @@ fn foo(set1: Set1) void {
1007310073
10074 {#header_open|Incorrect Pointer Alignment#}10074 {#header_open|Incorrect Pointer Alignment#}
10075 <p>At compile-time:</p>10075 <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#}
10077comptime {10077comptime {
10078 const ptr = @intToPtr(*align(1) i32, 0x1);10078 const ptr = @intToPtr(*align(1) i32, 0x1);
10079 const aligned = @alignCast(4, ptr);10079 const aligned = @alignCast(4, ptr);
...@@ -10081,7 +10081,7 @@ comptime {...@@ -10081,7 +10081,7 @@ comptime {
10081}10081}
10082 {#code_end#}10082 {#code_end#}
10083 <p>At runtime:</p>10083 <p>At runtime:</p>
10084 {#code_begin|exe_err#}10084 {#code_begin|exe_err|runtime_incorrect_pointer_alignment#}
10085const mem = @import("std").mem;10085const mem = @import("std").mem;
10086pub fn main() !void {10086pub fn main() !void {
10087 var array align(4) = [_]u32{ 0x11111111, 0x11111111 };10087 var array align(4) = [_]u32{ 0x11111111, 0x11111111 };
...@@ -10097,7 +10097,7 @@ fn foo(bytes: []u8) u32 {...@@ -10097,7 +10097,7 @@ fn foo(bytes: []u8) u32 {
10097 {#header_close#}10097 {#header_close#}
10098 {#header_open|Wrong Union Field Access#}10098 {#header_open|Wrong Union Field Access#}
10099 <p>At compile-time:</p>10099 <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#}
10101comptime {10101comptime {
10102 var f = Foo{ .int = 42 };10102 var f = Foo{ .int = 42 };
10103 f.float = 12.34;10103 f.float = 12.34;
...@@ -10109,7 +10109,7 @@ const Foo = union {...@@ -10109,7 +10109,7 @@ const Foo = union {
10109};10109};
10110 {#code_end#}10110 {#code_end#}
10111 <p>At runtime:</p>10111 <p>At runtime:</p>
10112 {#code_begin|exe_err#}10112 {#code_begin|exe_err|runtime_wrong_union_field_access#}
10113const std = @import("std");10113const std = @import("std");
1011410114
10115const Foo = union {10115const Foo = union {
...@@ -10133,7 +10133,7 @@ fn bar(f: *Foo) void {...@@ -10133,7 +10133,7 @@ fn bar(f: *Foo) void {
10133 <p>10133 <p>
10134 To change the active field of a union, assign the entire union, like this:10134 To change the active field of a union, assign the entire union, like this:
10135 </p>10135 </p>
10136 {#code_begin|exe#}10136 {#code_begin|exe|change_active_union_field#}
10137const std = @import("std");10137const std = @import("std");
1013810138
10139const Foo = union {10139const Foo = union {
...@@ -10155,7 +10155,7 @@ fn bar(f: *Foo) void {...@@ -10155,7 +10155,7 @@ fn bar(f: *Foo) void {
10155 To change the active field of a union when a meaningful value for the field is not known,10155 To change the active field of a union when a meaningful value for the field is not known,
10156 use {#link|undefined#}, like this:10156 use {#link|undefined#}, like this:
10157 </p>10157 </p>
10158 {#code_begin|exe#}10158 {#code_begin|exe|undefined_active_union_field#}
10159const std = @import("std");10159const std = @import("std");
1016010160
10161const Foo = union {10161const Foo = union {
...@@ -10188,7 +10188,7 @@ fn bar(f: *Foo) void {...@@ -10188,7 +10188,7 @@ fn bar(f: *Foo) void {
10188 allow address zero, but normal {#link|Pointers#} do not.10188 allow address zero, but normal {#link|Pointers#} do not.
10189 </p>10189 </p>
10190 <p>At compile-time:</p>10190 <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#}
10192comptime {10192comptime {
10193 const opt_ptr: ?*i32 = null;10193 const opt_ptr: ?*i32 = null;
10194 const ptr = @ptrCast(*i32, opt_ptr);10194 const ptr = @ptrCast(*i32, opt_ptr);
...@@ -10196,7 +10196,7 @@ comptime {...@@ -10196,7 +10196,7 @@ comptime {
10196}10196}
10197 {#code_end#}10197 {#code_end#}
10198 <p>At runtime:</p>10198 <p>At runtime:</p>
10199 {#code_begin|exe_err#}10199 {#code_begin|exe_err|runtime_invalid_null_pointer_cast#}
10200pub fn main() void {10200pub fn main() void {
10201 var opt_ptr: ?*i32 = null;10201 var opt_ptr: ?*i32 = null;
10202 var ptr = @ptrCast(*i32, opt_ptr);10202 var ptr = @ptrCast(*i32, opt_ptr);
...@@ -10224,7 +10224,7 @@ pub fn main() void {...@@ -10224,7 +10224,7 @@ pub fn main() void {
10224 {#syntax#}std.ArrayList{#endsyntax#} accept an {#syntax#}Allocator{#endsyntax#} parameter in10224 {#syntax#}std.ArrayList{#endsyntax#} accept an {#syntax#}Allocator{#endsyntax#} parameter in
10225 their initialization functions:10225 their initialization functions:
10226 </p>10226 </p>
10227 {#code_begin|test|allocator#}10227 {#code_begin|test|test_allocator#}
10228const std = @import("std");10228const std = @import("std");
10229const Allocator = std.mem.Allocator;10229const Allocator = std.mem.Allocator;
10230const expect = std.testing.expect;10230const expect = std.testing.expect;
...@@ -10278,7 +10278,7 @@ fn concat(allocator: Allocator, a: []const u8, b: []const u8) ![]u8 {...@@ -10278,7 +10278,7 @@ fn concat(allocator: Allocator, a: []const u8, b: []const u8) ![]u8 {
10278 cyclical pattern (such as a video game main loop, or a web server request handler),10278 cyclical pattern (such as a video game main loop, or a web server request handler),
10279 such that it would make sense to free everything at once at the end?10279 such that it would make sense to free everything at once at the end?
10280 In this case, it is recommended to follow this pattern:10280 In this case, it is recommended to follow this pattern:
10281 {#code_begin|exe|cli_allocation#}10281 {#code_begin|exe|cli_allocation#}
10282const std = @import("std");10282const std = @import("std");
1028310283
10284pub fn main() !void {10284pub fn main() !void {
...@@ -10290,7 +10290,7 @@ pub fn main() !void {...@@ -10290,7 +10290,7 @@ pub fn main() !void {
10290 const ptr = try allocator.create(i32);10290 const ptr = try allocator.create(i32);
10291 std.debug.print("ptr={*}\n", .{ptr});10291 std.debug.print("ptr={*}\n", .{ptr});
10292}10292}
10293 {#code_end#}10293 {#code_end#}
10294 When using this kind of allocator, there is no need to free anything manually. Everything10294 When using this kind of allocator, there is no need to free anything manually. Everything
10295 gets freed at once with the call to {#syntax#}arena.deinit(){#endsyntax#}.10295 gets freed at once with the call to {#syntax#}arena.deinit(){#endsyntax#}.
10296 </li>10296 </li>
...@@ -10328,7 +10328,7 @@ pub fn main() !void {...@@ -10328,7 +10328,7 @@ pub fn main() !void {
10328 <p>String literals such as {#syntax#}"foo"{#endsyntax#} are in the global constant data section.10328 <p>String literals such as {#syntax#}"foo"{#endsyntax#} are in the global constant data section.
10329 This is why it is an error to pass a string literal to a mutable slice, like this:10329 This is why it is an error to pass a string literal to a mutable slice, like this:
10330 </p>10330 </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'#}
10332fn foo(s: []u8) void {10332fn foo(s: []u8) void {
10333 _ = s;10333 _ = s;
10334}10334}
...@@ -10338,7 +10338,7 @@ test "string literal to mutable slice" {...@@ -10338,7 +10338,7 @@ test "string literal to mutable slice" {
10338}10338}
10339 {#code_end#}10339 {#code_end#}
10340 <p>However if you make the slice constant, then it works:</p>10340 <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#}
10342fn foo(s: []const u8) void {10342fn foo(s: []const u8) void {
10343 _ = s;10343 _ = s;
10344}10344}
...@@ -10474,7 +10474,7 @@ test "string literal to constant slice" {...@@ -10474,7 +10474,7 @@ test "string literal to constant slice" {
10474 which the compiler makes available to every Zig source file. It contains10474 which the compiler makes available to every Zig source file. It contains
10475 compile-time constants such as the current target, endianness, and release mode.10475 compile-time constants such as the current target, endianness, and release mode.
10476 </p>10476 </p>
10477 {#code_begin|syntax#}10477 {#code_begin|syntax|compile_variables#}
10478const builtin = @import("builtin");10478const builtin = @import("builtin");
10479const separator = if (builtin.os.tag == .windows) '\\' else '/';10479const separator = if (builtin.os.tag == .windows) '\\' else '/';
10480 {#code_end#}10480 {#code_end#}
...@@ -10526,7 +10526,7 @@ const separator = if (builtin.os.tag == .windows) '\\' else '/';...@@ -10526,7 +10526,7 @@ const separator = if (builtin.os.tag == .windows) '\\' else '/';
10526 {#header_open|Building an Executable#}10526 {#header_open|Building an Executable#}
10527 <p>This <code class="file">build.zig</code> file is automatically generated10527 <p>This <code class="file">build.zig</code> file is automatically generated
10528 by <kbd>zig init-exe</kbd>.</p>10528 by <kbd>zig init-exe</kbd>.</p>
10529 {#code_begin|syntax|build#}10529 {#code_begin|syntax|build_executable#}
10530const Builder = @import("std").build.Builder;10530const Builder = @import("std").build.Builder;
1053110531
10532pub fn build(b: *Builder) void {10532pub fn build(b: *Builder) void {
...@@ -10560,7 +10560,7 @@ pub fn build(b: *Builder) void {...@@ -10560,7 +10560,7 @@ pub fn build(b: *Builder) void {
10560 {#header_open|Building a Library#}10560 {#header_open|Building a Library#}
10561 <p>This <code class="file">build.zig</code> file is automatically generated10561 <p>This <code class="file">build.zig</code> file is automatically generated
10562 by <kbd>zig init-lib</kbd>.</p>10562 by <kbd>zig init-lib</kbd>.</p>
10563 {#code_begin|syntax|build#}10563 {#code_begin|syntax|build_library#}
10564const Builder = @import("std").build.Builder;10564const Builder = @import("std").build.Builder;
1056510565
10566pub fn build(b: *Builder) void {10566pub fn build(b: *Builder) void {
...@@ -10622,7 +10622,7 @@ lib.addCSourceFile("src/lib.c", &[_][]const u8{...@@ -10622,7 +10622,7 @@ lib.addCSourceFile("src/lib.c", &[_][]const u8{
10622 The {#syntax#}@cImport{#endsyntax#} builtin function can be used10622 The {#syntax#}@cImport{#endsyntax#} builtin function can be used
10623 to directly import symbols from <code class="file">.h</code> files:10623 to directly import symbols from <code class="file">.h</code> files:
10624 </p>10624 </p>
10625 {#code_begin|exe#}10625 {#code_begin|exe|cImport_builtin#}
10626 {#link_libc#}10626 {#link_libc#}
10627const c = @cImport({10627const c = @cImport({
10628 // See https://github.com/ziglang/zig/issues/51510628 // 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#}...@@ -10738,7 +10738,7 @@ pub extern fn do_something(foo: enum_FOO) c_int;{#end_shell_samp#}
10738 To see where the cached files are stored when compiling code that uses {#syntax#}@cImport{#endsyntax#},10738 To see where the cached files are stored when compiling code that uses {#syntax#}@cImport{#endsyntax#},
10739 use the <kbd>--verbose-cimport</kbd> flag:10739 use the <kbd>--verbose-cimport</kbd> flag:
10740 </p>10740 </p>
10741 {#code_begin|exe|verbose#}10741 {#code_begin|exe|verbose_cimport_flag#}
10742 {#link_libc#}10742 {#link_libc#}
10743 {#code_verbose_cimport#}10743 {#code_verbose_cimport#}
10744const c = @cImport({10744const c = @cImport({
...@@ -10856,7 +10856,7 @@ pub const MAKELOCAL = @compileError("unable to translate C expr: unexpected toke...@@ -10856,7 +10856,7 @@ pub const MAKELOCAL = @compileError("unable to translate C expr: unexpected toke
1085610856
10857 {#header_open|C Variadic Functions#}10857 {#header_open|C Variadic Functions#}
10858 <p>Zig supports extern variadic functions.</p>10858 <p>Zig supports extern variadic functions.</p>
10859 {#code_begin|test|variadic_function#}10859 {#code_begin|test|test_variadic_function#}
10860 {#link_libc#}10860 {#link_libc#}
10861 {#code_verbose_cimport#}10861 {#code_verbose_cimport#}
10862const std = @import("std");10862const std = @import("std");
...@@ -10872,7 +10872,7 @@ test "variadic function" {...@@ -10872,7 +10872,7 @@ test "variadic function" {
10872 <p>10872 <p>
10873 Variadic functions can be implemented using {#link|@cVaStart#}, {#link|@cVaEnd#}, {#link|@cVaArg#} and {#link|@cVaCopy#}10873 Variadic functions can be implemented using {#link|@cVaStart#}, {#link|@cVaEnd#}, {#link|@cVaArg#} and {#link|@cVaCopy#}
10874 </p>10874 </p>
10875 {#code_begin|test|defining_variadic_function#}10875 {#code_begin|test|test_defining_variadic_function#}
10876const std = @import("std");10876const std = @import("std");
10877const testing = std.testing;10877const testing = std.testing;
10878const builtin = @import("builtin");10878const builtin = @import("builtin");
...@@ -10926,7 +10926,7 @@ int main(int argc, char **argv) {...@@ -10926,7 +10926,7 @@ int main(int argc, char **argv) {
10926 return 0;10926 return 0;
10927}10927}
10928 {#end_syntax_block#}10928 {#end_syntax_block#}
10929 {#code_begin|syntax|build#}10929 {#code_begin|syntax|build_c#}
10930const Builder = @import("std").build.Builder;10930const Builder = @import("std").build.Builder;
1093110931
10932pub fn build(b: *Builder) void {10932pub fn build(b: *Builder) void {
...@@ -10988,7 +10988,7 @@ int main(int argc, char **argv) {...@@ -10988,7 +10988,7 @@ int main(int argc, char **argv) {
10988 return 0;10988 return 0;
10989}10989}
10990 {#end_syntax_block#}10990 {#end_syntax_block#}
10991 {#code_begin|syntax|build#}10991 {#code_begin|syntax|build_object#}
10992const Builder = @import("std").build.Builder;10992const Builder = @import("std").build.Builder;
1099310993
10994pub fn build(b: *Builder) void {10994pub fn build(b: *Builder) void {
...@@ -11040,7 +11040,7 @@ The result is 3{#end_shell_samp#}...@@ -11040,7 +11040,7 @@ The result is 3{#end_shell_samp#}
11040 {#header_open|WASI#}11040 {#header_open|WASI#}
11041 <p>Zig's support for WebAssembly System Interface (WASI) is under active development.11041 <p>Zig's support for WebAssembly System Interface (WASI) is under active development.
11042 Example of using the standard library and reading command line arguments:</p>11042 Example of using the standard library and reading command line arguments:</p>
11043 {#code_begin|exe|args#}11043 {#code_begin|exe|wasi_args#}
11044 {#target_wasi#}11044 {#target_wasi#}
11045const std = @import("std");11045const std = @import("std");
1104611046
...@@ -11061,7 +11061,7 @@ pub fn main() !void {...@@ -11061,7 +11061,7 @@ pub fn main() !void {
110612: hello{#end_shell_samp#}110612: hello{#end_shell_samp#}
11062 <p>A more interesting example would be extracting the list of preopens from the runtime.11062 <p>A more interesting example would be extracting the list of preopens from the runtime.
11063 This is now supported in the standard library via {#syntax#}std.fs.wasi.PreopenList{#endsyntax#}:</p>11063 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#}
11065 {#target_wasi#}11065 {#target_wasi#}
11066const std = @import("std");11066const std = @import("std");
11067const fs = std.fs;11067const fs = std.fs;