From 00f42909adf23a92905aa7211d74ed5b5397b397 Mon Sep 17 00:00:00 2001
From: Pat Tullmann
The syntax {#syntax#}[N:x]T{#endsyntax#} describes an array which has a sentinel element of value {#syntax#}x{#endsyntax#} at the
- index corresponding to {#syntax#}len{#endsyntax#}.
+ index corresponding to the length {#syntax#}N{#endsyntax#}.
- A Non-exhaustive enum can be created by adding a trailing '_' field.
- It must specify a tag type and cannot consume every enumeration value.
+ A non-exhaustive enum can be created by adding a trailing {#syntax#}_{#endsyntax#} field.
+ The enum must specify a tag type and cannot consume every enumeration value.
{#link|@enumFromInt#} on a non-exhaustive enum involves the safety semantics
@@ -3822,8 +3829,8 @@ test "switch using enum literals" {
a well-defined enum value.
- A switch on a non-exhaustive enum can include a '_' prong as an alternative to an {#syntax#}else{#endsyntax#} prong
- with the difference being that it makes it a compile error if all the known tag names are not handled by the switch.
+ A switch on a non-exhaustive enum can include a {#syntax#}_{#endsyntax#} prong as an alternative to an {#syntax#}else{#endsyntax#} prong.
+ With a {#syntax#}_{#endsyntax#} prong the compiler errors if all the known tag names are not handled by the switch.
There is a difference between a function body and a function pointer.
@@ -6515,7 +6522,7 @@ test "coerce to optionals" {
try expect(y == null);
}
{#code_end#}
- It works nested inside the {#link|Error Union Type#}, too: Optionals work nested inside the {#link|Error Union Type#}, too:
- Expressions of type {#syntax#}void{#endsyntax#} are the only ones whose value can be ignored. For example: + Expressions of type {#syntax#}void{#endsyntax#} are the only ones whose value can be ignored. For example, ignoring + a non-{#syntax#}void{#endsyntax#} expression is a compile error:
{#code_begin|test_err|test_expression_ignored|ignored#} test "ignoring expression value" { @@ -6852,7 +6860,7 @@ fn foo() i32 { return 1234; } {#code_end#} -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#}.
+However, if the expression has type {#syntax#}void{#endsyntax#}, there will be no error. Expression results can be explicitly ignored by assigning them to {#syntax#}_{#endsyntax#}.
{#code_begin|test|test_void_ignored#} test "void is ignored" { returnsVoid(); @@ -7110,12 +7118,10 @@ fn performFn(start_value: i32) i32 { } {#end_syntax_block#}- Note that this happens even in a debug build; in a release build these generated functions still - pass through rigorous LLVM optimizations. The important thing to note, however, is not that this - is a way to write more optimized code, but that it is a way to make sure that what should happen - at compile-time, does happen at compile-time. This catches more errors and as demonstrated - later in this article, allows expressiveness that in other languages requires using macros, - generated code, or a preprocessor to accomplish. + Note that this happens even in a debug build. + This is not a way to write more optimized code, but it is a way to make sure that what should happen + at compile-time, does happen at compile-time. This catches more errors and allows expressiveness + that in other languages requires using macros, generated code, or a preprocessor to accomplish.
{#header_close#} {#header_open|Compile-Time Expressions#} @@ -7297,9 +7303,8 @@ test "variable values" { {#header_close#} {#header_open|Generic Data Structures#}- Zig uses these capabilities to implement generic data structures without introducing any - special-case syntax. If you followed along so far, you may already know how to create a - generic data structure. + Zig uses comptime capabilities to implement generic data structures without introducing any + special-case syntax.
Here is an example of a generic {#syntax#}List{#endsyntax#} data structure. @@ -7321,7 +7326,6 @@ var list = List(i32){ {#code_end#}
That's it. It's a function that returns an anonymous {#syntax#}struct{#endsyntax#}. - To keep the language small and uniform, all aggregate types in Zig are anonymous. For the purposes of error messages and debugging, Zig infers the name {#syntax#}"List(i32)"{#endsyntax#} from the function name and parameters invoked when creating the anonymous struct. @@ -7754,6 +7758,9 @@ test "global assembly" {
TODO: @fence()
TODO: @atomic rmw
TODO: builtin atomic memory ordering enum
+ + {#see_also|@atomicLoad|@atomicStore|@atomicRmw|@fence|@cmpxchgWeak|@cmpxchgStrong#} + {#header_close#} {#header_open|Async Functions#} @@ -7824,7 +7831,7 @@ comptime { {#header_open|@atomicLoad#}{#syntax#}@atomicLoad(comptime T: type, ptr: *const T, comptime ordering: builtin.AtomicOrder) T{#endsyntax#}
- This builtin function atomically dereferences a pointer and returns the value. + This builtin function atomically dereferences a pointer to a {#syntax#}T{#endsyntax#} and returns the value.
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, @@ -7836,14 +7843,15 @@ comptime { {#header_open|@atomicRmw#}
{#syntax#}@atomicRmw(comptime T: type, ptr: *T, comptime op: builtin.AtomicRmwOp, operand: T, comptime ordering: builtin.AtomicOrder) T{#endsyntax#}
- This builtin function atomically modifies memory and then returns the previous value. + This builtin function dereferences a pointer to a {#syntax#}T{#endsyntax#} and atomically + modifies the value and returns the previous value.
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, an integer or an enum.
- Supported operations: + Supported values for the {#syntax#}op{#endsyntax#} parameter:
{#syntax#}@atomicStore(comptime T: type, ptr: *T, value: T, comptime ordering: builtin.AtomicOrder) void{#endsyntax#}
- This builtin function atomically stores a value. + This builtin function dereferences a pointer to a {#syntax#}T{#endsyntax#} and atomically stores the given value.
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, @@ -8122,7 +8130,8 @@ pub const CallModifier = enum { {#header_open|@cmpxchgStrong#}
{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}
- This function performs a strong atomic compare exchange operation. It's the equivalent of this code, + This function performs a strong atomic compare-and-exchange operation, returning {#syntax#}null{#endsyntax#} + if the current value is not the given expected value. It's the equivalent of this code, except atomic:
{#code_begin|syntax|not_atomic_cmpxchgStrong#} @@ -8137,7 +8146,7 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v } {#code_end#}- If you are using cmpxchg in a loop, {#link|@cmpxchgWeak#} is the better choice, because it can be implemented + If you are using cmpxchg in a retry loop, {#link|@cmpxchgWeak#} is the better choice, because it can be implemented more efficiently in machine instructions.
@@ -8151,7 +8160,8 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v {#header_open|@cmpxchgWeak#}
{#syntax#}@cmpxchgWeak(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}
- This function performs a weak atomic compare exchange operation. It's the equivalent of this code, + This function performs a weak atomic compare-and-exchange operation, returning {#syntax#}null{#endsyntax#} + if the current value is not the given expected value. It's the equivalent of this code, except atomic:
{#syntax_block|zig|cmpxchgWeakButNotAtomic#} @@ -8166,7 +8176,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val } {#end_syntax_block#}- If you are using cmpxchg in a loop, the sporadic failure will be no problem, and {#syntax#}cmpxchgWeak{#endsyntax#} + If you are using cmpxchg in a retry loop, the sporadic failure will be no problem, and {#syntax#}cmpxchgWeak{#endsyntax#} is the better choice, because it can be implemented more efficiently in machine instructions. However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}.
@@ -8219,24 +8229,6 @@ const num1 = blk: { test "main" { @compileLog("comptime in main"); - print("Runtime in main, num1 = {}.\n", .{num1}); -} - {#code_end#} -- If all {#syntax#}@compileLog{#endsyntax#} calls are removed or - not encountered by analysis, the - program compiles successfully and the generated executable prints: -
- {#code_begin|test|test_without_compileLog_builtin#} -const print = @import("std").debug.print; - -const num1 = blk: { - var val1: i32 = 99; - val1 = val1 + 1; - break :blk val1; -}; - -test "main" { print("Runtime in main, num1 = {}.\n", .{num1}); } {#code_end#} @@ -9020,14 +9012,16 @@ pub const PrefetchOptions = struct { {#header_open|@setCold#}{#syntax#}@setCold(comptime is_cold: bool) void{#endsyntax#}
- Tells the optimizer that a function is rarely called. + Tells the optimizer that the current function is (or is not) rarely called. + + This function is only valid within function scope.
{#header_close#} {#header_open|@setEvalBranchQuota#}{#syntax#}@setEvalBranchQuota(comptime new_quota: u32) void{#endsyntax#}
- Changes the maximum number of backwards branches that compile-time code + Increase the maximum number of backwards branches that compile-time code execution can use before giving up and making a compile error.
@@ -9232,7 +9226,7 @@ test "vector @shuffle" { The result is a target-specific compile time constant.
- This size may contain padding bytes. If there were two consecutive T in memory, this would be the offset + This size may contain padding bytes. If there were two consecutive T in memory, the padding would be the offset in bytes between element at index 0 and the element at index 1. For {#link|integer|Integers#}, consider whether you want to use {#syntax#}@sizeOf(T){#endsyntax#} or {#syntax#}@typeInfo(T).Int.bits{#endsyntax#}. @@ -9247,7 +9241,7 @@ test "vector @shuffle" { {#header_open|@splat#}
{#syntax#}@splat(scalar: anytype) anytype{#endsyntax#}
- Produces a vector where each element is the value {#syntax#}scalar{#endsyntax#}. + Produces a vector where each element is the value {#syntax#}scalar{#endsyntax#}. The return type and thus the length of the vector is inferred.
{#code_begin|test|test_splat_builtin#}