| ... | @@ -381,7 +381,7 @@ | ... | @@ -381,7 +381,7 @@ |
| 381 | In this case, the {#syntax#}!{#endsyntax#} may be omitted from the return | 381 | In this case, the {#syntax#}!{#endsyntax#} may be omitted from the return |
| 382 | type of <code>main</code> because no errors are returned from the function. | 382 | type of <code>main</code> because no errors are returned from the function. |
| 383 | </p> | 383 | </p> |
| 384 | {#see_also|Values|Tuples|@import|Errors|Root Source File|Source Encoding|try#} | 384 | {#see_also|Values|Tuples|@import|Errors|Entry Point|Source Encoding|try#} |
| 385 | {#header_close#} | 385 | {#header_close#} |
| 386 | {#header_open|Comments#} | 386 | {#header_open|Comments#} |
| 387 | <p> | 387 | <p> |
| ... | @@ -823,7 +823,7 @@ | ... | @@ -823,7 +823,7 @@ |
| 823 | <kbd>zig test</kbd> is a tool that creates and runs a test build. By default, it builds and runs an | 823 | <kbd>zig test</kbd> is a tool that creates and runs a test build. By default, it builds and runs an |
| 824 | executable program using the <em>default test runner</em> provided by the {#link|Zig Standard Library#} | 824 | executable program using the <em>default test runner</em> provided by the {#link|Zig Standard Library#} |
| 825 | as its main entry point. During the build, {#syntax#}test{#endsyntax#} declarations found while | 825 | as its main entry point. During the build, {#syntax#}test{#endsyntax#} declarations found while |
| 826 | {#link|resolving|Root Source File#} the given Zig source file are included for the default test runner | 826 | {#link|resolving|File and Declaration Discovery#} the given Zig source file are included for the default test runner |
| 827 | to run and report on. | 827 | to run and report on. |
| 828 | </p> | 828 | </p> |
| 829 | <aside> | 829 | <aside> |
| ... | @@ -1049,12 +1049,12 @@ | ... | @@ -1049,12 +1049,12 @@ |
| 1049 | {#header_close#} | 1049 | {#header_close#} |
| 1050 | {#header_open|Runtime Integer Values#} | 1050 | {#header_open|Runtime Integer Values#} |
| 1051 | <p> | 1051 | <p> |
| 1052 | Integer literals have no size limitation, and if any undefined behavior occurs, | 1052 | Integer literals have no size limitation, and if any Illegal Behavior occurs, |
| 1053 | the compiler catches it. | 1053 | the compiler catches it. |
| 1054 | </p> | 1054 | </p> |
| 1055 | <p> | 1055 | <p> |
| 1056 | However, once an integer value is no longer known at compile-time, it must have a | 1056 | However, once an integer value is no longer known at compile-time, it must have a |
| 1057 | known size, and is vulnerable to undefined behavior. | 1057 | known size, and is vulnerable to safety-checked {#link|Illegal Behavior#}. |
| 1058 | </p> | 1058 | </p> |
| 1059 | {#code|runtime_vs_comptime.zig#} | 1059 | {#code|runtime_vs_comptime.zig#} |
| 1060 | | 1060 | |
| ... | @@ -1064,7 +1064,7 @@ | ... | @@ -1064,7 +1064,7 @@ |
| 1064 | {#link|Division by Zero#}. | 1064 | {#link|Division by Zero#}. |
| 1065 | </p> | 1065 | </p> |
| 1066 | <p> | 1066 | <p> |
| 1067 | Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause undefined behavior on | 1067 | Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause {#link|Illegal Behavior#} on |
| 1068 | integer overflow. Alternative operators are provided for wrapping and saturating arithmetic on all targets. | 1068 | integer overflow. Alternative operators are provided for wrapping and saturating arithmetic on all targets. |
| 1069 | {#syntax#}+%{#endsyntax#} and {#syntax#}-%{#endsyntax#} perform wrapping arithmetic | 1069 | {#syntax#}+%{#endsyntax#} and {#syntax#}-%{#endsyntax#} perform wrapping arithmetic |
| 1070 | while {#syntax#}+|{#endsyntax#} and {#syntax#}-|{#endsyntax#} perform saturating arithmetic. | 1070 | while {#syntax#}+|{#endsyntax#} and {#syntax#}-|{#endsyntax#} perform saturating arithmetic. |
| ... | @@ -2029,7 +2029,7 @@ or | ... | @@ -2029,7 +2029,7 @@ or |
| 2029 | </p> | 2029 | </p> |
| 2030 | <p> | 2030 | <p> |
| 2031 | Slices have bounds checking and are therefore protected | 2031 | Slices have bounds checking and are therefore protected |
| 2032 | against this kind of undefined behavior. This is one reason | 2032 | against this kind of Illegal Behavior. This is one reason |
| 2033 | we prefer slices to pointers. | 2033 | we prefer slices to pointers. |
| 2034 | </p> | 2034 | </p> |
| 2035 | {#code|test_slice_bounds.zig#} | 2035 | {#code|test_slice_bounds.zig#} |
| ... | @@ -2048,7 +2048,7 @@ or | ... | @@ -2048,7 +2048,7 @@ or |
| 2048 | | 2048 | |
| 2049 | <p> | 2049 | <p> |
| 2050 | {#link|@ptrCast#} converts a pointer's element type to another. This | 2050 | {#link|@ptrCast#} converts a pointer's element type to another. This |
| 2051 | creates a new pointer that can cause undetectable illegal behavior | 2051 | creates a new pointer that can cause undetectable Illegal Behavior |
| 2052 | depending on the loads and stores that pass through it. Generally, other | 2052 | depending on the loads and stores that pass through it. Generally, other |
| 2053 | kinds of type conversions are preferable to | 2053 | kinds of type conversions are preferable to |
| 2054 | {#syntax#}@ptrCast{#endsyntax#} if possible. | 2054 | {#syntax#}@ptrCast{#endsyntax#} if possible. |
| ... | @@ -2164,7 +2164,7 @@ or | ... | @@ -2164,7 +2164,7 @@ or |
| 2164 | | 2164 | |
| 2165 | <p> | 2165 | <p> |
| 2166 | Sentinel-terminated slicing asserts that the element in the sentinel position of the backing data is | 2166 | Sentinel-terminated slicing asserts that the element in the sentinel position of the backing data is |
| 2167 | actually the sentinel value. If this is not the case, safety-protected {#link|Undefined Behavior#} results. | 2167 | actually the sentinel value. If this is not the case, safety-checked {#link|Illegal Behavior#} results. |
| 2168 | </p> | 2168 | </p> |
| 2169 | {#code|test_sentinel_mismatch.zig#} | 2169 | {#code|test_sentinel_mismatch.zig#} |
| 2170 | | 2170 | |
| ... | @@ -2425,7 +2425,7 @@ or | ... | @@ -2425,7 +2425,7 @@ or |
| 2425 | or use an {#link|extern union#} or a {#link|packed union#} which have | 2425 | or use an {#link|extern union#} or a {#link|packed union#} which have |
| 2426 | guaranteed in-memory layout. | 2426 | guaranteed in-memory layout. |
| 2427 | {#link|Accessing the non-active field|Wrong Union Field Access#} is | 2427 | {#link|Accessing the non-active field|Wrong Union Field Access#} is |
| 2428 | safety-checked {#link|Undefined Behavior#}: | 2428 | safety-checked {#link|Illegal Behavior#}: |
| 2429 | </p> | 2429 | </p> |
| 2430 | {#code|test_wrong_union_access.zig#} | 2430 | {#code|test_wrong_union_access.zig#} |
| 2431 | | 2431 | |
| ... | @@ -3023,11 +3023,11 @@ or | ... | @@ -3023,11 +3023,11 @@ or |
| 3023 | {#syntax#}const number = parseU64("1234", 10) catch unreachable;{#endsyntax#} | 3023 | {#syntax#}const number = parseU64("1234", 10) catch unreachable;{#endsyntax#} |
| 3024 | <p> | 3024 | <p> |
| 3025 | Here we know for sure that "1234" will parse successfully. So we put the | 3025 | Here we know for sure that "1234" will parse successfully. So we put the |
| 3026 | {#syntax#}unreachable{#endsyntax#} value on the right hand side. {#syntax#}unreachable{#endsyntax#} generates | 3026 | {#syntax#}unreachable{#endsyntax#} value on the right hand side. |
| 3027 | a panic in {#link|Debug#} and {#link|ReleaseSafe#} modes and undefined behavior in | 3027 | {#syntax#}unreachable{#endsyntax#} invokes safety-checked {#link|Illegal Behavior#}, so |
| 3028 | {#link|ReleaseFast#} and {#link|ReleaseSmall#} modes. So, while we're debugging the | 3028 | in {#link|Debug#} and {#link|ReleaseSafe#}, triggers a safety panic by default. So, while |
| 3029 | application, if there <em>was</em> a surprise error here, the application would crash | 3029 | we're debugging the application, if there <em>was</em> a surprise error here, the application |
| 3030 | appropriately. | 3030 | would crash appropriately. |
| 3031 | </p> | 3031 | </p> |
| 3032 | <p> | 3032 | <p> |
| 3033 | You may want to take a different action for every situation. For that, we combine | 3033 | You may want to take a different action for every situation. For that, we combine |
| ... | @@ -4034,7 +4034,7 @@ fn performFn(start_value: i32) i32 { | ... | @@ -4034,7 +4034,7 @@ fn performFn(start_value: i32) i32 { |
| 4034 | </p> | 4034 | </p> |
| 4035 | <p> | 4035 | <p> |
| 4036 | Luckily, we used an unsigned integer, and so when we tried to subtract 1 from 0, it triggered | 4036 | Luckily, we used an unsigned integer, and so when we tried to subtract 1 from 0, it triggered |
| 4037 | undefined behavior, which is always a compile error if the compiler knows it happened. | 4037 | {#link|Illegal Behavior#}, which is always a compile error if the compiler knows it happened. |
| 4038 | But what would have happened if we used a signed integer? | 4038 | But what would have happened if we used a signed integer? |
| 4039 | </p> | 4039 | </p> |
| 4040 | {#code|fibonacci_comptime_infinite_recursion.zig#} | 4040 | {#code|fibonacci_comptime_infinite_recursion.zig#} |
| ... | @@ -4239,7 +4239,7 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void { | ... | @@ -4239,7 +4239,7 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void { |
| 4239 | </p> | 4239 | </p> |
| 4240 | <p> | 4240 | <p> |
| 4241 | Failure to declare the full set of clobbers for a given inline assembly | 4241 | Failure to declare the full set of clobbers for a given inline assembly |
| 4242 | expression is unchecked {#link|Undefined Behavior#}. | 4242 | expression is unchecked {#link|Illegal Behavior#}. |
| 4243 | </p> | 4243 | </p> |
| 4244 | {#header_close#} | 4244 | {#header_close#} |
| 4245 | | 4245 | |
| ... | @@ -4805,7 +4805,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -4805,7 +4805,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 4805 | </p> | 4805 | </p> |
| 4806 | <p> | 4806 | <p> |
| 4807 | Attempting to convert an integer with no corresponding value in the enum invokes | 4807 | Attempting to convert an integer with no corresponding value in the enum invokes |
| 4808 | safety-checked {#link|Undefined Behavior#}. | 4808 | safety-checked {#link|Illegal Behavior#}. |
| 4809 | Note that a {#link|non-exhaustive enum|Non-exhaustive enum#} has corresponding values for all | 4809 | Note that a {#link|non-exhaustive enum|Non-exhaustive enum#} has corresponding values for all |
| 4810 | integers in the enum's integer tag type: the {#syntax#}_{#endsyntax#} value represents all | 4810 | integers in the enum's integer tag type: the {#syntax#}_{#endsyntax#} value represents all |
| 4811 | the remaining unnamed integers in the enum's tag type. | 4811 | the remaining unnamed integers in the enum's tag type. |
| ... | @@ -4824,7 +4824,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -4824,7 +4824,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 4824 | </p> | 4824 | </p> |
| 4825 | <p> | 4825 | <p> |
| 4826 | Attempting to convert an integer that does not correspond to any error results in | 4826 | Attempting to convert an integer that does not correspond to any error results in |
| 4827 | safety-protected {#link|Undefined Behavior#}. | 4827 | safety-checked {#link|Illegal Behavior#}. |
| 4828 | </p> | 4828 | </p> |
| 4829 | {#see_also|@intFromError#} | 4829 | {#see_also|@intFromError#} |
| 4830 | {#header_close#} | 4830 | {#header_close#} |
| ... | @@ -4856,7 +4856,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -4856,7 +4856,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 4856 | <p> | 4856 | <p> |
| 4857 | Converts an error set or error union value from one error set to another error set. The return type is the | 4857 | Converts an error set or error union value from one error set to another error set. The return type is the |
| 4858 | 			inferred result type. Attempting to convert an error which is not in the destination error | 4858 | 			inferred result type. Attempting to convert an error which is not in the destination error |
| 4859 | 			set results in safety-protected {#link|Undefined Behavior#}. | 4859 | 			set results in safety-checked {#link|Illegal Behavior#}. |
| 4860 | </p> | 4860 | </p> |
| 4861 | {#header_close#} | 4861 | {#header_close#} |
| 4862 | | 4862 | |
| ... | @@ -4907,7 +4907,12 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -4907,7 +4907,12 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 4907 | {#header_open|@fieldParentPtr#} | 4907 | {#header_open|@fieldParentPtr#} |
| 4908 | <pre>{#syntax#}@fieldParentPtr(comptime field_name: []const u8, field_ptr: *T) anytype{#endsyntax#}</pre> | 4908 | <pre>{#syntax#}@fieldParentPtr(comptime field_name: []const u8, field_ptr: *T) anytype{#endsyntax#}</pre> |
| 4909 | <p> | 4909 | <p> |
| 4910 | Given a pointer to a field, returns the base pointer of a struct. | 4910 | Given a pointer to a struct field, returns a pointer to the struct containing that field. |
| | 4911 | The return type (and struct in question) is the inferred result type. |
| | 4912 | </p> |
| | 4913 | <p> |
| | 4914 | If {#syntax#}field_ptr{#endsyntax#} does not point to the {#syntax#}field_name{#endsyntax#} field of an instance of |
| | 4915 | the result type, and the result type has ill-defined layout, invokes unchecked {#link|Illegal Behavior#}. |
| 4911 | </p> | 4916 | </p> |
| 4912 | {#header_close#} | 4917 | {#header_close#} |
| 4913 | | 4918 | |
| ... | @@ -5024,7 +5029,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5024,7 +5029,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5024 | Converts an integer to another integer while keeping the same numerical value. | 5029 | Converts an integer to another integer while keeping the same numerical value. |
| 5025 | 			The return type is the inferred result type. | 5030 | 			The return type is the inferred result type. |
| 5026 | Attempting to convert a number which is out of range of the destination type results in | 5031 | Attempting to convert a number which is out of range of the destination type results in |
| 5027 | safety-protected {#link|Undefined Behavior#}. | 5032 | safety-checked {#link|Illegal Behavior#}. |
| 5028 | </p> | 5033 | </p> |
| 5029 | {#code|test_intCast_builtin.zig#} | 5034 | {#code|test_intCast_builtin.zig#} |
| 5030 | | 5035 | |
| ... | @@ -5085,7 +5090,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5085,7 +5090,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5085 | </p> | 5090 | </p> |
| 5086 | <p> | 5091 | <p> |
| 5087 | If the integer part of the floating point number cannot fit in the destination type, | 5092 | If the integer part of the floating point number cannot fit in the destination type, |
| 5088 | it invokes safety-checked {#link|Undefined Behavior#}. | 5093 | it invokes safety-checked {#link|Illegal Behavior#}. |
| 5089 | </p> | 5094 | </p> |
| 5090 | {#see_also|@floatFromInt#} | 5095 | {#see_also|@floatFromInt#} |
| 5091 | {#header_close#} | 5096 | {#header_close#} |
| ... | @@ -5217,7 +5222,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5217,7 +5222,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5217 | <li>From library code, calling the programmer's panic function if they exposed one in the root source file.</li> | 5222 | <li>From library code, calling the programmer's panic function if they exposed one in the root source file.</li> |
| 5218 | <li>When mixing C and Zig code, calling the canonical panic implementation across multiple .o files.</li> | 5223 | <li>When mixing C and Zig code, calling the canonical panic implementation across multiple .o files.</li> |
| 5219 | </ul> | 5224 | </ul> |
| 5220 | {#see_also|Root Source File#} | 5225 | {#see_also|Panic Handler#} |
| 5221 | {#header_close#} | 5226 | {#header_close#} |
| 5222 | | 5227 | |
| 5223 | {#header_open|@popCount#} | 5228 | {#header_open|@popCount#} |
| ... | @@ -5245,7 +5250,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5245,7 +5250,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5245 | <p> | 5250 | <p> |
| 5246 | The {#syntax#}ptr{#endsyntax#} argument may be any pointer type and determines the memory | 5251 | The {#syntax#}ptr{#endsyntax#} argument may be any pointer type and determines the memory |
| 5247 | address to prefetch. This function does not dereference the pointer, it is perfectly legal | 5252 | address to prefetch. This function does not dereference the pointer, it is perfectly legal |
| 5248 | to pass a pointer to invalid memory to this function and no illegal behavior will result. | 5253 | to pass a pointer to invalid memory to this function and no Illegal Behavior will result. |
| 5249 | </p> | 5254 | </p> |
| 5250 | <p>{#syntax#}PrefetchOptions{#endsyntax#} can be found with {#syntax#}@import("std").builtin.PrefetchOptions{#endsyntax#}.</p> | 5255 | <p>{#syntax#}PrefetchOptions{#endsyntax#} can be found with {#syntax#}@import("std").builtin.PrefetchOptions{#endsyntax#}.</p> |
| 5251 | {#header_close#} | 5256 | {#header_close#} |
| ... | @@ -5257,7 +5262,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5257,7 +5262,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5257 | </p> | 5262 | </p> |
| 5258 | <p> | 5263 | <p> |
| 5259 | {#link|Optional Pointers#} are allowed. Casting an optional pointer which is {#link|null#} | 5264 | {#link|Optional Pointers#} are allowed. Casting an optional pointer which is {#link|null#} |
| 5260 | to a non-optional pointer invokes safety-checked {#link|Undefined Behavior#}. | 5265 | to a non-optional pointer invokes safety-checked {#link|Illegal Behavior#}. |
| 5261 | </p> | 5266 | </p> |
| 5262 | <p> | 5267 | <p> |
| 5263 | {#syntax#}@ptrCast{#endsyntax#} cannot be used for: | 5268 | {#syntax#}@ptrCast{#endsyntax#} cannot be used for: |
| ... | @@ -5281,7 +5286,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5281,7 +5286,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5281 | </p> | 5286 | </p> |
| 5282 | <p> | 5287 | <p> |
| 5283 | If the destination pointer type does not allow address zero and {#syntax#}address{#endsyntax#} | 5288 | If the destination pointer type does not allow address zero and {#syntax#}address{#endsyntax#} |
| 5284 | is zero, this invokes safety-checked {#link|Undefined Behavior#}. | 5289 | is zero, this invokes safety-checked {#link|Illegal Behavior#}. |
| 5285 | </p> | 5290 | </p> |
| 5286 | {#header_close#} | 5291 | {#header_close#} |
| 5287 | | 5292 | |
| ... | @@ -5356,8 +5361,8 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5356,8 +5361,8 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5356 | <li> | 5361 | <li> |
| 5357 | {#syntax#}Optimized{#endsyntax#} - Floating point operations may do all of the following: | 5362 | {#syntax#}Optimized{#endsyntax#} - Floating point operations may do all of the following: |
| 5358 | <ul> | 5363 | <ul> |
| 5359 | <li>Assume the arguments and result are not NaN. Optimizations are required to retain defined behavior over NaNs, but the value of the result is undefined.</li> | 5364 | <li>Assume the arguments and result are not NaN. Optimizations are required to retain legal behavior over NaNs, but the value of the result is undefined.</li> |
| 5360 | <li>Assume the arguments and result are not +/-Inf. Optimizations are required to retain defined behavior over +/-Inf, but the value of the result is undefined.</li> | 5365 | <li>Assume the arguments and result are not +/-Inf. Optimizations are required to retain legal behavior over +/-Inf, but the value of the result is undefined.</li> |
| 5361 | <li>Treat the sign of a zero argument or result as insignificant.</li> | 5366 | <li>Treat the sign of a zero argument or result as insignificant.</li> |
| 5362 | <li>Use the reciprocal of an argument rather than perform division.</li> | 5367 | <li>Use the reciprocal of an argument rather than perform division.</li> |
| 5363 | <li>Perform floating-point contraction (e.g. fusing a multiply followed by an addition into a fused multiply-add).</li> | 5368 | <li>Perform floating-point contraction (e.g. fusing a multiply followed by an addition into a fused multiply-add).</li> |
| ... | @@ -5396,7 +5401,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5396,7 +5401,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5396 | </p> | 5401 | </p> |
| 5397 | <p> | 5402 | <p> |
| 5398 | The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(@typeInfo(T).int.bits){#endsyntax#} bits. | 5403 | The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(@typeInfo(T).int.bits){#endsyntax#} bits. |
| 5399 | This is because {#syntax#}shift_amt >= @typeInfo(T).int.bits{#endsyntax#} is undefined behavior. | 5404 | This is because {#syntax#}shift_amt >= @typeInfo(T).int.bits{#endsyntax#} triggers safety-checked {#link|Illegal Behavior#}. |
| 5400 | </p> | 5405 | </p> |
| 5401 | <p> | 5406 | <p> |
| 5402 | {#syntax#}comptime_int{#endsyntax#} is modeled as an integer with an infinite number of bits, | 5407 | {#syntax#}comptime_int{#endsyntax#} is modeled as an integer with an infinite number of bits, |
| ... | @@ -5413,7 +5418,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5413,7 +5418,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5413 | </p> | 5418 | </p> |
| 5414 | <p> | 5419 | <p> |
| 5415 | The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(@typeInfo(@TypeOf(a)).int.bits){#endsyntax#} bits. | 5420 | The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(@typeInfo(@TypeOf(a)).int.bits){#endsyntax#} bits. |
| 5416 | This is because {#syntax#}shift_amt >= @typeInfo(@TypeOf(a)).int.bits{#endsyntax#} is undefined behavior. | 5421 | This is because {#syntax#}shift_amt >= @typeInfo(@TypeOf(a)).int.bits{#endsyntax#} triggers safety-checked {#link|Illegal Behavior#}. |
| 5417 | </p> | 5422 | </p> |
| 5418 | {#see_also|@shlExact|@shrExact#} | 5423 | {#see_also|@shlExact|@shrExact#} |
| 5419 | {#header_close#} | 5424 | {#header_close#} |
| ... | @@ -5426,7 +5431,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5426,7 +5431,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5426 | </p> | 5431 | </p> |
| 5427 | <p> | 5432 | <p> |
| 5428 | The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(@typeInfo(T).int.bits){#endsyntax#} bits. | 5433 | The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(@typeInfo(T).int.bits){#endsyntax#} bits. |
| 5429 | This is because {#syntax#}shift_amt >= @typeInfo(T).int.bits{#endsyntax#} is undefined behavior. | 5434 | This is because {#syntax#}shift_amt >= @typeInfo(T).int.bits{#endsyntax#} triggers safety-checked {#link|Illegal Behavior#}. |
| 5430 | </p> | 5435 | </p> |
| 5431 | {#see_also|@shlExact|@shlWithOverflow#} | 5436 | {#see_also|@shlExact|@shlWithOverflow#} |
| 5432 | {#header_close#} | 5437 | {#header_close#} |
| ... | @@ -5701,7 +5706,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5701,7 +5706,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5701 | {#header_open|@tagName#} | 5706 | {#header_open|@tagName#} |
| 5702 | <pre>{#syntax#}@tagName(value: anytype) [:0]const u8{#endsyntax#}</pre> | 5707 | <pre>{#syntax#}@tagName(value: anytype) [:0]const u8{#endsyntax#}</pre> |
| 5703 | <p> | 5708 | <p> |
| 5704 | Converts an enum value or union value to a string literal representing the name.</p><p>If the enum is non-exhaustive and the tag value does not map to a name, it invokes safety-checked {#link|Undefined Behavior#}. | 5709 | Converts an enum value or union value to a string literal representing the name.</p><p>If the enum is non-exhaustive and the tag value does not map to a name, it invokes safety-checked {#link|Illegal Behavior#}. |
| 5705 | </p> | 5710 | </p> |
| 5706 | {#header_close#} | 5711 | {#header_close#} |
| 5707 | | 5712 | |
| ... | @@ -5938,7 +5943,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5938,7 +5943,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5938 | <li>Reproducible build</li> | 5943 | <li>Reproducible build</li> |
| 5939 | </ul> | 5944 | </ul> |
| 5940 | {#header_close#} | 5945 | {#header_close#} |
| 5941 | {#see_also|Compile Variables|Zig Build System|Undefined Behavior#} | 5946 | {#see_also|Compile Variables|Zig Build System|Illegal Behavior#} |
| 5942 | {#header_close#} | 5947 | {#header_close#} |
| 5943 | | 5948 | |
| 5944 | {#header_open|Single Threaded Builds#} | 5949 | {#header_open|Single Threaded Builds#} |
| ... | @@ -5953,20 +5958,36 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5953,20 +5958,36 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5953 | </ul> | 5958 | </ul> |
| 5954 | {#header_close#} | 5959 | {#header_close#} |
| 5955 | | 5960 | |
| 5956 | {#header_open|Undefined Behavior#} | 5961 | {#header_open|Illegal Behavior#} |
| | 5962 | <p> |
| | 5963 | Many operations in Zig trigger what is known as "Illegal Behavior" (IB). If Illegal Behavior is detected at |
| | 5964 | compile-time, Zig emits a compile error and refuses to continue. Otherwise, when Illegal Behavior is not caught |
| | 5965 | at compile-time, it falls into one of two categories. |
| | 5966 | </p> |
| | 5967 | <p> |
| | 5968 | Some Illegal Behavior is <em>safety-checked</em>: this means that the compiler will insert "safety checks" |
| | 5969 | anywhere that the Illegal Behavior may occur at runtime, to determine whether it is about to happen. If it |
| | 5970 | is, the safety check "fails", which triggers a panic. |
| | 5971 | </p> |
| | 5972 | <p> |
| | 5973 | All other Illegal Behavior is <em>unchecked</em>, meaning the compiler is unable to insert safety checks for |
| | 5974 | it. If Unchecked Illegal Behavior is invoked at runtime, anything can happen: usually that will be some kind of |
| | 5975 | crash, but the optimizer is free to make Unchecked Illegal Behavior do anything, such as calling arbitrary functions |
| | 5976 | or clobbering arbitrary data. This is similar to the concept of "undefined behavior" in some other languages. Note that |
| | 5977 | Unchecked Illegal Behavior still always results in a compile error if evaluated at {#link|comptime#}, because the Zig |
| | 5978 | compiler is able to perform more sophisticated checks at compile-time than at runtime. |
| | 5979 | </p> |
| 5957 | <p> | 5980 | <p> |
| 5958 | Zig has many instances of undefined behavior. If undefined behavior is | 5981 | Most Illegal Behavior is safety-checked. However, to facilitate optimizations, safety checks are disabled by default |
| 5959 | detected at compile-time, Zig emits a compile error and refuses to continue. | 5982 | in the {#link|ReleaseFast#} and {#link|ReleaseSmall#} optimization modes. Safety checks can also be enabled or disabled |
| 5960 | Most undefined behavior that cannot be detected at compile-time can be detected | 5983 | on a per-block basis, overriding the default for the current optimization mode, using {#link|@setRuntimeSafety#}. When |
| 5961 | at runtime. In these cases, Zig has safety checks. Safety checks can be disabled | 5984 | safety checks are disabled, Safety-Checked Illegal Behavior behaves like Unchecked Illegal Behavior; that is, any behavior |
| 5962 | on a per-block basis with {#link|@setRuntimeSafety#}. The {#link|ReleaseFast#} | 5985 | may result from invoking it. |
| 5963 | and {#link|ReleaseSmall#} build modes disable all safety checks (except where overridden | | |
| 5964 | by {#link|@setRuntimeSafety#}) in order to facilitate optimizations. | | |
| 5965 | </p> | 5986 | </p> |
| 5966 | <p> | 5987 | <p> |
| 5967 | When a safety check fails, Zig crashes with a stack trace, like this: | 5988 | When a safety check fails, Zig's default panic handler crashes with a stack trace, like this: |
| 5968 | </p> | 5989 | </p> |
| 5969 | {#code|test_undefined_behavior.zig#} | 5990 | {#code|test_illegal_behavior.zig#} |
| 5970 | | 5991 | |
| 5971 | {#header_open|Reaching Unreachable Code#} | 5992 | {#header_open|Reaching Unreachable Code#} |
| 5972 | <p>At compile-time:</p> | 5993 | <p>At compile-time:</p> |
| ... | @@ -6332,7 +6353,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -6332,7 +6353,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 6332 | <p> | 6353 | <p> |
| 6333 | {#syntax#}var{#endsyntax#} declarations inside functions are stored in the function's stack frame. Once a function returns, | 6354 | {#syntax#}var{#endsyntax#} declarations inside functions are stored in the function's stack frame. Once a function returns, |
| 6334 | any {#link|Pointers#} to variables in the function's stack frame become invalid references, and | 6355 | any {#link|Pointers#} to variables in the function's stack frame become invalid references, and |
| 6335 | dereferencing them becomes unchecked {#link|Undefined Behavior#}. | 6356 | dereferencing them becomes unchecked {#link|Illegal Behavior#}. |
| 6336 | </p> | 6357 | </p> |
| 6337 | <p> | 6358 | <p> |
| 6338 | {#syntax#}var{#endsyntax#} declarations at the top level or in {#link|struct#} declarations are stored in the global | 6359 | {#syntax#}var{#endsyntax#} declarations at the top level or in {#link|struct#} declarations are stored in the global |
| ... | @@ -6440,7 +6461,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -6440,7 +6461,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 6440 | The API documentation for functions and data structures should take great care to explain | 6461 | The API documentation for functions and data structures should take great care to explain |
| 6441 | the ownership and lifetime semantics of pointers. Ownership determines whose responsibility it | 6462 | the ownership and lifetime semantics of pointers. Ownership determines whose responsibility it |
| 6442 | is to free the memory referenced by the pointer, and lifetime determines the point at which | 6463 | is to free the memory referenced by the pointer, and lifetime determines the point at which |
| 6443 | the memory becomes inaccessible (lest {#link|Undefined Behavior#} occur). | 6464 | the memory becomes inaccessible (lest {#link|Illegal Behavior#} occur). |
| 6444 | </p> | 6465 | </p> |
| 6445 | {#header_close#} | 6466 | {#header_close#} |
| 6446 | | 6467 | |
| ... | @@ -6459,14 +6480,155 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -6459,14 +6480,155 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 6459 | {#builtin#} | 6480 | {#builtin#} |
| 6460 | {#see_also|Build Mode#} | 6481 | {#see_also|Build Mode#} |
| 6461 | {#header_close#} | 6482 | {#header_close#} |
| 6462 | {#header_open|Root Source File#} | 6483 | {#header_open|Compilation Model#} |
| 6463 | <p>TODO: explain how root source file finds other files</p> | 6484 | <p> |
| 6464 | <p>TODO: pub fn main</p> | 6485 | A Zig compilation is separated into <em>modules</em>. Each module is a collection of Zig source files, |
| 6465 | <p>TODO: pub fn panic</p> | 6486 | one of which is the module's <em>root source file</em>. Each module can <em>depend</em> on any number of |
| 6466 | <p>TODO: if linking with libc you can use export fn main</p> | 6487 | other modules, forming a directed graph (dependency loops between modules are allowed). If module A |
| 6467 | <p>TODO: order independent top level declarations</p> | 6488 | depends on module B, then any Zig source file in module A can import the <em>root source file</em> of |
| 6468 | <p>TODO: lazy analysis</p> | 6489 | module B using {#syntax#}@import{#endsyntax#} with the module's name. In essence, a module acts as an |
| 6469 | <p>TODO: using comptime { _ = @import() }</p> | 6490 | alias to import a Zig source file (which might exist in a completely separate part of the filesystem). |
| | 6491 | </p> |
| | 6492 | <p> |
| | 6493 | A simple Zig program compiled with <code>zig build-exe</code> has two key modules: the one containing your |
| | 6494 | code, known as the "main" or "root" module, and the standard library. Your module <em>depends on</em> |
| | 6495 | the standard library module under the name "std", which is what allows you to write |
| | 6496 | {#syntax#}@import("std"){#endsyntax#}! In fact, every single module in a Zig compilation &mdash; including |
| | 6497 | the standard library itself &mdash; implicitly depends on the standard library module under the name "std". |
| | 6498 | </p> |
| | 6499 | <p> |
| | 6500 | The "root module" (the one provided by you in the <code>zig build-exe</code> example) has a special |
| | 6501 | property. Like the standard library, it is implicitly made available to all modules (including itself), |
| | 6502 | this time under the name "root". So, {#syntax#}@import("root"){#endsyntax#} will always be equivalent to |
| | 6503 | {#syntax#}@import{#endsyntax#} of your "main" source file (often, but not necessarily, named |
| | 6504 | <code>main.zig</code>). |
| | 6505 | </p> |
| | 6506 | {#header_open|Source File Structs#} |
| | 6507 | <p> |
| | 6508 | Every Zig source file is implicitly a {#syntax#}struct{#endsyntax#} declaration; you can imagine that |
| | 6509 | the file's contents are literally surrounded by {#syntax#}struct { ... }{#endsyntax#}. This means that |
| | 6510 | as well as declarations, the top level of a file is permitted to contain fields: |
| | 6511 | </p> |
| | 6512 | {#code|TopLevelFields.zig#} |
| | 6513 | <p> |
| | 6514 | Such files can be instantiated just like any other {#syntax#}struct{#endsyntax#} type. A file's "root |
| | 6515 | struct type" can be referred to within that file using {#link|@This#}. |
| | 6516 | </p> |
| | 6517 | {#header_close#} |
| | 6518 | {#header_open|File and Declaration Discovery#} |
| | 6519 | <p> |
| | 6520 | Zig places importance on the concept of whether any piece of code is <em>semantically analyzed</em>; in |
| | 6521 | essence, whether the compiler "looks at" it. What code is analyzed is based on what files and |
| | 6522 | declarations are "discovered" from a certain point. This process of "discovery" is based on a simple set |
| | 6523 | of recursive rules: |
| | 6524 | </p> |
| | 6525 | <ul> |
| | 6526 | <li>If a call to {#syntax#}@import{#endsyntax#} is analyzed, the file being imported is analyzed.</li> |
| | 6527 | <li>If a type (including a file) is analyzed, all {#syntax#}comptime{#endsyntax#}, {#syntax#}usingnamespace{#endsyntax#}, and {#syntax#}export{#endsyntax#} declarations within it are analyzed.</li> |
| | 6528 | <li>If a type (including a file) is analyzed, and the compilation is for a {#link|test|Zig Test#}, and the module the type is within is the root module of the compilation, then all {#syntax#}test{#endsyntax#} declarations within it are also analyzed.</li> |
| | 6529 | <li>If a reference to a named declaration (i.e. a usage of it) is analyzed, the declaration being referenced is analyzed. Declarations are order-independent, so this reference may be above or below the declaration being referenced, or even in another file entirely.</li> |
| | 6530 | </ul> |
| | 6531 | <p> |
| | 6532 | That's it! Those rules define how Zig files and declarations are discovered. All that remains is to |
| | 6533 | understand where this process <em>starts</em>. |
| | 6534 | </p> |
| | 6535 | <p> |
| | 6536 | The answer to that is the root of the standard library: every Zig compilation begins by analyzing the |
| | 6537 | file <code>lib/std/std.zig</code>. This file contains a {#syntax#}comptime{#endsyntax#} declaration |
| | 6538 | which imports {#syntax#}lib/std/start.zig{#endsyntax#}, and that file in turn uses |
| | 6539 | {#syntax#}@import("root"){#endsyntax#} to reference the "root module"; so, the file you provide as your |
| | 6540 | main module's root source file is effectively also a root, because the standard library will always |
| | 6541 | reference it. |
| | 6542 | </p> |
| | 6543 | <p> |
| | 6544 | It is often desirable to make sure that certain declarations &mdash; particularly {#syntax#}test{#endsyntax#} |
| | 6545 | or {#syntax#}export{#endsyntax#} declarations &mdash; are discovered. Based on the above rules, a common |
| | 6546 | strategy for this is to use {#syntax#}@import{#endsyntax#} within a {#syntax#}comptime{#endsyntax#} or |
| | 6547 | {#syntax#}test{#endsyntax#} block: |
| | 6548 | </p> |
| | 6549 | {#syntax_block|zig|force_file_discovery.zig#} |
| | 6550 | comptime { |
| | 6551 | // This will ensure that the file 'api.zig' is always discovered (as long as this file is discovered). |
| | 6552 | // It is useful if 'api.zig' contains important exported declarations. |
| | 6553 | _ = @import("api.zig"); |
| | 6554 | |
| | 6555 | // We could also have a file which contains declarations we only want to export depending on a comptime |
| | 6556 | // condition. In that case, we can use an `if` statement here: |
| | 6557 | if (builtin.os.tag == .windows) { |
| | 6558 | _ = @import("windows_api.zig"); |
| | 6559 | } |
| | 6560 | } |
| | 6561 | |
| | 6562 | test { |
| | 6563 | // This will ensure that the file 'tests.zig' is always discovered (as long as this file is discovered), |
| | 6564 | // if this compilation is a test. It is useful if 'tests.zig' contains tests we want to ensure are run. |
| | 6565 | _ = @import("tests.zig"); |
| | 6566 | |
| | 6567 | // We could also have a file which contains tests we only want to run depending on a comptime condition. |
| | 6568 | // In that case, we can use an `if` statement here: |
| | 6569 | if (builtin.os.tag == .windows) { |
| | 6570 | _ = @import("windows_tests.zig"); |
| | 6571 | } |
| | 6572 | } |
| | 6573 | |
| | 6574 | const builtin = @import("builtin"); |
| | 6575 | {#end_syntax_block#} |
| | 6576 | {#header_close#} |
| | 6577 | {#header_open|Special Root Declarations#} |
| | 6578 | <p> |
| | 6579 | Because the root module's root source file is always accessible using |
| | 6580 | {#syntax#}@import("root"){#endsyntax#}, is is sometimes used by libraries &mdash; including the Zig Standard |
| | 6581 | Library &mdash; as a place for the program to expose some "global" information to that library. The Zig |
| | 6582 | Standard Library will look for several declarations in this file. |
| | 6583 | </p> |
| | 6584 | {#header_open|Entry Point#} |
| | 6585 | <p> |
| | 6586 | When building an executable, the most important thing to be looked up in this file is the program's |
| | 6587 | <em>entry point</em>. Most commonly, this is a function named {#syntax#}main{#endsyntax#}, which |
| | 6588 | {#syntax#}std.start{#endsyntax#} will call just after performing important initialization work. |
| | 6589 | </p> |
| | 6590 | <p> |
| | 6591 | Alternatively, the presence of a declaration named {#syntax#}_start{#endsyntax#} (for instance, |
| | 6592 | {#syntax#}pub const _start = {};{#endsyntax#}) will disable the default {#syntax#}std.start{#endsyntax#} |
| | 6593 | logic, allowing your root source file to export a low-level entry point as needed. |
| | 6594 | </p> |
| | 6595 | {#code|entry_point.zig#} |
| | 6596 | <p> |
| | 6597 | If the Zig compilation links libc, the {#syntax#}main{#endsyntax#} function can optionally be an |
| | 6598 | {#syntax#}export fn{#endsyntax#} which matches the signature of the C <code>main</code> function: |
| | 6599 | </p> |
| | 6600 | {#code|libc_export_entry_point.zig#} |
| | 6601 | <p> |
| | 6602 | {#syntax#}std.start{#endsyntax#} may also use other entry point declarations in certain situations, such |
| | 6603 | as {#syntax#}wWinMain{#endsyntax#} or {#syntax#}EfiMain{#endsyntax#}. Refer to the |
| | 6604 | {#syntax#}lib/std/start.zig{#endsyntax#} logic for details of these declarations. |
| | 6605 | </p> |
| | 6606 | {#header_close#} |
| | 6607 | {#header_open|Standard Library Options#} |
| | 6608 | <p> |
| | 6609 | The standard library also looks for a declaration in the root module's root source file named |
| | 6610 | {#syntax#}std_options{#endsyntax#}. If present, this declaration is expected to be a struct of type |
| | 6611 | {#syntax#}std.Options{#endsyntax#}, and allows the program to customize some standard library |
| | 6612 | functionality, such as the {#syntax#}std.log{#endsyntax#} implementation. |
| | 6613 | </p> |
| | 6614 | {#code|std_options.zig#} |
| | 6615 | {#header_close#} |
| | 6616 | {#header_open|Panic Handler#} |
| | 6617 | <p> |
| | 6618 | The Zig Standard Library looks for a declaration named {#syntax#}panic{#endsyntax#} in the root module's |
| | 6619 | root source file. If present, it is expected to be a namespace (container type) with declarations |
| | 6620 | providing different panic handlers. |
| | 6621 | </p> |
| | 6622 | <p> |
| | 6623 | See {#syntax#}std.debug.simple_panic{#endsyntax#} for a basic implementation of this namespace. |
| | 6624 | </p> |
| | 6625 | <p> |
| | 6626 | Overriding how the panic handler actually outputs messages, but keeping the formatted safety panics |
| | 6627 | which are enabled by default, can be easily achieved with {#syntax#}std.debug.FullPanic{#endsyntax#}: |
| | 6628 | </p> |
| | 6629 | {#code|panic_handler.zig#} |
| | 6630 | {#header_close#} |
| | 6631 | {#header_close#} |
| 6470 | {#header_close#} | 6632 | {#header_close#} |
| 6471 | {#header_open|Zig Build System#} | 6633 | {#header_open|Zig Build System#} |
| 6472 | <p> | 6634 | <p> |
| ... | @@ -6728,10 +6890,10 @@ int foo(void) { | ... | @@ -6728,10 +6890,10 @@ int foo(void) { |
| 6728 | <li>Supports all the syntax of the other two pointer types ({#syntax#}*T{#endsyntax#}) and ({#syntax#}[*]T{#endsyntax#}).</li> | 6890 | <li>Supports all the syntax of the other two pointer types ({#syntax#}*T{#endsyntax#}) and ({#syntax#}[*]T{#endsyntax#}).</li> |
| 6729 | <li>Coerces to other pointer types, as well as {#link|Optional Pointers#}. | 6891 | <li>Coerces to other pointer types, as well as {#link|Optional Pointers#}. |
| 6730 | When a C pointer is coerced to a non-optional pointer, safety-checked | 6892 | When a C pointer is coerced to a non-optional pointer, safety-checked |
| 6731 | {#link|Undefined Behavior#} occurs if the address is 0. | 6893 | {#link|Illegal Behavior#} occurs if the address is 0. |
| 6732 | </li> | 6894 | </li> |
| 6733 | <li>Allows address 0. On non-freestanding targets, dereferencing address 0 is safety-checked | 6895 | <li>Allows address 0. On non-freestanding targets, dereferencing address 0 is safety-checked |
| 6734 | {#link|Undefined Behavior#}. Optional C pointers introduce another bit to keep track of | 6896 | {#link|Illegal Behavior#}. Optional C pointers introduce another bit to keep track of |
| 6735 | null, just like {#syntax#}?usize{#endsyntax#}. Note that creating an optional C pointer | 6897 | null, just like {#syntax#}?usize{#endsyntax#}. Note that creating an optional C pointer |
| 6736 | is unnecessary as one can use normal {#link|Optional Pointers#}. | 6898 | is unnecessary as one can use normal {#link|Optional Pointers#}. |
| 6737 | </li> | 6899 | </li> |
| ... | @@ -7046,8 +7208,8 @@ fn readU32Be() u32 {} | ... | @@ -7046,8 +7208,8 @@ fn readU32Be() u32 {} |
| 7046 | <ul> | 7208 | <ul> |
| 7047 | <li>Omit any information that is redundant based on the name of the thing being documented.</li> | 7209 | <li>Omit any information that is redundant based on the name of the thing being documented.</li> |
| 7048 | <li>Duplicating information onto multiple similar functions is encouraged because it helps IDEs and other tools provide better help text.</li> | 7210 | <li>Duplicating information onto multiple similar functions is encouraged because it helps IDEs and other tools provide better help text.</li> |
| 7049 | <li>Use the word <strong>assume</strong> to indicate invariants that cause {#link|Undefined Behavior#} when violated.</li> | 7211 | <li>Use the word <strong>assume</strong> to indicate invariants that cause <em>unchecked</em> {#link|Illegal Behavior#} when violated.</li> |
| 7050 | <li>Use the word <strong>assert</strong> to indicate invariants that cause <em>safety-checked</em> {#link|Undefined Behavior#} when violated.</li> | 7212 | <li>Use the word <strong>assert</strong> to indicate invariants that cause <em>safety-checked</em> {#link|Illegal Behavior#} when violated.</li> |
| 7051 | </ul> | 7213 | </ul> |
| 7052 | {#header_close#} | 7214 | {#header_close#} |
| 7053 | {#header_close#} | 7215 | {#header_close#} |
| ... | @@ -7443,8 +7605,8 @@ fn readU32Be() u32 {} | ... | @@ -7443,8 +7605,8 @@ fn readU32Be() u32 {} |
| 7443 | In particular, inside a {#syntax#}nosuspend{#endsyntax#} scope: | 7605 | In particular, inside a {#syntax#}nosuspend{#endsyntax#} scope: |
| 7444 | <ul> | 7606 | <ul> |
| 7445 | <li>Using the {#syntax#}suspend{#endsyntax#} keyword results in a compile error.</li> | 7607 | <li>Using the {#syntax#}suspend{#endsyntax#} keyword results in a compile error.</li> |
| 7446 | <li>Using {#syntax#}await{#endsyntax#} on a function frame which hasn't completed yet results in safety-checked {#link|Undefined Behavior#}.</li> | 7608 | <li>Using {#syntax#}await{#endsyntax#} on a function frame which hasn't completed yet results in safety-checked {#link|Illegal Behavior#}.</li> |
| 7447 | <li>Calling an async function may result in safety-checked {#link|Undefined Behavior#}, because it's equivalent to <code>await async some_async_fn()</code>, which contains an {#syntax#}await{#endsyntax#}.</li> | 7609 | <li>Calling an async function may result in safety-checked {#link|Illegal Behavior#}, because it's equivalent to <code>await async some_async_fn()</code>, which contains an {#syntax#}await{#endsyntax#}.</li> |
| 7448 | </ul> | 7610 | </ul> |
| 7449 | Code inside a {#syntax#}nosuspend{#endsyntax#} scope does not cause the enclosing function to become an {#link|async function|Async Functions#}. | 7611 | Code inside a {#syntax#}nosuspend{#endsyntax#} scope does not cause the enclosing function to become an {#link|async function|Async Functions#}. |
| 7450 | <ul> | 7612 | <ul> |