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