diff --git a/doc/langref.html.in b/doc/langref.html.in index f55765b086..5b41bb8c73 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -1049,12 +1049,12 @@ {#header_close#} {#header_open|Runtime Integer Values#}
- Integer literals have no size limitation, and if any undefined behavior occurs, + Integer literals have no size limitation, and if any Illegal Behavior occurs, the compiler catches it.
However, once an integer value is no longer known at compile-time, it must have a - known size, and is vulnerable to undefined behavior. + known size, and is vulnerable to safety-checked {#link|Illegal Behavior#}.
{#code|runtime_vs_comptime.zig#} @@ -1064,7 +1064,7 @@ {#link|Division by Zero#}.- Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause undefined behavior on + Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause {#link|Illegal Behavior#} on integer overflow. Alternative operators are provided for wrapping and saturating arithmetic on all targets. {#syntax#}+%{#endsyntax#} and {#syntax#}-%{#endsyntax#} perform wrapping arithmetic while {#syntax#}+|{#endsyntax#} and {#syntax#}-|{#endsyntax#} perform saturating arithmetic. @@ -2029,7 +2029,7 @@ or
Slices have bounds checking and are therefore protected - against this kind of undefined behavior. This is one reason + against this kind of Illegal Behavior. This is one reason we prefer slices to pointers.
{#code|test_slice_bounds.zig#} @@ -2048,7 +2048,7 @@ or{#link|@ptrCast#} converts a pointer's element type to another. This - creates a new pointer that can cause undetectable illegal behavior + creates a new pointer that can cause undetectable Illegal Behavior depending on the loads and stores that pass through it. Generally, other kinds of type conversions are preferable to {#syntax#}@ptrCast{#endsyntax#} if possible. @@ -2164,7 +2164,7 @@ or
Sentinel-terminated slicing asserts that the element in the sentinel position of the backing data is - actually the sentinel value. If this is not the case, safety-protected {#link|Undefined Behavior#} results. + actually the sentinel value. If this is not the case, safety-checked {#link|Illegal Behavior#} results.
{#code|test_sentinel_mismatch.zig#} @@ -2425,7 +2425,7 @@ or or use an {#link|extern union#} or a {#link|packed union#} which have guaranteed in-memory layout. {#link|Accessing the non-active field|Wrong Union Field Access#} is - safety-checked {#link|Undefined Behavior#}: + safety-checked {#link|Illegal Behavior#}: {#code|test_wrong_union_access.zig#} @@ -3023,11 +3023,11 @@ or {#syntax#}const number = parseU64("1234", 10) catch unreachable;{#endsyntax#}Here we know for sure that "1234" will parse successfully. So we put the - {#syntax#}unreachable{#endsyntax#} value on the right hand side. {#syntax#}unreachable{#endsyntax#} generates - a panic in {#link|Debug#} and {#link|ReleaseSafe#} modes and undefined behavior in - {#link|ReleaseFast#} and {#link|ReleaseSmall#} modes. So, while we're debugging the - application, if there was a surprise error here, the application would crash - appropriately. + {#syntax#}unreachable{#endsyntax#} value on the right hand side. + {#syntax#}unreachable{#endsyntax#} invokes safety-checked {#link|Illegal Behavior#}, so + in {#link|Debug#} and {#link|ReleaseSafe#}, triggers a safety panic by default. So, while + we're debugging the application, if there was a surprise error here, the application + would crash appropriately.
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 {
Luckily, we used an unsigned integer, and so when we tried to subtract 1 from 0, it triggered - undefined behavior, which is always a compile error if the compiler knows it happened. + {#link|Illegal Behavior#}, which is always a compile error if the compiler knows it happened. But what would have happened if we used a signed integer?
{#code|fibonacci_comptime_infinite_recursion.zig#} @@ -4239,7 +4239,7 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void {Failure to declare the full set of clobbers for a given inline assembly - expression is unchecked {#link|Undefined Behavior#}. + expression is unchecked {#link|Illegal Behavior#}.
{#header_close#} @@ -4805,7 +4805,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_valAttempting to convert an integer with no corresponding value in the enum invokes - safety-checked {#link|Undefined Behavior#}. + safety-checked {#link|Illegal Behavior#}. Note that a {#link|non-exhaustive enum|Non-exhaustive enum#} has corresponding values for all integers in the enum's integer tag type: the {#syntax#}_{#endsyntax#} value represents all 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
Attempting to convert an integer that does not correspond to any error results in - safety-protected {#link|Undefined Behavior#}. + safety-checked {#link|Illegal Behavior#}.
{#see_also|@intFromError#} {#header_close#} @@ -4856,7 +4856,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_valConverts an error set or error union value from one error set to another error set. The return type is the inferred result type. Attempting to convert an error which is not in the destination error - set results in safety-protected {#link|Undefined Behavior#}. + set results in safety-checked {#link|Illegal Behavior#}.
{#header_close#} @@ -4912,7 +4912,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_valIf {#syntax#}field_ptr{#endsyntax#} does not point to the {#syntax#}field_name{#endsyntax#} field of an instance of - the result type, and the result type has ill-defined layout, invokes unchecked {#link|Undefined Behavior#}. + the result type, and the result type has ill-defined layout, invokes unchecked {#link|Illegal Behavior#}.
{#header_close#} @@ -5029,7 +5029,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val Converts an integer to another integer while keeping the same numerical value. The return type is the inferred result type. Attempting to convert a number which is out of range of the destination type results in - safety-protected {#link|Undefined Behavior#}. + safety-checked {#link|Illegal Behavior#}. {#code|test_intCast_builtin.zig#} @@ -5090,7 +5090,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_valIf the integer part of the floating point number cannot fit in the destination type, - it invokes safety-checked {#link|Undefined Behavior#}. + it invokes safety-checked {#link|Illegal Behavior#}.
{#see_also|@floatFromInt#} {#header_close#} @@ -5250,7 +5250,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_valThe {#syntax#}ptr{#endsyntax#} argument may be any pointer type and determines the memory address to prefetch. This function does not dereference the pointer, it is perfectly legal - to pass a pointer to invalid memory to this function and no illegal behavior will result. + to pass a pointer to invalid memory to this function and no Illegal Behavior will result.
{#syntax#}PrefetchOptions{#endsyntax#} can be found with {#syntax#}@import("std").builtin.PrefetchOptions{#endsyntax#}.
{#header_close#} @@ -5262,7 +5262,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val{#link|Optional Pointers#} are allowed. Casting an optional pointer which is {#link|null#} - to a non-optional pointer invokes safety-checked {#link|Undefined Behavior#}. + to a non-optional pointer invokes safety-checked {#link|Illegal Behavior#}.
{#syntax#}@ptrCast{#endsyntax#} cannot be used for: @@ -5286,7 +5286,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
If the destination pointer type does not allow address zero and {#syntax#}address{#endsyntax#} - is zero, this invokes safety-checked {#link|Undefined Behavior#}. + is zero, this invokes safety-checked {#link|Illegal Behavior#}.
{#header_close#} @@ -5361,8 +5361,8 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_valThe type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(@typeInfo(T).int.bits){#endsyntax#} bits. - This is because {#syntax#}shift_amt >= @typeInfo(T).int.bits{#endsyntax#} is undefined behavior. + This is because {#syntax#}shift_amt >= @typeInfo(T).int.bits{#endsyntax#} triggers safety-checked {#link|Illegal Behavior#}.
{#syntax#}comptime_int{#endsyntax#} is modeled as an integer with an infinite number of bits, @@ -5418,7 +5418,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(@typeInfo(@TypeOf(a)).int.bits){#endsyntax#} bits. - This is because {#syntax#}shift_amt >= @typeInfo(@TypeOf(a)).int.bits{#endsyntax#} is undefined behavior. + This is because {#syntax#}shift_amt >= @typeInfo(@TypeOf(a)).int.bits{#endsyntax#} triggers safety-checked {#link|Illegal Behavior#}.
{#see_also|@shlExact|@shrExact#} {#header_close#} @@ -5431,7 +5431,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_valThe type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(@typeInfo(T).int.bits){#endsyntax#} bits. - This is because {#syntax#}shift_amt >= @typeInfo(T).int.bits{#endsyntax#} is undefined behavior. + This is because {#syntax#}shift_amt >= @typeInfo(T).int.bits{#endsyntax#} triggers safety-checked {#link|Illegal Behavior#}.
{#see_also|@shlExact|@shlWithOverflow#} {#header_close#} @@ -5706,7 +5706,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val {#header_open|@tagName#}{#syntax#}@tagName(value: anytype) [:0]const u8{#endsyntax#}
- Converts an enum value or union value to a string literal representing the name.
If the enum is non-exhaustive and the tag value does not map to a name, it invokes safety-checked {#link|Undefined Behavior#}. + Converts an enum value or union value to a string literal representing the name.
If the enum is non-exhaustive and the tag value does not map to a name, it invokes safety-checked {#link|Illegal Behavior#}.
{#header_close#} @@ -5943,7 +5943,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val- Zig has many instances of undefined behavior. If undefined behavior is - detected at compile-time, Zig emits a compile error and refuses to continue. - Most undefined behavior that cannot be detected at compile-time can be detected - at runtime. In these cases, Zig has safety checks. Safety checks can be disabled - on a per-block basis with {#link|@setRuntimeSafety#}. The {#link|ReleaseFast#} - and {#link|ReleaseSmall#} build modes disable all safety checks (except where overridden - by {#link|@setRuntimeSafety#}) in order to facilitate optimizations. + Many operations in Zig trigger what is known as "Illegal Behavior" (IB). If Illegal Behavior is detected at + compile-time, Zig emits a compile error and refuses to continue. Otherwise, when Illegal Behavior is not caught + at compile-time, it falls into one of two categories.
- When a safety check fails, Zig crashes with a stack trace, like this: + Some Illegal Behavior is safety-checked: this means that the compiler will insert "safety checks" + anywhere that the Illegal Behavior may occur at runtime, to determine whether it is about to happen. If it + is, the safety check "fails", which triggers a panic.
- {#code|test_undefined_behavior.zig#} ++ All other Illegal Behavior is unchecked, meaning the compiler is unable to insert safety checks for + it. If Unchecked Illegal Behavior is invoked at runtime, anything can happen: usually that will be some kind of + crash, but the optimizer is free to make Unchecked Illegal Behavior do anything, such as calling arbitrary functions + or clobbering arbitrary data. This is similar to the concept of "undefined behavior" in some other languages. Note that + Unchecked Illegal Behavior still always results in a compile error if evaluated at {#link|comptime#}, because the Zig + compiler is able to perform more sophisticated checks at compile-time than at runtime. +
++ Most Illegal Behavior is safety-checked. However, to facilitate optimizations, safety checks are disabled by default + in the {#link|ReleaseFast#} and {#link|ReleaseSmall#} optimization modes. Safety checks can also be enabled or disabled + on a per-block basis, overriding the default for the current optimization mode, using {#link|@setRuntimeSafety#}. When + safety checks are disabled, Safety-Checked Illegal Behavior behaves like Unchecked Illegal Behavior; that is, any behavior + may result from invoking it. +
++ When a safety check fails, Zig's default panic handler crashes with a stack trace, like this: +
+ {#code|test_illegal_behavior.zig#} {#header_open|Reaching Unreachable Code#}At compile-time:
@@ -6337,7 +6353,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val{#syntax#}var{#endsyntax#} declarations inside functions are stored in the function's stack frame. Once a function returns, any {#link|Pointers#} to variables in the function's stack frame become invalid references, and - dereferencing them becomes unchecked {#link|Undefined Behavior#}. + dereferencing them becomes unchecked {#link|Illegal Behavior#}.
{#syntax#}var{#endsyntax#} declarations at the top level or in {#link|struct#} declarations are stored in the global @@ -6445,7 +6461,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val The API documentation for functions and data structures should take great care to explain the ownership and lifetime semantics of pointers. Ownership determines whose responsibility it is to free the memory referenced by the pointer, and lifetime determines the point at which - the memory becomes inaccessible (lest {#link|Undefined Behavior#} occur). + the memory becomes inaccessible (lest {#link|Illegal Behavior#} occur).
{#header_close#} @@ -6733,10 +6749,10 @@ int foo(void) {await async some_async_fn(), which contains an {#syntax#}await{#endsyntax#}.await async some_async_fn(), which contains an {#syntax#}await{#endsyntax#}.