authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-19 12:14:30-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-01-19 12:14:30-08:00
logd7b6d637df5b94ec07cf017fa742e8c34a4b9433
treeb4a589f9628d97f7dca0e3da389b4b5f77fa9545
parent3c16e8037261e2f19e4a4daf9c88453ec11281b3
parent96e54e70175881573de2cd1a5e031e391e166f6a
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #18615 from ziglang/langref

miscellaneous documentation changes

4 files changed, 40 insertions(+), 271 deletions(-)

doc/langref.html.in+25-271
...@@ -1156,10 +1156,8 @@ fn addOne(number: i32) i32 {...@@ -1156,10 +1156,8 @@ fn addOne(number: i32) i32 {
1156 {#link|identifier|Identifiers#}, followed by a {#link|block|Blocks#} containing any valid Zig code that1156 {#link|identifier|Identifiers#}, followed by a {#link|block|Blocks#} containing any valid Zig code that
1157 is allowed in a {#link|function|Functions#}.1157 is allowed in a {#link|function|Functions#}.
1158 </p>1158 </p>
1159 <aside>1159 <p>Non-named test blocks always run during test builds and are exempt from
1160 By convention, non-named tests should only be used to {#link|make other tests run|Nested Container Tests#}.1160 {#link|Skip Tests#}.</p>
1161 Non-named tests cannot be {#link|filtered|Skip Tests#}.
1162 </aside>
1163 <p>1161 <p>
1164 Test declarations are similar to {#link|Functions#}: they have a return type and a block of code. The implicit1162 Test declarations are similar to {#link|Functions#}: they have a return type and a block of code. The implicit
1165 return type of {#syntax#}test{#endsyntax#} is the {#link|Error Union Type#} {#syntax#}anyerror!void{#endsyntax#},1163 return type of {#syntax#}test{#endsyntax#} is the {#link|Error Union Type#} {#syntax#}anyerror!void{#endsyntax#},
...@@ -1173,74 +1171,6 @@ fn addOne(number: i32) i32 {...@@ -1173,74 +1171,6 @@ fn addOne(number: i32) i32 {
1173 </p>1171 </p>
1174 {#see_also|The Global Error Set|Grammar#}1172 {#see_also|The Global Error Set|Grammar#}
1175 {#header_close#}1173 {#header_close#}
1176 {#header_open|Nested Container Tests#}
1177 <p>
1178 When the <kbd>zig test</kbd> tool is building a test runner, only resolved {#syntax#}test{#endsyntax#}
1179 declarations are included in the build. Initially, only the given Zig source file's top-level
1180 declarations are resolved. Unless nested {#link|containers|Containers#} are referenced from a top-level test declaration,
1181 nested container tests will not be resolved.
1182 </p>
1183 <p>
1184 The code sample below uses the {#syntax#}std.testing.refAllDecls(@This()){#endsyntax#} function call to
1185 reference all of the containers that are in the file including the imported Zig source file. The code
1186 sample also shows an alternative way to reference containers using the {#syntax#}_ = C;{#endsyntax#}
1187 syntax. This syntax tells the compiler to ignore the result of the expression on the right side of the
1188 assignment operator.
1189 </p>
1190 {#code_begin|test|testing_nested_container_tests#}
1191const std = @import("std");
1192const expect = std.testing.expect;
1193
1194// Imported source file tests will run when referenced from a top-level test declaration.
1195// The next line alone does not cause "testing_introduction.zig" tests to run.
1196const imported_file = @import("testing_introduction.zig");
1197
1198test {
1199 // To run nested container tests, either, call `refAllDecls` which will
1200 // reference all declarations located in the given argument.
1201 // `@This()` is a builtin function that returns the innermost container it is called from.
1202 // In this example, the innermost container is this file (implicitly a struct).
1203 std.testing.refAllDecls(@This());
1204
1205 // or, reference each container individually from a top-level test declaration.
1206 // The `_ = C;` syntax is a no-op reference to the identifier `C`.
1207 _ = S;
1208 _ = U;
1209 _ = @import("testing_introduction.zig");
1210}
1211
1212const S = struct {
1213 test "S demo test" {
1214 try expect(true);
1215 }
1216
1217 const SE = enum {
1218 V,
1219
1220 // This test won't run because its container (SE) is not referenced.
1221 test "This Test Won't Run" {
1222 try expect(false);
1223 }
1224 };
1225};
1226
1227const U = union { // U is referenced by the file's top-level test declaration
1228 s: US, // and US is referenced here; therefore, "U.Us demo test" will run
1229
1230 const US = struct {
1231 test "U.US demo test" {
1232 // This test is a top-level test declaration for the struct.
1233 // The struct is nested (declared) inside of a union.
1234 try expect(true);
1235 }
1236 };
1237
1238 test "U demo test" {
1239 try expect(true);
1240 }
1241};
1242 {#code_end#}
1243 {#header_close#}
1244 {#header_open|Test Failure#}1174 {#header_open|Test Failure#}
1245 <p>1175 <p>
1246 The default test runner checks for an {#link|error|Errors#} returned from a test.1176 The default test runner checks for an {#link|error|Errors#} returned from a test.
...@@ -2856,9 +2786,11 @@ test "volatile" {...@@ -2856,9 +2786,11 @@ test "volatile" {
2856 </p>2786 </p>
2857 {#header_close#}2787 {#header_close#}
2858 <p>2788 <p>
2859 To convert one pointer type to another, use {#link|@ptrCast#}. This is an unsafe2789 {#link|@ptrCast#} converts a pointer's element type to another. This
2860 operation that Zig cannot protect you against. Use {#syntax#}@ptrCast{#endsyntax#} only when other2790 creates a new pointer that can cause undetectable illegal behavior
2861 conversions are not possible.2791 depending on the loads and stores that pass through it. Generally, other
2792 kinds of type conversions are preferable to
2793 {#syntax#}@ptrCast{#endsyntax#} if possible.
2862 </p>2794 </p>
2863 {#code_begin|test|test_pointer_casting#}2795 {#code_begin|test|test_pointer_casting#}
2864const std = @import("std");2796const std = @import("std");
...@@ -5075,12 +5007,12 @@ test "if error union with optional" {...@@ -5075,12 +5007,12 @@ test "if error union with optional" {
5075 {#see_also|Optionals|Errors#}5007 {#see_also|Optionals|Errors#}
5076 {#header_close#}5008 {#header_close#}
5077 {#header_open|defer#}5009 {#header_open|defer#}
5010 <p>Executes an expression unconditionally at scope exit.</p>
5078 {#code_begin|test|test_defer#}5011 {#code_begin|test|test_defer#}
5079const std = @import("std");5012const std = @import("std");
5080const expect = std.testing.expect;5013const expect = std.testing.expect;
5081const print = std.debug.print;5014const print = std.debug.print;
50825015
5083// defer will execute an expression at the end of the current scope.
5084fn deferExample() !usize {5016fn deferExample() !usize {
5085 var a: usize = 1;5017 var a: usize = 1;
50865018
...@@ -5097,10 +5029,14 @@ fn deferExample() !usize {...@@ -5097,10 +5029,14 @@ fn deferExample() !usize {
5097test "defer basics" {5029test "defer basics" {
5098 try expect((try deferExample()) == 5);5030 try expect((try deferExample()) == 5);
5099}5031}
5032 {#code_end#}
5033 <p>Defer expressions are evaluated in reverse order.</p>
5034 {#code_begin|test|defer_unwind#}
5035const std = @import("std");
5036const expect = std.testing.expect;
5037const print = std.debug.print;
51005038
5101// If multiple defer statements are specified, they will be executed in5039test "defer unwinding" {
5102// the reverse order they were run.
5103fn deferUnwindExample() void {
5104 print("\n", .{});5040 print("\n", .{});
51055041
5106 defer {5042 defer {
...@@ -5116,63 +5052,15 @@ fn deferUnwindExample() void {...@@ -5116,63 +5052,15 @@ fn deferUnwindExample() void {
5116 }5052 }
5117 }5053 }
5118}5054}
5119
5120test "defer unwinding" {
5121 deferUnwindExample();
5122}
5123 {#code_end#}5055 {#code_end#}
5056 <p>Inside a defer expression the return statement is not allowed.</p>
5124 {#code_begin|test_err|test_invalid_defer|cannot return from defer expression#}5057 {#code_begin|test_err|test_invalid_defer|cannot return from defer expression#}
5125// Inside a defer expression the return statement is not allowed.
5126fn deferInvalidExample() !void {5058fn deferInvalidExample() !void {
5127 defer {5059 defer {
5128 return error.DeferError;5060 return error.DeferError;
5129 }5061 }
51305062
5131 return error.DeferError;5063 return error.DeferError;
5132}
5133 {#code_end#}
5134 {#code_begin|test|test_errdefer#}
5135const std = @import("std");
5136const print = std.debug.print;
5137
5138// The errdefer keyword is similar to defer, but will only execute if the
5139// scope returns with an error.
5140//
5141// This is especially useful in allowing a function to clean up properly
5142// on error, and replaces goto error handling tactics as seen in c.
5143fn deferErrorExample(is_error: bool) !void {
5144 print("\nstart of function\n", .{});
5145
5146 // This will always be executed on exit
5147 defer {
5148 print("end of function\n", .{});
5149 }
5150
5151 errdefer {
5152 print("encountered an error!\n", .{});
5153 }
5154
5155 if (is_error) {
5156 return error.DeferError;
5157 }
5158}
5159
5160// The errdefer keyword also supports an alternative syntax to capture the
5161// generated error.
5162//
5163// This is useful for printing an additional error message during clean up.
5164fn deferErrorCaptureExample() !void {
5165 errdefer |err| {
5166 std.debug.print("the error is {s}\n", .{@errorName(err)});
5167 }
5168
5169 return error.DeferError;
5170}
5171
5172test "errdefer unwinding" {
5173 deferErrorExample(false) catch {};
5174 deferErrorExample(true) catch {};
5175 deferErrorCaptureExample() catch {};
5176}5064}
5177 {#code_end#}5065 {#code_end#}
5178 {#see_also|Errors#}5066 {#see_also|Errors#}
...@@ -8660,7 +8548,8 @@ test "decl access by string" {...@@ -8660,7 +8548,8 @@ test "decl access by string" {
8660 <pre>{#syntax#}@floatFromInt(int: anytype) anytype{#endsyntax#}</pre>8548 <pre>{#syntax#}@floatFromInt(int: anytype) anytype{#endsyntax#}</pre>
8661 <p>8549 <p>
8662 Converts an integer to the closest floating point representation. The return type is the inferred result type.8550 Converts an integer to the closest floating point representation. The return type is the inferred result type.
8663 To convert the other way, use {#link|@intFromFloat#}. This cast is always safe.8551 To convert the other way, use {#link|@intFromFloat#}. This operation is legal
8552 for all values of all integer types.
8664 </p>8553 </p>
8665 {#header_close#}8554 {#header_close#}
86668555
...@@ -10873,6 +10762,9 @@ const separator = if (builtin.os.tag == .windows) '\\' else '/';...@@ -10873,6 +10762,9 @@ const separator = if (builtin.os.tag == .windows) '\\' else '/';
10873 Some examples of tasks the build system can help with:10762 Some examples of tasks the build system can help with:
10874 </p>10763 </p>
10875 <ul>10764 <ul>
10765 <li>Performing tasks in parallel and caching the results.</li>
10766 <li>Depending on other projects.</li>
10767 <li>Providing a package for other projects to depend on.</li>
10876 <li>Creating build artifacts by executing the Zig compiler. This includes10768 <li>Creating build artifacts by executing the Zig compiler. This includes
10877 building Zig source code as well as C and C++ source code.</li>10769 building Zig source code as well as C and C++ source code.</li>
10878 <li>Capturing user-configured options and using those options to configure10770 <li>Capturing user-configured options and using those options to configure
...@@ -10891,148 +10783,10 @@ const separator = if (builtin.os.tag == .windows) '\\' else '/';...@@ -10891,148 +10783,10 @@ const separator = if (builtin.os.tag == .windows) '\\' else '/';
10891 to see a command-line usage help menu. This will include project-specific10783 to see a command-line usage help menu. This will include project-specific
10892 options that were declared in the build.zig script.10784 options that were declared in the build.zig script.
10893 </p>10785 </p>
1089410786 <p>
10895 {#header_open|Building an Executable#}10787 For the time being, the build system documentation is hosted externally:
10896 <p>This <code class="file">build.zig</code> file is automatically generated10788 <a href="https://ziglang.org/learn/build-system/">Build System Documentation</a>
10897 by <kbd>zig init-exe</kbd>.</p>10789 </p>
10898 {#code_begin|syntax|build_executable#}
10899const std = @import("std");
10900
10901// Although this function looks imperative, note that its job is to
10902// declaratively construct a build graph that will be executed by an external
10903// runner.
10904pub fn build(b: *std.Build) void {
10905 // Standard target options allows the person running `zig build` to choose
10906 // what target to build for. Here we do not override the defaults, which
10907 // means any target is allowed, and the default is native. Other options
10908 // for restricting supported target set are available.
10909 const target = b.standardTargetOptions(.{});
10910
10911 // Standard optimization options allow the person running `zig build` to select
10912 // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
10913 // set a preferred release mode, allowing the user to decide how to optimize.
10914 const optimize = b.standardOptimizeOption(.{});
10915
10916 const exe = b.addExecutable(.{
10917 .name = "example",
10918 // In this case the main source file is merely a path, however, in more
10919 // complicated build scripts, this could be a generated file.
10920 .root_source_file = .{ .path = "src/main.zig" },
10921 .target = target,
10922 .optimize = optimize,
10923 });
10924
10925 // This declares intent for the executable to be installed into the
10926 // standard location when the user invokes the "install" step (the default
10927 // step when running `zig build`).
10928 b.installArtifact(exe);
10929
10930 // This *creates* a Run step in the build graph, to be executed when another
10931 // step is evaluated that depends on it. The next line below will establish
10932 // such a dependency.
10933 const run_cmd = b.addRunArtifact(exe);
10934
10935 // By making the run step depend on the install step, it will be run from the
10936 // installation directory rather than directly from within the cache directory.
10937 // This is not necessary, however, if the application depends on other installed
10938 // files, this ensures they will be present and in the expected location.
10939 run_cmd.step.dependOn(b.getInstallStep());
10940
10941 // This allows the user to pass arguments to the application in the build
10942 // command itself, like this: `zig build run -- arg1 arg2 etc`
10943 if (b.args) |args| {
10944 run_cmd.addArgs(args);
10945 }
10946
10947 // This creates a build step. It will be visible in the `zig build --help` menu,
10948 // and can be selected like this: `zig build run`
10949 // This will evaluate the `run` step rather than the default, which is "install".
10950 const run_step = b.step("run", "Run the app");
10951 run_step.dependOn(&run_cmd.step);
10952
10953 // Creates a step for unit testing. This only builds the test executable
10954 // but does not run it.
10955 const unit_tests = b.addTest(.{
10956 .root_source_file = .{ .path = "src/main.zig" },
10957 .target = target,
10958 .optimize = optimize,
10959 });
10960
10961 const run_unit_tests = b.addRunArtifact(unit_tests);
10962
10963 // Similar to creating the run step earlier, this exposes a `test` step to
10964 // the `zig build --help` menu, providing a way for the user to request
10965 // running the unit tests.
10966 const test_step = b.step("test", "Run unit tests");
10967 test_step.dependOn(&run_unit_tests.step);
10968}
10969 {#code_end#}
10970 {#header_close#}
10971
10972 {#header_open|Building a Library#}
10973 <p>This <code class="file">build.zig</code> file is automatically generated
10974 by <kbd>zig init-lib</kbd>.</p>
10975 {#code_begin|syntax|build_library#}
10976const std = @import("std");
10977
10978// Although this function looks imperative, note that its job is to
10979// declaratively construct a build graph that will be executed by an external
10980// runner.
10981pub fn build(b: *std.Build) void {
10982 // Standard target options allows the person running `zig build` to choose
10983 // what target to build for. Here we do not override the defaults, which
10984 // means any target is allowed, and the default is native. Other options
10985 // for restricting supported target set are available.
10986 const target = b.standardTargetOptions(.{});
10987
10988 // Standard optimization options allow the person running `zig build` to select
10989 // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
10990 // set a preferred release mode, allowing the user to decide how to optimize.
10991 const optimize = b.standardOptimizeOption(.{});
10992
10993 const lib = b.addStaticLibrary(.{
10994 .name = "example",
10995 // In this case the main source file is merely a path, however, in more
10996 // complicated build scripts, this could be a generated file.
10997 .root_source_file = .{ .path = "src/main.zig" },
10998 .target = target,
10999 .optimize = optimize,
11000 });
11001
11002 // This declares intent for the library to be installed into the standard
11003 // location when the user invokes the "install" step (the default step when
11004 // running `zig build`).
11005 b.installArtifact(lib);
11006
11007 // Creates a step for unit testing. This only builds the test executable
11008 // but does not run it.
11009 const main_tests = b.addTest(.{
11010 .root_source_file = .{ .path = "src/main.zig" },
11011 .target = target,
11012 .optimize = optimize,
11013 });
11014
11015 const run_main_tests = b.addRunArtifact(main_tests);
11016
11017 // This creates a build step. It will be visible in the `zig build --help` menu,
11018 // and can be selected like this: `zig build test`
11019 // This will evaluate the `test` step rather than the default, which is "install".
11020 const test_step = b.step("test", "Run library tests");
11021 test_step.dependOn(&run_main_tests.step);
11022}
11023 {#code_end#}
11024 {#header_close#}
11025
11026 {#header_open|Compiling C Source Code#}
11027 <pre>{#syntax#}
11028lib.addCSourceFile(.{ .file = .{ .path = "src/lib.c" }, .flags = &.{
11029 "-Wall",
11030 "-Wextra",
11031 "-Werror",
11032 } });
11033 {#endsyntax#}</pre>
11034 {#header_close#}
11035
11036 {#header_close#}10790 {#header_close#}
11037 {#header_open|C#}10791 {#header_open|C#}
11038 <p>10792 <p>
lib/std/Build.zig+10
...@@ -599,6 +599,11 @@ pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list:...@@ -599,6 +599,11 @@ pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list:
599 self.h_dir = self.pathJoin(&h_list);599 self.h_dir = self.pathJoin(&h_list);
600}600}
601601
602/// Create a set of key-value pairs that can be converted into a Zig source
603/// file and then inserted into a Zig compilation's module table for importing.
604/// In other words, this provides a way to expose build.zig values to Zig
605/// source code with `@import`.
606/// Related: `Module.addOptions`.
602pub fn addOptions(self: *Build) *Step.Options {607pub fn addOptions(self: *Build) *Step.Options {
603 return Step.Options.create(self);608 return Step.Options.create(self);
604}609}
...@@ -1031,6 +1036,11 @@ fn makeUninstall(uninstall_step: *Step, prog_node: *std.Progress.Node) anyerror!...@@ -1031,6 +1036,11 @@ fn makeUninstall(uninstall_step: *Step, prog_node: *std.Progress.Node) anyerror!
1031 // TODO remove empty directories1036 // TODO remove empty directories
1032}1037}
10331038
1039/// Creates a configuration option to be passed to the build.zig script.
1040/// When a user directly runs `zig build`, they can set these options with `-D` arguments.
1041/// When a project depends on a Zig package as a dependency, it programmatically sets
1042/// these options when calling the dependency's build.zig script as a function.
1043/// `null` is returned when an option is left to default.
1034pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_raw: []const u8) ?T {1044pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_raw: []const u8) ?T {
1035 const name = self.dupe(name_raw);1045 const name = self.dupe(name_raw);
1036 const description = self.dupe(description_raw);1046 const description = self.dupe(description_raw);
lib/std/Build/Module.zig+3
...@@ -318,6 +318,9 @@ pub fn addAnonymousImport(m: *Module, name: []const u8, options: CreateOptions)...@@ -318,6 +318,9 @@ pub fn addAnonymousImport(m: *Module, name: []const u8, options: CreateOptions)
318 return addImport(m, name, module);318 return addImport(m, name, module);
319}319}
320320
321/// Converts a set of key-value pairs into a Zig source file, and then inserts it into
322/// the Module's import table with the specified name. This makes the options importable
323/// via `@import("module_name")`.
321pub fn addOptions(m: *Module, module_name: []const u8, options: *Step.Options) void {324pub fn addOptions(m: *Module, module_name: []const u8, options: *Step.Options) void {
322 addImport(m, module_name, options.createModule());325 addImport(m, module_name, options.createModule());
323}326}
lib/std/Build/Step/Options.zig+2
...@@ -198,6 +198,8 @@ pub fn createModule(self: *Options) *std.Build.Module {...@@ -198,6 +198,8 @@ pub fn createModule(self: *Options) *std.Build.Module {
198/// deprecated: use `getOutput`198/// deprecated: use `getOutput`
199pub const getSource = getOutput;199pub const getSource = getOutput;
200200
201/// Returns the main artifact of this Build Step which is a Zig source file
202/// generated from the key-value pairs of the Options.
201pub fn getOutput(self: *Options) LazyPath {203pub fn getOutput(self: *Options) LazyPath {
202 return .{ .generated = &self.generated_file };204 return .{ .generated = &self.generated_file };
203}205}