Zig 0.12.0 Delivery Notes

Zig 0.12.0 Delivery Notes

Download & Documentation

Zig is a frequent-aim programming language and toolchain for asserting
robust, optimum, and reusable utility.

Zig model is funded by Zig Tool Foundation,
a 501(c)(3) non-profit organization. Please set in thoughts a ordinary donation
in reveal that we are in a position to offer extra billable hours to our core team participants. Right here’s
the most easy methodology to hasten the mission alongside the
Roadmap to 1.0.

This free up aspects 8 months of work:
adjustments from 268 varied contributors, spread amongst
3688 commits.

Within the past, these free up notes gather been extremely prolonged, trying to
gather in thoughts all enhancements that befell at some level of the free up cycle. In
the hobby of no longer overwhelming the reader to boot to the maintainers
creating these notes, this doc is abridged. Many adjustments, at the side of
API breaking adjustments, are no longer mentioned right here.

Table of Contents §

  • Table of Contents
  • Make stronger Table
    • Tier Machine
      • Tier 1 Make stronger
      • Tier 2 Make stronger
      • Tier 3 Make stronger
      • Tier 4 Make stronger
  • Redesign How Autodoc Works
    • Installed Standard Library Documentation
    • Time to Generate Documentation
    • Original Autodoc Facets
      • Reliable Linkification
      • Interactive Source Listings
      • Embedded Source Listings
      • Search Contains Doc Feedback
      • Error Build Take into memoir
      • Honest appropriate Form Detection
      • Honest appropriate Implementation of Scroll Ancient past
  • Language Modifications
    • Unnecessary Employ of var
    • Consequence Space Semantics
    • Combination Destructuring
    • Namespace Form Equivalence
    • Comptime Reminiscence Modifications
    • @fieldParentPtr
    • Disallow alignment on feature form
    • @errorCast
    • @abs
  • Standard Library
    • Windows Expose Line Argument Parsing
    • Bring-Your-Maintain-OS API Layer Regressed
    • std.os renamed to std.posix
    • Ryu Floating-Point Formatting
    • Transformed HTTP
      • Elimination of std.http.Headers
      • Remodel Server Fully
    • deflate reimplemented from first principles
    • std.posix APIs Invent Form Safety
    • std.builtin Enum Fields Lowercased
    • World Configuration
    • Pointer Stability Locks
  • Variety Machine
    • Machine Package Mode
      • Potential to Present Non-mandatory Machine Library Integration
      • Machine Integration Support Share
      • The usage of the Machine Integration Alternate choices
      • Original Delivery Option
      • Steer sure of Fetching in Machine Mode
    • Sluggish Dependencies
    • introduce b.route; deprecate LazyPath.relative
    • Header Installation
    • dependencyFromBuildZig
  • Compiler
    • x86 Backend
  • Windows Belongings
  • Linker
  • Cache Machine
  • Bug Fixes
    • Comptime Pointer Catch admission to
    • This Delivery Incorporates Bugs
  • Toolchain
    • LLVM 17
    • musl 1.2.4
    • glibc 2.38
    • mingw-w64
  • Roadmap
    • Async/Await Characteristic Standing
  • Thank You Contributors!
  • Thank You Sponsors!

Make stronger Table §

Tier Machine §

A inexperienced check trace (✅) indicates the aim meets the final necessities for the
make stronger tier. The plenty of icons show camouflage what is stopping the aim from
reaching the make stronger tier
. In varied phrases, the icons are
to-attain items. When you see any disagreeable knowledge right here please
submit a pull query!

Tier 1 Make stronger §

  • Now not easiest can Zig generate machine code for these targets, however the
    Standard Library execrable-platform abstractions gather implementations
    for these targets.
  • The CI server automatically assessments these targets on every decide to master
    division. The 🧪 icon manner this aim doesn’t yet gather CI take a look at protection.
  • The CI server automatically produces pre-constructed binaries for these targets,
    on every decide to master, and updates
    the download page with hyperlinks.
    The 📦 icon manner the download page is missing this aim.
  • These targets gather debug info capabilities and therefore
    make stack traces on failed assertions.
  • libc is equipped for this aim even when execrable compiling.
  • The overall behavior assessments and acceptable typical library assessments pass for this aim.
    All language aspects are known to work appropriately. Experimental aspects attain no longer
    depend towards disqualifying an operating intention or structure from Tier 1.
    The 🐛 icon manner there are known bugs stopping
    this aim from reaching Tier 1.
  • zig cc, zig c++, and linked toolchain instructions make stronger
    this aim.
  • If the Working Machine is proprietary then the aim is now not any longer marked deprecated
    by the dealer. The 💀 icon manner the OS is formally deprecated,
    similar to macos/x86.
freestanding Linux 3.16+ macOS 11+ Windows 10+ WASI
x86_64 N/A
x86 #1929 🐛 💀 #537 🐛 N/A
aarch64 #2443 🐛 #16665 🐛 N/A
arm #3174 🐛 💀 🐛📦🧪 N/A
mips #3345 🐛📦 N/A N/A N/A
riscv64 #4456 🐛 N/A N/A N/A
sparc64 #4931 🐛📦🧪 N/A N/A N/A
powerpc64 🐛 N/A N/A N/A
powerpc 🐛 N/A N/A N/A
wasm32 N/A N/A N/A

Tier 2 Make stronger §

  • The Standard Library helps this aim, however it completely is feasible that some
    APIs will give an “Unsupported OS” compile error. One can hyperlink with libc or varied
    libraries to comprise in the gaps in the long-established library. The 📖 icon manner the
    typical library is simply too incomplete to be regarded as Tier 2 famous.
  • These targets are known to work, however would possibly maybe perchance perchance perchance no longer be automatically tested, so there
    are occasional regressions. 🔍 manner that no one has in actuality looked into this aim
    so whether or no longer or no longer it works is unknown.
  • Some assessments also can very smartly be disabled for these targets as we work towards
    Tier 1 Make stronger.
free standing Linux 3.16+ macOS 11+ Windows 10+ FreeBSD 12.0+ NetBSD 8.0+ Dragon FlyBSD 5.8+ OpenBSD 7.3+ UEFI
x86_64 Tier 1 Tier 1 Tier 1 Tier 1
x86 Tier 1 💀 🔍 🔍 N/A 🔍
aarch64 Tier 1 Tier 1 🔍 🔍 N/A 🔍 🔍
arm Tier 1 💀 🔍 🔍 🔍 N/A 🔍 🔍
mips64 N/A N/A 🔍 🔍 N/A 🔍 N/A
mips Tier 1 N/A N/A 🔍 🔍 N/A 🔍 N/A
powerpc64 Tier 1 💀 N/A 🔍 🔍 N/A 🔍 N/A
powerpc Tier 1 💀 N/A 🔍 🔍 N/A 🔍 N/A
riscv64 Tier 1 N/A N/A 🔍 🔍 N/A 🔍 🔍
sparc64 Tier 1 N/A N/A 🔍 🔍 N/A 🔍 N/A

Tier 3 Make stronger §

  • The long-established library has minute to no knowledge of the existence of this
    aim.
  • If this aim is equipped by LLVM, LLVM has the aim enabled by default.
  • These targets are no longer usually tested; one will likely must contribute
    to Zig with a opinion to operate for these targets.
  • The Zig compiler would possibly maybe perchance perchance perchance must be updated with a couple of issues similar to
    • what sizes are the C integer kinds
    • C ABI calling conference for this aim
    • originate code and default fear handler
  • zig targets is guaranteed to incorporate this aim.
freestanding Linux 3.16+ Windows 10+ FreeBSD 12.0+ NetBSD 8.0+ UEFI
x86_64 Tier 1 Tier 1 Tier 1 Tier 2 Tier 2 Tier 2
x86 Tier 1 Tier 2 Tier 2 Tier 2
aarch64 Tier 1 Tier 2 Tier 2
arm Tier 1 Tier 2
mips64 Tier 2 Tier 2 N/A N/A
mips Tier 1 Tier 2 N/A N/A
riscv64 Tier 1 Tier 2 N/A
powerpc32 Tier 2 Tier 2 N/A N/A
powerpc64 Tier 2 Tier 2 N/A N/A
bpf N/A N/A
hexagon N/A N/A
amdgcn N/A N/A
sparc N/A N/A
s390x N/A N/A
lanai N/A N/A
csky N/A N/A
freestanding emscripten
wasm32 Tier 1

Tier 4 Make stronger §

  • Make stronger for these targets is exclusively experimental.
  • If this aim is equipped by LLVM, LLVM would possibly maybe perchance perchance perchance gather the aim as an
    experimental aim, which manner that you just gather to make spend of Zig-equipped binaries
    for the aim to be accessible, or operate LLVM from provide with particular configure flags.
    zig targets will show camouflage the aim if it’s accessible.
  • This aim also can very smartly be regarded as deprecated by an authentic birthday celebration, in
    which case this aim will remain with no waste in sight stuck in Tier 4.
  • This aim would possibly maybe perchance perchance perchance easiest make stronger -femit-asm and can’t emit
    object recordsdata, whereby case -fno-emit-bin is enabled by
    default and can’t be overridden.

Tier 4 targets:

  • avr
  • riscv32
  • xcore
  • nvptx
  • msp430
  • r600
  • arc
  • tce
  • le
  • amdil
  • hsail
  • spir
  • kalimba
  • shave
  • renderscript
  • 32-bit x86 macOS, 32-bit ARM macOS, powerpc32 and powerpc64 macOS, on memoir of
    Apple has formally dropped make stronger for them.

Redesign How Autodoc Works §

This free up deletes the earlier (experimental) Autodoc implementation and replaces it with a peculiar (no longer experimental!) one.

The outmoded implementation looked like this:

   5987 src/Autodoc.zig
   435 src/autodoc/render_source.zig
 10270 lib/docs/commonmark.js
  1245 lib/docs/index.html
  5242 lib/docs/main.js
  2146 lib/docs/ziglexer.js
 25325 total

After compilation (sizes are for typical library documentation):

272K commonmark.js
3.8M data-astNodes.js
360K data-calls.js
767K data-comptimeExprs.js
2.2M data-decls.js
896K data-exprs.js
 13K data-files.js
  45 data-guideSections.js
 129 data-modules.js
  15 data-rootMod.js
 294 data-typeKinds.js
3.2M data-types.js
 38K index.html
158K main.js
 36M src/ (470 .zig.html files)
 78K ziglexer.js

Total output size: 47M (5.7M gzipped)

src/Autodoc.zig processed ZIR code, outputting JSON knowledge for a web utility to savor. This resulted in rather a couple of code ineffectively trying to reconstruct the AST from no-longer-accessible knowledge.

lib/docs/commonmark.js used to be a Third-birthday celebration markdown implementation that supported too many aspects; as an instance I attain no longer need it to be that it’s doubtless you’ll perchance perchance perchance maybe factor in to assemble HTML tags in doc feedback, on memoir of that will fetch provide code uglier. Easiest markdown that seems appropriate both as provide and rendered must be allowed.

lib/docs/ziglexer.js used to be an implementation of Zig language tokenization in JavaScript, despite Zig already exposing its own tokenizer in the long-established library. After I saw this added to the zig mission, a minute bit portion of me died inner.

src/autodoc/render_source.zig used to be a instrument that transformed .zig recordsdata to a syntax-highlighted however non-interactive .zig.html recordsdata.

The unusual implementation appears like this:

   942 lib/docs/main.js
   403 lib/docs/index.html
   933 lib/docs/wasm/markdown.zig
   226 lib/docs/wasm/Decl.zig
  1500 lib/docs/wasm/markdown/Parser.zig
   254 lib/docs/wasm/markdown/renderer.zig
   192 lib/docs/wasm/markdown/Document.zig
   941 lib/docs/wasm/main.zig
  1038 lib/docs/wasm/Walk.zig
  6630 total

After compilation (sizes are for typical library documentation):

 12K index.html
 32K main.js
192K main.wasm
 12M sources.tar

Total output size: 12M (2.3M gzipped)

As it’s doubtless you’ll perchance perchance perchance maybe look, it’s both dramatically extra life like in the case of implementation to boot to operate artifacts. Now there are exactly 4 recordsdata as an different of many, with a 4x good buy in entire file size of the generated web app.

Nevertheless, no longer easiest is it extra life like, it’s in actuality extra powerful than the outmoded intention, on memoir of as an different of processing ZIR, this methodology processes the availability recordsdata without lengthen, which manner it has 100% of the knowledge and never desires to portion the rest collectively backwards.

This approach uses a WebAssembly module written in Zig. This enables it to reuse ingredients from the compiler, similar to the tokenizer, parser, and varied utilities for operating on Zig code.

The sources.tar file, after being decompressed by the HTTP layer, is fed without lengthen into the wasm module’s memory. The tar file is parsed the spend of std.tar and provide recordsdata are parsed in space, with some extra computations added to hash tables on the side.

There would possibly maybe be room for introducing employee threads to velocity up the parsing, even supposing single-threaded it’s already so quick that it doesn’t seem necessary.

Installed Standard Library Documentation §

In Zig 0.11.0, a Zig installation comes with a docs/std/
directory that includes these 47M of output artifacts mentioned above.

This rewrite eliminated these artifacts from Zig installations, as an different
offering the zig std exclaim, which hosts std lib autodocs and
spawns a browser window to peep them. When this exclaim is activated,
lib/compiler/std-docs.zig is compiled from provide to fetch
this operation.

The HTTP server creates the requested recordsdata on the flit, at the side of
rebuilding main.wasm if any of its provide recordsdata changed, and developing
sources.tar, which manner that any provide adjustments to the documented recordsdata,
or to the autodoc intention itself are without lengthen reflected when
viewing doctors. Prefixing the URL with /debug ends in a debug
operate of the WebAssembly module.

This vogue contributors can take a look at adjustments to Zig typical library documentation, to boot to autodocs performance, by urgent refresh in their browser window, the spend of a easiest binary distribution of Zig.

In entire, this reduced the Zig installation size from 317M to 268M (-15%).

A ReleaseSmall operate of the compiler shrinks from 10M to 9.8M (-1%).

Time to Generate Documentation §

Autodocs period is now carried out smartly as portion of the pipeline of the compiler in wish to tacked on on the pause. It also now no longer has any dependencies on varied ingredients of the pipeline.

Right here’s how prolonged it now takes to generate typical library documentation:

Benchmark 1 (3 runs): old/zig test /home/andy/dev/zig/lib/std/std.zig -fno-emit-bin -femit-docs=docs
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          13.3s  ±  405ms    12.8s  … 13.6s           0 ( 0%)        0%
  peak_rss           1.08GB ±  463KB    1.08GB … 1.08GB          0 ( 0%)        0%
  cpu_cycles         54.8G  ±  878M     54.3G  … 55.8G           0 ( 0%)        0%
  instructions        106G  ±  313K      106G  …  106G           0 ( 0%)        0%
  cache_references   2.11G  ± 35.4M     2.07G  … 2.14G           0 ( 0%)        0%
  cache_misses       41.3M  ±  455K     40.8M  … 41.7M           0 ( 0%)        0%
  branch_misses       116M  ± 67.8K      116M  …  116M           0 ( 0%)        0%
Benchmark 2 (197 runs): new/zig build-obj -fno-emit-bin -femit-docs=docs ../lib/std/std.zig
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          24.6ms ± 1.03ms    22.8ms … 28.3ms          4 ( 2%)        ⚡- 99.8% ±  0.3%
  peak_rss           87.3MB ± 60.6KB    87.2MB … 87.4MB          0 ( 0%)        ⚡- 91.9% ±  0.0%
  cpu_cycles         38.4M  ±  903K     37.4M  … 46.1M          13 ( 7%)        ⚡- 99.9% ±  0.2%
  instructions       39.7M  ± 12.4K     39.7M  … 39.8M           0 ( 0%)        ⚡-100.0% ±  0.0%
  cache_references   2.65M  ± 89.1K     2.54M  … 3.43M           3 ( 2%)        ⚡- 99.9% ±  0.2%
  cache_misses        197K  ± 5.71K      186K  …  209K           0 ( 0%)        ⚡- 99.5% ±  0.1%
  branch_misses       184K  ± 1.97K      178K  …  190K           6 ( 3%)        ⚡- 99.8% ±  0.0%

It dilapidated to plot end upwards of 13 seconds. Now it takes 25ms.

Original Autodoc Facets §

Reliable Linkification §

This stems from the actual fact that with stout provide recordsdata we now gather the final knowledge, and would possibly maybe perchance perchance write extra robust code to assemble a study up identifiers from the context they occur in.

Interactive Source Listings §

Press u to head to provide code for any declaration:

The hyperlinks plot end you to the API page for that categorical hyperlink by changing the placement hash.

Embedded Source Listings §

Error Build Take into memoir §

Merged error units are detected:

Errors that advance from varied declarations are linked:

Errors are also confirmed on feature peep:

Honest appropriate Form Detection §

Old implementation guesses disagreeable on the vogue of options to boot to DynLib.

Honest appropriate Implementation of Scroll Ancient past §

The earlier implementation implemented scroll historical past in JavaScript, which is inconceivable to realize
appropriately. The unusual intention makes cautious spend of the ‘popstate’ event combined with the historical past API
to scroll to the high of the window easiest when the user navigates to a peculiar hyperlink – respecting the browser’s
saved scroll historical past in all varied cases.

For extra little print look
the commit diff.

Language Modifications §

Unnecessary Employ of var §

Zig 0.12.0 introduces a peculiar compile error which is emitted when a native variable is declared as
a var, however the compiler can infer that const would suffice.

unnecessary_var.zig
const expectEqual = @import("std").testing.expectEqual;
test "unnecessary use of var" {
    var x: u32 = 123;
    try expectEqual(123, x);
}
Shell
$ zig test unnecessary_var.zig
docgen_tmp/unnecessary_var.zig:3:9: error: local variable is never mutated
    var x: u32 = 123;
        ^
docgen_tmp/unnecessary_var.zig:3:9: note: consider using 'const'

As indicated by the error message, the answer is straightforward: spend const as an different
the place acceptable.

Consequence Space Semantics §

Zig 0.12.0 features quite so much of enhancements to Consequence Space Semantics (RLS).

This free up implements forwarding of result kinds by the address-of operator (&). This enables
syntactic constructs which rely on result kinds, similar to nameless initializations .{ ... }
and casting builtins like @intCast, to feature appropriately in the presence of the
address-of operator:

address_of_rls.zig
const S = struct { x: u32 };
const int: u64 = 123;
const val: *const S = &.{ .x = @intCast(int) };
comptime {
    _ = val;
}
Shell
$ zig test address_of_rls.zig
All 0 tests passed.

To boot, Zig 0.12.0 removes the flexibility for result areas to propagate by @as
and explicitly-typed mixture initializations T{ ... }. This restriction is in space to
simplify the language originate: earlier releases contained quite so much of bugs touching on to incorrect casting of result pointers.

Combination Destructuring §

Zig 0.12.0 introduces a peculiar syntax to permit destructuring indexable aggregates: that is, tuples, vectors, and arrays.
Writing a sequence of lvalues or native variable declarations on the left-hand side of the assignment will strive to
destructure the stamp specified on the staunch-hand side:

destructure.zig
const std = @import("std");
const assert = std.debug.assert;
const expectEqual = std.testing.expectEqual;
test "destructure array" {
    var z: u32 = undefined;
    const x, var y, z = [3]u32{ 1, 2, 3 };
    y += 10;
    try expectEqual(1, x);
    try expectEqual(12, y);
    try expectEqual(3, z);
}
test "destructure vector" {
    // Comptime-known values are propagated as you would expect.
    const x, const y = @Vector(2, u32){ 1, 2 };
    comptime assert(x == 1);
    comptime assert(y == 2);
}
test "destructure tuple" {
    var runtime: u32 = undefined;
    runtime = 123;
    const x, const y = .{ 42, runtime };
    // The first tuple field is a `comptime` field, so `x` is comptime-known even
    // though `y` is runtime-known.
    comptime assert(x == 42);
    try expectEqual(123, y);
}
Shell
$ zig test destructure.zig
1/3 destructure.test.destructure array... OK
2/3 destructure.test.destructure vector... OK
3/3 destructure.test.destructure tuple... OK
All 3 tests passed.

Slices can’t be without lengthen destructured. To destructure values from a nick, convert it to an array by lowering
with comptime-known bounds, similar to slice[0..3].*.

Namespace Form Equivalence §

In Zig, struct, enum, union, and opaque kinds are particular. They
attain no longer spend structural equivalence, like tuples and arrays attain; as an different, they operate determined kinds. These kinds gather
namespaces, and thus would possibly maybe perchance perchance perchance have declarations. For this motive, they would possibly maybe perchance perchance perchance even be referred to collectively as “namespace
kinds”.

In 0.11.0, at any time when a declaration of this sort of form used to be semantically analyzed, a peculiar form used to be created. Equivalence of
generic kinds used to be handled by memoization of comptime feature calls; i.e.
std.ArrayList(u8) == std.ArrayList(u8) held since the ArrayList feature used to be easiest called
once, and its results memoized.

In 0.12.0, this has changed. Namespace kinds for the time being are deduplicated primarily based on two factors: their provide plot, and
their captures.

The “captures” of a form refers back to the dwelling of comptime-known kinds and values which it closes over. In varied phrases,
it is the dwelling of values referenced within the form however declared outdoor of it. For example, the
comptime T: type parameter of std.ArrayList is captured by the form it returns. If two
namespace kinds are declared by the identical portion of code and gather the identical captures, they for the time being are regarded as to be
exactly the identical form.

Camouflage that the compiler will mute memoize comptime calls: that hasn’t changed. Nevertheless, this memoization now no longer
has a necessary affect on language semantics.

It’s unlikely that this trade will reason breakage in unusual code. The maybe scenario the place it would possibly perchance perchance perchance is
something just like the following:

opaque_generator.zig
fn MakeOpaque(comptime n: comptime_int) type {
    _ = n;
    return opaque {};
}
const A = MakeOpaque(0);
const B = MakeOpaque(1);

In Zig 0.11.0, this code would operate two determined kinds, since the calls to MakeOpaque are determined
and thus the opaque declaration used to be analyzed individually for every call. In Zig 0.12.0, these kinds are
identical (A == B), on memoir of whereas the feature is called twice, the declaration doesn’t hold any
stamp.

This code would possibly maybe perchance perchance perchance even be mounted by forcing the form declaration to hold n:

opaque_generator.zig
fn MakeOpaque(comptime n: comptime_int) type {
    return opaque {
        comptime {
            _ = n;
        }
    };
}
const A = MakeOpaque(0);
const B = MakeOpaque(1);

Since n is referenced within the opaque declaration, this code creates two determined kinds.

Comptime Reminiscence Modifications §

Zig 0.12.0 overhauls the compiler’s interior illustration of comptime memory, and extra specifically
comptime-mutable memory (i.e. comptime var). This overhaul comes with some user-going by
adjustments in the develop of fresh restrictions on what it’s doubtless you’ll perchance perchance perchance maybe attain with a comptime var.

The first, and most necessary, unusual rule is that a pointer to a comptime var is now not any longer in actuality
allowed to turn out to be runtime-known. For example, set in thoughts the following snippet:

comptime_var_ptr_runtime.zig
test "runtime-known comptime var pointer" {
    comptime var x: u32 = 123;
    // `var` makes `ptr` runtime-known
    var ptr: *const u32 = undefined;
    ptr = &x;
    if (ptr.* != 123) return error.TestFailed;
}
Shell
$ zig test comptime_var_ptr_runtime.zig
docgen_tmp/comptime_var_ptr_runtime.zig:5:11: error: runtime value contains reference to comptime var
    ptr = &x;
          ^~
docgen_tmp/comptime_var_ptr_runtime.zig:5:11: note: comptime var pointers are not available at runtime

In earlier variations of Zig, this take a look at passed as it’s doubtless you’ll perchance perchance perchance maybe query. In Zig 0.12.0, it emits a compile error,
since the assignment to ptr makes the stamp &x – which is a pointer to a
comptime var – runtime-known.

Such pointers also can moreover turn out to be runtime-known by, as an instance, being passed to a feature called at runtime:

comptime_var_ptr_runtime_arg.zig
test "comptime var pointer as runtime argument" {
    comptime var x: u32 = 123;
    if (load(&x) != 123) return error.TestFailed;
}
fn load(ptr: *const u32) u32 {
    return ptr.*;
}
Shell
$ zig test comptime_var_ptr_runtime_arg.zig
docgen_tmp/comptime_var_ptr_runtime_arg.zig:3:14: error: runtime value contains reference to comptime var
    if (load(&x) != 123) return error.TestFailed;
             ^~
docgen_tmp/comptime_var_ptr_runtime_arg.zig:3:14: note: comptime var pointers are not available at runtime

This take a look at also emits a compile error in Zig 0.12.0. The choice to load occurs at runtime, and its
ptr parameter is now not any longer marked comptime, so ptr is runtime-known
within the body of load. This vogue the call to load makes the pointer &x
runtime-known, hence the compile error.

This restriction used to be set in space to fix some soundness bugs. When a pointer to a comptime var
turns into runtime-known, mutations to it turn out to be invalid since the pointed-to knowledge turns into constant, however the form intention
fails to replicate this, resulting in the probability of runtime segmentation faults in what looks to be real code. In
addition, the stamp you read from this sort of pointer at runtime would possibly maybe perchance perchance perchance be its “closing” comptime stamp, which used to be an
unintuitive behavior. Thus, these pointers can now no longer be runtime-known.

The second unusual restriction is that a pointer to a comptime var is now not any longer in actuality allowed to be contained
within the resolved stamp of a world declaration. For example, set in thoughts the following snippet:

comptime_var_ptr_global.zig
const ptr: *const u32 = ptr: {
    var x: u32 = 123;
    break :ptr &x;
};
comptime {
    _ = ptr;
}
Shell
$ zig test comptime_var_ptr_global.zig
docgen_tmp/comptime_var_ptr_global.zig:1:30: error: global variable contains reference to comptime var
const ptr: *const u32 = ptr: {
                        ~~~~~^
referenced by:
    comptime_0: docgen_tmp/comptime_var_ptr_global.zig:6:9
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

Right here, ptr is a world declaration whose stamp is a pointer to a comptime var.
This declaration used to be authorized in Zig 0.11.0, however raises a compile error in Zig 0.12.0. The identical rule applies in
extra advanced cases, similar to when the pointer is contained within a struct self-discipline:

comptime_var_ptr_global_struct.zig
const S = struct { ptr: *const u32 };
const val: S = blk: {
    var x: u32 = 123;
    break :blk .{ .ptr = &x };
};
comptime {
    _ = val;
}
Shell
$ zig test comptime_var_ptr_global_struct.zig
docgen_tmp/comptime_var_ptr_global_struct.zig:2:21: error: global variable contains reference to comptime var
const val: S = blk: {
               ~~~~~^
referenced by:
    comptime_0: docgen_tmp/comptime_var_ptr_global_struct.zig:7:9
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

This code raises the identical compile error as the earlier instance. This restriction has been set in space primarily to
succor the implementation of incremental compilation in the Zig compiler, which depends on the actual fact that diagnosis of
global declarations is reveal-autonomous, and the dependencies between declarations would possibly maybe perchance perchance perchance even be with out train modeled.

Essentially the most frequent methodology for this to manifest as a compile error in unusual code is if a feature constructs a nick
at comptime which is then dilapidated at runtime. For example, set in thoughts the following snippet:

construct_slice_comptime.zig
fn getName() []const u8 {
    comptime var buf: [9]u8 = undefined;
    // In practice there would likely be more complex logic here to populate `buf`.
    @memcpy(&buf, "some name");
    return &buf;
}
test getName {
    try @import("std").testing.expectEqualStrings("some name", getName());
}
Shell
$ zig test construct_slice_comptime.zig
docgen_tmp/construct_slice_comptime.zig:5:12: error: runtime value contains reference to comptime var
    return &buf;
           ^~~~
docgen_tmp/construct_slice_comptime.zig:5:12: note: comptime var pointers are not available at runtime
referenced by:
    decltest.getName: docgen_tmp/construct_slice_comptime.zig:8:64
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

A call to getName returns a nick whose ptr self-discipline is a pointer to a
comptime var. This vogue the stamp can’t be dilapidated at runtime, nor can it seem in the stamp
of a world declaration. This code would possibly maybe perchance perchance perchance even be mounted by selling the computed knowledge to a const
after filling the buffer:

construct_slice_comptime.zig
fn getName() []const u8 {
    comptime var buf: [9]u8 = undefined;
    // In practice there would likely be more complex logic here to populate `buf`.
    @memcpy(&buf, "some name");
    const final_name = buf;
    return &final_name;
}
test getName {
    try @import("std").testing.expectEqualStrings("some name", getName());
}
Shell
$ zig test construct_slice_comptime.zig
1/1 construct_slice_comptime.decltest.getName... OK
All 1 tests passed.

Love in earlier variations of Zig, comptime-known consts gather limitless lifetime, and the
restrictions mentioned right here attain no longer apply to them. Therefore, this code functions as expected.

One other that it’s doubtless you’ll perchance perchance perchance maybe factor in failure mode is in code which dilapidated the outmoded semantics to operate global mutable comptime instruct. For
instance, the following snippet attempts to operate a world comptime counter:

global_comptime_counter.zig
const counter: *u32 = counter: {
    var n: u32 = 0;
    break :counter &n;
};
comptime {
    counter.* += 1;
}
Shell
$ zig test global_comptime_counter.zig
docgen_tmp/global_comptime_counter.zig:1:32: error: global variable contains reference to comptime var
const counter: *u32 = counter: {
                      ~~~~~~~~~^
referenced by:
    comptime_0: docgen_tmp/global_comptime_counter.zig:6:5
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

This code emits a compile error in Zig 0.12.0. This spend case is now not any longer and ought to now not ever be supported by Zig: any mutable
comptime instruct ought to be represented in the community.

@fieldParentPtr §

The first argument is eliminated in choose of the spend of the pause result form.

Migration recordsdata:

sample_code
const parent_ptr = @fieldParentPtr(Parent, "field_name", field_ptr);

sample_code
const parent_ptr: *Parent = @fieldParentPtr("field_name", field_ptr);

or

sample_code
const parent_ptr: *Parent = @alignCast(@fieldParentPtr("field_name", field_ptr));

looking out on what parent pointer alignment the compiler is able to show camouflage.
The second develop is extra portable, because it’s that it’s doubtless you’ll perchance perchance perchance maybe factor in for the
@alignCast to be necessary for some targets however no longer others.

Disallow alignment on feature form §

Zig 0.11.0 allowed feature kinds to specify an alignment. Right here’s disallowed in Zig 0.12.0,
on memoir of is it a property of feature declarations and pointers, no longer of feature kinds.

func_type_align.zig
comptime {
    _ = fn () align(4) void;
}
Shell
$ zig test func_type_align.zig
docgen_tmp/func_type_align.zig:2:21: error: function type cannot have an alignment
    _ = fn () align(4) void;
                    ^

@errorCast §

Old releases of Zig incorporated an @errSetCast builtin which performed a security-checked
cast from one error dwelling to another, doubtlessly smaller, one. In Zig 0.12.0, this builtin is changed with
@errorCast. Old uses will continue to work, however to boot to, this unusual builtin can cast
the error dwelling of an error union:

error_cast.zig
const testing = @import("std").testing;

test "@errorCast error set" {
    const err: error{Foo, Bar} = error.Foo;
    const casted: error{Foo} = @errorCast(err);
    try testing.expectEqual(error.Foo, casted);
}

test "@errorCast error union" {
    const err: error{Foo, Bar}!u32 = error.Foo;
    const casted: error{Foo}!u32 = @errorCast(err);
    try testing.expectError(error.Foo, casted);
}

test "@errorCast error union payload" {
    const err: error{Foo, Bar}!u32 = 123;
    const casted: error{Foo}!u32 = @errorCast(err);
    try testing.expectEqual(123, casted);
}
Shell
$ zig test error_cast.zig
1/3 error_cast.test.@errorCast error set... OK
2/3 error_cast.test.@errorCast error union... OK
3/3 error_cast.test.@errorCast error union payload... OK
All 3 tests passed.

@abs §

Old releases of Zig incorporated the @fabs builtin. This has been changed with a peculiar
@abs builtin, which is able to feature on integers to boot to floats:

abs.zig
const expectEqual = @import("std").testing.expectEqual;

test "@abs on float" {
    const x: f32 = -123.5;
    const y = @abs(x);
    try expectEqual(123.5, y);
}

test "@abs on int" {
    const x: i32 = -12345;
    const y = @abs(x);
    try expectEqual(12345, y);
}
Shell
$ zig test abs.zig
1/2 abs.test.@abs on float... OK
2/2 abs.test.@abs on int... OK
All 2 tests passed.

Standard Library §

Windows Expose Line Argument Parsing §

On Windows, the exclaim line arguments of a program are a single WTF-16
encoded string and it’s as much as this system to chop up it into an array of
strings. In C/C++, the entry level of the C runtime takes care of splitting
the exclaim line and passing argc/argv to the main feature.

Previously, ArgIteratorWindows matched the behavior of
CommandLineToArgvW, however it completely looks that CommandLineToArgvW’s behavior
doesn’t match the behavior of the C runtime submit-2008. In 2008, the C
runtime argv splitting
changed how it handles consecutive double quotes
within a quoted argument (it’s now regarded as an escaped quote, e.g.
"foo""bar" submit-2008 would get parsed into foo"bar), and the foundations round
argv[0] had been also changed.

This free up makes ArgIteratorWindows match the behavior of the
submit-2008 C runtime. The motivation right here is roughly the identical as when the
same trade used to be made in Rust,
that is (paraphrased):

  • Fixed behavior between Zig and unusual C/C++ functions
  • Permits users to flee double quotes in a methodology that can perchance even be extra easy

Furthermore, the suggested mitigation for
BatBadBut
depends on the submit-2008 argv splitting behavior for roundtripping of the
arguments given to cmd.exe.

The BadBatBut
mitigation did no longer fetch the 0.12.0 free up cutoff.

Bring-Your-Maintain-OS API Layer Regressed §

Old variations of Zig allowed functions to override the POSIX API layer of the long-established library.
This free up deliberately removes this capacity, with no migration route equipped.

This used to be a mistake from day one. Right here’s the disagreeable abstraction layer to realize this in.

The alternate opinion for right here is to fetch all I/O operations require an IO
interface parameter, similar to how allocations require an Allocator
interface parameter nowadays.

The sort of opinion is now not any longer yet implemented, so functions which require this performance must withhold a
fork of the long-established library until then.

std.os renamed to std.posix §

Migration recordsdata:

sample_code
std.os.abort();

sample_code
std.posix.abort();

In most cases, one must desire to make spend of the increased-stage execrable-platform abstractions in wish to reaching
into the POSIX API layer. For example, std.process.exit is extra portable than
std.posix.exit. You have to most incessantly query the API inner std.posix
to be accessible on a given OS when the OS implements that corresponding POSIX performance.

Ryu Floating-Point Formatting §

Zig 0.12.0 replaces the earlier errol floating level formatting algorithm with one primarily based on
Ryu, a recent algorithm for
changing IEEE-754 floating-level numbers to decimal strings.

The improvements this brings are:

  • Potential to format f80 and f128 kinds
  • More beautiful f16 and f32 formatting
  • Full round-time out make stronger for every drift form
  • Generic backend that can perchance even be dilapidated to print any drift of a frequent choice of bits (much less than or equal to 128 bits)

Behavior Differences:

  • Exponents don’t seem to be any longer padded with a number one 0 to 2-digits and if sure, the trace is now no longer printed:
    errol: 1e+02
    ryu:   1e2
  • Fractional values of 0 are omitted in stout precision mode:
    errol: 2.0e+00
    ryu:   2e0
  • Stout precision output is extra beautiful in all cases varied than f64,
    since we now no longer attain a cast internally to f64:

    # Ryu
    3.1234567891011121314151617181920212E0 :f128
    3.1234567891011121314E0 :f80
    3.1234567891011121314E0 :c_longdouble
    3.123456789101112E0 :f64
    3.1234567E0 :f32
    3.123E0 :f16
    
    ## Errol
    3.123456789101112e+00 :f128
    3.123456789101112e+00 :f80
    3.123456789101112e+00 :c_longdouble
    3.123456789101112e+00 :f64
    3.12345671e+00 :f32
    3.123046875e+00 :f16
  • Furthermore, rounding behaviour in these cases can fluctuate in the mounted
    precision case as the shortest illustration will most incessantly fluctuate:

    # bits:         141333
    # precision:    3
    # std_shortest: 1.98049715e-40
    # ryu_shortest: 1.9805e-40
    # type:         f32
    |
    | std_dec: 0.000
    | ryu_dec: 0.000
    |
    | std_exp: 1.980e-40
    | ryu_exp: 1.981e-40

Performance: ~2.3x performance improvement

Code Dimension: roughly +5KB (2x)

Source for these stats

Transformed HTTP §

First, some truthful easy adjustments:

  • don’t emit Server HTTP header. Let the user add that if they wish to. It be no longer strictly necessary, and arguably a detrimental default.
  • appropriate the error dwelling of finish to no longer gather NotWriteable and MessageTooLong in it
  • offer protection to in opposition to zero-length chunks in Server
  • add missing redirect behavior approach to FetchOptions and fetch it an enum as an different of two fields
  • error.CompressionNotSupported is renamed to error.CompressionUnsupported, matching the naming conference from the final varied errors in the identical dwelling.
  • Removed documentation feedback that had been redundant with self-discipline and form names.
  • Disabling zstd decompression in the server for now; look #18937.
  • Robotically contend with query: 100-continue requests

Subsequent, eliminated the flexibility to heap-allocate the buffer for headers. The buffer for HTTP headers is now frequently equipped by a static buffer. As a , OutOfMemory is now no longer a member of the read() error dwelling, and the API and implementation of Client and Server are simplified. error.HttpHeadersExceededSizeLimit is renamed to error.HttpHeadersOversize.

Lastly, the astronomical adjustments:

As an different, some headers are equipped by narrate self-discipline names populated
whereas parsing the HTTP query/response, and some are equipped by unusual
fields that make stronger passing extra, arbitrary headers. This resulted in
simplification of common sense in a entire lot of locations, to boot to elimination of the
probability of failure in a entire lot of locations. There would possibly maybe be much less deinitialization
code occurring now. Furthermore, it made it now no longer necessary to clone
the headers knowledge building with a opinion to contend with redirects.

http_proxy and https_proxy fields for the time being are pointers because it’s no longer uncommon for them to be unpopulated.

loadDefaultProxies is became initDefaultProxies to keep up a correspondence that it doesn’t in actuality load the rest from disk or from the community. The feature now is leaky; the API user must pass an already instantiated area allocator. Eliminates the must deinitialize proxies.

Earlier than, proxies kept arbitrary units of headers. Now they easiest retailer the authorization stamp.

Removed the duplicated code between https_proxy and http_proxy. Lastly, parsing failures of the atmosphere variables result in errors being emitted in wish to silently ignoring the proxy.

Remodel Server Fully §

Essentially, this removes the poorly named wait, send, finish functions, which all operated on the identical “Response” object, which used to be in actuality being dilapidated as the query.

Now, it appears like this:

  1. std.net.Server.accept() provides you a std.net.Server.Connection
  2. std.http.Server.init() with the connection
  3. Server.receiveHead() provides you a Seek recordsdata from
  4. Request.reader() provides you a body reader
  5. Request.respond() is a one-shot, or Request.respondStreaming() creates
    a Response
  6. Response.writer() provides you a body author
  7. Response.end() finishes the response; Response.endChunked() permits
    passing response trailers.

In varied phrases, the form intention now guides the API user down the staunch route.

receiveHead permits extra bytes to be read into the read buffer, and then will reuse these bytes for the body or the following query upon connection reuse.

respond(), the one-shot feature, will send your entire response in a single syscall.

Streaming response bodies now no longer wastefully wraps every call to jot down with a chunk header and trailer; as an different it easiest sends the HTTP chunk wrapper when flushing. This vogue the user can mute regulate when it happens however it completely also doesn’t add pointless chunks.

Empirically, the usage code is very much much less noisy, it has much less
error facing whereas facing errors extra appropriately, it’s extra evident what
is going on, and it’s syscall-optimum.

sample_code
var read_buffer: [8000]u8 = undefined;
    accept: while (true) {
        const connection = try http_server.accept();
        defer connection.stream.close();

        var server = std.http.Server.init(connection, &read_buffer);
        while (server.state == .ready) {
            var request = server.receiveHead() catch |err| {
                std.debug.print("error: {s}n", .{@errorName(err)});
                continue :accept;
            };
            try static_http_file_server.serve(&request);
        }
    }
sample_code
pub fn serve(context: *Context, request: *std.http.Server.Request) ServeError!void {
    // ...
    return request.respond(content, .{
        .status = status,
        .extra_headers = &.{
            .{ .name = "content-type", .value = @tagName(file.mime_type) },
        },
    });

Furthermore:

  • Uncouple std.http.HeadParser from protocol.zig
  • Delete std.Server.Connection; spend std.net.Server.Connection as an different.
    • The API user provides the read buffer when initializing the
      http.Server, and it’s dilapidated for the HTTP head to boot to a buffer
      for reading the body into.
  • Replace and doc the Dispute enum. No longer is there both “originate”
    and “first”.

std.http.Client has no longer yet been reworked in a identical manner as std.http.Server.

deflate reimplemented from first principles §

In Zig 0.11.0, the deflate implementation used to be ported from the Crawl
typical library, which had a bunch of undesirable properties, similar to
incorrect spend of global variables, feedback about Crawl’s optimizer in Zig’s
codebase, and the requirement of dynamic memory allocation.

Zig 0.12.0 has a peculiar implementation that is now not any longer a port of an unusual codebase.

The unusual implementation is roughly 1.2-1.4x sooner in decompression and
1.1-1.2x sooner in compression. Compressed sizes are truthful powerful the identical
in both cases (provide).

The unusual code uses static allocations for all constructions, doesn’t require
allocator. That is nice especially for deflate the place all constructions,
interior buffers are allocated to the stout size. Runt much less for inflate
the place the earlier verision dilapidated much less memory by no longer preallocating to theoretical
max size array that are on the entire no longer fully dilapidated.

For deflate the unusual implementaiton allocates 395K whereas earlier
implementation dilapidated 779K. For inflate the unusual implementation allocates
74.5K whereas the outmoded one round 36K.

Inflate difference is on memoir of we right here spend 64K historical past as an different of 32K previously.

Migration recordsdata:

sample_code
const std = @import("std");

// To get this file:
// wget -nc -O war_and_peace.txt https://www.gutenberg.org/ebooks/2600.txt.utf-8
const data = @embedFile("war_and_peace.txt");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer std.debug.assert(gpa.deinit() == .ok);
    const allocator = gpa.allocator();

    try oldDeflate(allocator);
    try new(std.compress.flate, allocator);

    try oldZlib(allocator);
    try new(std.compress.zlib, allocator);

    try oldGzip(allocator);
    try new(std.compress.gzip, allocator);
}

pub fn new(comptime pkg: type, allocator: std.mem.Allocator) !void {
    var buf = std.ArrayList(u8).init(allocator);
    defer buf.deinit();

    // Compressor
    var cmp = try pkg.compressor(buf.writer(), .{});
    _ = try cmp.write(data);
    try cmp.finish();

    var fbs = std.io.fixedBufferStream(buf.items);
    // Decompressor
    var dcp = pkg.decompressor(fbs.reader());

    const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
    defer allocator.free(plain);
    try std.testing.expectEqualSlices(u8, data, plain);
}

pub fn oldDeflate(allocator: std.mem.Allocator) !void {
    const deflate = std.compress.v1.deflate;

    // Compressor
    var buf = std.ArrayList(u8).init(allocator);
    defer buf.deinit();
    // Remove allocator
    // Rename deflate -> flate
    var cmp = try deflate.compressor(allocator, buf.writer(), .{});
    _ = try cmp.write(data);
    try cmp.close(); // Rename to finish
    cmp.deinit(); // Remove

    // Decompressor
    var fbs = std.io.fixedBufferStream(buf.items);
    // Remove allocator and last param
    // Rename deflate -> flate
    // Remove try
    var dcp = try deflate.decompressor(allocator, fbs.reader(), null);
    defer dcp.deinit(); // Remove

    const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
    defer allocator.free(plain);
    try std.testing.expectEqualSlices(u8, data, plain);
}

pub fn oldZlib(allocator: std.mem.Allocator) !void {
    const zlib = std.compress.v1.zlib;

    var buf = std.ArrayList(u8).init(allocator);
    defer buf.deinit();

    // Compressor
    // Rename compressStream => compressor
    // Remove allocator
    var cmp = try zlib.compressStream(allocator, buf.writer(), .{});
    _ = try cmp.write(data);
    try cmp.finish();
    cmp.deinit(); // Remove

    var fbs = std.io.fixedBufferStream(buf.items);
    // Decompressor
    // decompressStream => decompressor
    // Remove allocator
    // Remove try
    var dcp = try zlib.decompressStream(allocator, fbs.reader());
    defer dcp.deinit(); // Remove

    const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
    defer allocator.free(plain);
    try std.testing.expectEqualSlices(u8, data, plain);
}

pub fn oldGzip(allocator: std.mem.Allocator) !void {
    const gzip = std.compress.v1.gzip;

    var buf = std.ArrayList(u8).init(allocator);
    defer buf.deinit();

    // Compressor
    // Rename compress => compressor
    // Remove allocator
    var cmp = try gzip.compress(allocator, buf.writer(), .{});
    _ = try cmp.write(data);
    try cmp.close(); // Rename to finisho
    cmp.deinit(); // Remove

    var fbs = std.io.fixedBufferStream(buf.items);
    // Decompressor
    // Rename decompress => decompressor
    // Remove allocator
    // Remove try
    var dcp = try gzip.decompress(allocator, fbs.reader());
    defer dcp.deinit(); // Remove

    const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
    defer allocator.free(plain);
    try std.testing.expectEqualSlices(u8, data, plain);
}

std.posix APIs Invent Form Safety §

For example, let’s watch at std.posix.termios:

  • Add missing API bits to termios and the forms of its fields for all 12 operating systems
  • Honest appropriate API bits on Linux (they had been disagreeable for some CPU architectures)
  • Consolidate std.c definitions
  • Add form safety to all integers

For example previously right here is the methodology it’s doubtless you’ll perchance perchance perchance maybe dwelling fast mode on a tty:

sample_code
const in = std.io.getStdIn();

// copy original settings and restore them once done
const original_termios = try std.posix.tcgetattr(in.handle);
defer std.posix.tcsetattr(in.handle, .FLUSH, original_termios) catch {};

// set immediate input mode
var termios = original_termios;
termios.lflag &= ~@as(std.posix.system.tcflag_t, std.posix.system.ICANON);

// flush changes
try std.posix.tcsetattr(in.handle, .FLUSH, termios);

Now the center portion appears like this:

sample_code
// set immediate input mode
var termios = original_termios;
termios.lflag.ICANON = false;

Right here’s due to the unusual definitions primarily based on packed struct.
Right here’s as an instance the definition of lflag for Linux:

sample_code
pub const tc_lflag_t = switch (native_arch) {
    .powerpc, .powerpcle, .powerpc64, .powerpc64le => packed struct(u32) {
        _0: u1 = 0,
        ECHOE: bool = false,
        ECHOK: bool = false,
        ECHO: bool = false,
        ECHONL: bool = false,
        _5: u2 = 0,
        ISIG: bool = false,
        ICANON: bool = false,
        _9: u1 = 0,
        IEXTEN: bool = false,
        _11: u11 = 0,
        TOSTOP: bool = false,
        _23: u8 = 0,
        NOFLSH: bool = false,
    },
    .mips, .mipsel, .mips64, .mips64el => packed struct(u32) {
        ISIG: bool = false,
        ICANON: bool = false,
        _2: u1 = 0,
        ECHO: bool = false,
        ECHOE: bool = false,
        ECHOK: bool = false,
        ECHONL: bool = false,
        NOFLSH: bool = false,
        IEXTEN: bool = false,
        _9: u6 = 0,
        TOSTOP: bool = false,
        _: u16 = 0,
    },
    else => packed struct(u32) {
        ISIG: bool = false,
        ICANON: bool = false,
        _2: u1 = 0,
        ECHO: bool = false,
        ECHOE: bool = false,
        ECHOK: bool = false,
        ECHONL: bool = false,
        NOFLSH: bool = false,
        TOSTOP: bool = false,
        _9: u6 = 0,
        IEXTEN: bool = false,
        _: u16 = 0,
    },
};

Many extra std.posix APIs had been adjusted in a
identical methodology.

std.builtin Enum Fields Lowercased §

Zig 0.12.0 takes the opportunity to regulate the self-discipline names of some enums in std.builtin to align
with our latest naming conventions, which dictate that enum fields must be snake_case. The next enums gather been updated:

  • std.builtin.AtomicOrder
  • std.builtin.ContainerLayout
  • std.builtin.Endian
  • std.builtin.FloatMode
  • std.builtin.GlobalLinkage
  • std.builtin.LinkMode

World Configuration §

Previously, when one necessary to override defaults, similar to the logging feature dilapidated by std.log, they would must clarify std_options in their root file, like so:

sample_code
pub const std_options = struct {
    pub const logFn = myLogFn;
};

Camouflage how std_options above is a struct form definiton. In this free up std_options is now an instance of std.Options, making the arrangement of defining overrides much less error-inclined.

The code above would watch like this now:

sample_code
pub const std_options: std.Options = .{
    .logFn = myLogFn,
};

And right here is the definition of std.Options to assemble a study what else it’s doubtless you’ll perchance perchance perchance maybe override.

sample_code
pub const Options = struct {
    enable_segfault_handler: bool = debug.default_enable_segfault_handler,

    /// Function used to implement `std.fs.cwd` for WASI.
    wasiCwd: fn () os.wasi.fd_t = fs.defaultWasiCwd,

    /// The current log level.
    log_level: log.Level = log.default_level,

    log_scope_levels: []const log.ScopeLevel = &.{},

    logFn: fn (
        comptime message_level: log.Level,
        comptime scope: @TypeOf(.enum_literal),
        comptime format: []const u8,
        args: anytype,
    ) void = log.defaultLog,

    fmt_max_depth: usize = fmt.default_max_depth,

    cryptoRandomSeed: fn (buffer: []u8) void = @import("crypto/tlcsprng.zig").defaultRandomSeed,

    crypto_always_getrandom: bool = false,

    crypto_fork_safety: bool = true,

    /// By default Zig disables SIGPIPE by setting a "no-op" handler for it.  Set this option
    /// to `true` to prevent that.
    ///
    /// Note that we use a "no-op" handler instead of SIG_IGN because it will not be inherited by
    /// any child process.
    ///
    /// SIGPIPE is triggered when a process attempts to write to a broken pipe. By default, SIGPIPE
    /// will terminate the process instead of exiting.  It doesn't trigger the panic handler so in many
    /// cases it's unclear why the process was terminated.  By capturing SIGPIPE instead, functions that
    /// write to broken pipes will return the EPIPE error (error.BrokenPipe) and the program can handle
    /// it like any other error.
    keep_sigpipe: bool = false,

    /// By default, std.http.Client will support HTTPS connections.  Set this option to `true` to
    /// disable TLS support.
    ///
    /// This will likely reduce the size of the binary, but it will also make it impossible to
    /// make a HTTPS connection.
    http_disable_tls: bool = false,

    side_channels_mitigations: crypto.SideChannelsMitigations = crypto.default_side_channels_mitigations,
};

Pointer Stability Locks §

This provides std.debug.SafetyLock and uses it in typical library hash maps by adding lockPointers() and unlockPointers().

This provides a methodology to detect when an unlawful modification has took space and fear in wish to invoke undefined behavior:

safety_locks.zig
const std = @import("std");

pub fn main() !void {
    const gpa = std.heap.page_allocator;
    var map: std.AutoHashMapUnmanaged(i32, i32) = .{};

    const gop = try map.getOrPut(gpa, 1234);
    map.lockPointers();
    defer map.unlockPointers();

    gop.value_ptr.* = try calculate(gpa, &map);
}

fn calculate(gpa: std.mem.Allocator, m: anytype) !i32 {
    try m.put(gpa, 42, 420);
    return 999;
}
Shell
$ zig build-exe safety_locks.zig
$ ./safety_locks
thread 188810 panic: reached unreachable code
/home/andy/local/lib/zig/std/debug.zig:403:14: 0x1036b4d in assert (safety_locks)
    if (!ok) unreachable; // assertion failure
             ^
/home/andy/local/lib/zig/std/debug.zig:2845:15: 0x10375fb in lock (safety_locks)
        assert(l.state == .unlocked);
              ^
/home/andy/local/lib/zig/std/hash_map.zig:1331:44: 0x1066683 in getOrPutContextAdapted__anon_6584 (safety_locks)
                self.pointer_stability.lock();
                                           ^
/home/andy/local/lib/zig/std/hash_map.zig:1318:56: 0x1037505 in getOrPutContext (safety_locks)
            const gop = try self.getOrPutContextAdapted(allocator, key, ctx, ctx);
                                                       ^
/home/andy/local/lib/zig/std/hash_map.zig:1244:52: 0x103765a in putContext (safety_locks)
            const result = try self.getOrPutContext(allocator, key, ctx);
                                                   ^
/home/andy/local/lib/zig/std/hash_map.zig:1241:35: 0x1034023 in put (safety_locks)
            return self.putContext(allocator, key, value, undefined);
                                  ^
/home/andy/docgen_tmp/safety_locks.zig:15:14: 0x1033fb6 in calculate__anon_3194 (safety_locks)
    try m.put(gpa, 42, 420);
             ^
/home/andy/docgen_tmp/safety_locks.zig:11:36: 0x10341eb in main (safety_locks)
    gop.value_ptr.* = try calculate(gpa, &map);
                                   ^
/home/andy/local/lib/zig/std/start.zig:511:37: 0x1033ec5 in posixCallMainAndExit (safety_locks)
            const result = root.main() catch |err| {
                                    ^
/home/andy/local/lib/zig/std/start.zig:253:5: 0x10339e1 in _start (safety_locks)
    asm volatile (switch (native_arch) {
    ^
???:?:?: 0x0 in ??? (???)
(process terminated by signal)

One thing nice about right here is that whenever you occur to spend the “think capability” variants then such mutations are in actuality smartly-outlined, and don’t dwelling off the train:

assume_capacity.zig
const std = @import("std");

pub fn main() !void {
    const gpa = std.heap.page_allocator;
    var map: std.AutoHashMapUnmanaged(i32, i32) = .{};

    try map.ensureUnusedCapacity(gpa, 2);
    const gop = map.getOrPutAssumeCapacity(1234);
    map.lockPointers();
    defer map.unlockPointers();

    gop.value_ptr.* = calculate(&map);
}

fn calculate(m: anytype) i32 {
    m.putAssumeCapacity(42, 420);
    return 999;
}
Shell
$ zig build-exe assume_capacity.zig
$ ./assume_capacity

Observe-up initiatives that did no longer fetch the free up cutoff:

  • introduce pointer stability safety locks to array lists
  • introduce pointer stability safety locks to MultiArrayList
  • add stack traces to pointer stability safety locks

Variety Machine §

Machine Package Mode §

Makes the zig operate intention very much extra friendly to intention equipment maintainers by introducing Machine Integration Alternate choices.

Let’s discover about this characteristic the spend of
groovebasin
as an instance mission:

Potential to Present Non-mandatory Machine Library Integration §

--- a/build.zig
+++ b/build.zig
@@ -5,18 +5,8 @@ pub fn build(b: *std.Build) void {
     const optimize = b.standardOptimizeOption(.{
         .preferred_optimize_mode = .ReleaseSafe,
     });
-    const libgroove_optimize_mode = b.option(
-        std.builtin.OptimizeMode,
-        "libgroove-optimize",
-        "override optimization mode of libgroove and its dependencies",
-    );
     const use_llvm = b.option(bool, "use-llvm", "LLVM backend");
 
-    const groove_dep = b.dependency("groove", .{
-        .optimize = libgroove_optimize_mode orelse .ReleaseFast,
-        .target = target,
-    });
-
     b.installDirectory(.{
         .source_dir = .{ .path = "public" },
         .install_dir = .lib,
@@ -31,7 +21,22 @@ pub fn build(b: *std.Build) void {
         .use_llvm = use_llvm,
         .use_lld = use_llvm,
     });
-    server.linkLibrary(groove_dep.artifact("groove"));
+
+    if (b.systemIntegrationOption("groove", .{})) {
+        server.linkSystemLibrary("groove");
+    } else {
+        const libgroove_optimize_mode = b.option(
+            std.builtin.OptimizeMode,
+            "libgroove-optimize",
+            "override optimization mode of libgroove and its dependencies",
+        );
+        const groove_dep = b.dependency("groove", .{
+            .optimize = libgroove_optimize_mode orelse .ReleaseFast,
+            .target = target,
+        });
+        server.linkLibrary(groove_dep.artifact("groove"));
+    }
+
     b.installArtifact(server);
 
     const run_cmd = b.addRunArtifact(server);

With this diff plus some identical adjustments in the mission’s dependency tree…

Machine Integration Support Share §

There is a peculiar --help portion:

System Integration Options:
  --system [dir]               System Package Mode. Disable fetching; prefer system libs
  -fsys=[name]                 Enable a system integration
  -fno-sys=[name]              Disable a system integration
  --host-target [triple]       Use the provided target as the host
  --host-cpu [cpu]             Use the provided CPU as the host
  --host-dynamic-linker [path] Use the provided dynamic linker as the host

  Available System Integrations:                Enabled:
    groove                                      no
    z                                           no
    mp3lame                                     no
    vorbis                                      no
    ogg                                         no

The usage of the Machine Integration Alternate choices §

Shell
[nix-shell:~/dev/groovebasin]$ zig build -fsys=z

[nix-shell:~/dev/groovebasin]$ ldd zig-out/bin/groovebasin
    linux-vdso.so.1 (0x00007fff054c7000)
    libz.so.1 => /nix/store/8mw6ssjspf8k1ija88cfldmxlbarl1bb-zlib-1.2.13/lib/libz.so.1 (0x00007fe164675000)
    libm.so.6 => /nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib/libm.so.6 (0x00007fe164595000)
    libc.so.6 => /nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib/libc.so.6 (0x00007fe1643ae000)
    /nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib64/ld-linux-x86-64.so.2 (0x00007fe164696000)

Now, re-slump the exclaim however eliminating -fsys=z:

Shell
[nix-shell:~/dev/groovebasin]$ ~/Downloads/zig/build-release/stage4/bin/zig build

[nix-shell:~/dev/groovebasin]$ ldd zig-out/bin/groovebasin
    linux-vdso.so.1 (0x00007ffcc23f6000)
    libm.so.6 => /nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib/libm.so.6 (0x00007f525feea000)
    libc.so.6 => /nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib/libc.so.6 (0x00007f525fd03000)
    /nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib64/ld-linux-x86-64.so.2 (0x00007f525ffcc000)

Original Delivery Option §

Machine equipment maintainers can provide the unusual --release option with a opinion to
dwelling a tool-extensive need for optimization mode, whereas respecting the utility developer’s different.

  --release[=mode]             Request release mode, optionally specifying a
                               preferred optimization mode: fast, safe, small
Shell
andy@ark ~/d/a/zlib (main)> zig build --release
the project does not declare a preferred optimization mode. choose: --release=fast, --release=safe, or --release=small
error: the following build command failed with exit code 1:
/home/andy/dev/ayb/zlib/zig-cache/o/6f46a03cb0f5f70d2c891f31086fecc9/build /home/andy/Downloads/zig/build-release/stage3/bin/zig /home/andy/dev/ayb/zlib /home/andy/dev/ayb/zlib/zig-cache /home/andy/.cache/zig --seed 0x3e999c60 --release
andy@ark ~/d/a/zlib (main) [1]> zig build --release=safe
andy@ark ~/d/a/zlib (main)> vim build.zig
andy@ark ~/d/a/zlib (main)> git diff
diff --git a/build.zig b/build.zig
index 76bbb01..1bc13e6 100644
--- a/build.zig
+++ b/build.zig
@@ -5,7 +5,9 @@ pub fn build(b: *std.Build) void {
     const lib = b.addStaticLibrary(.{
         .name = "z",
         .target = b.standardTargetOptions(.{}),
-        .optimize = b.standardOptimizeOption(.{}),
+        .optimize = b.standardOptimizeOption(.{
+            .preferred_optimize_mode = .ReleaseFast,
+        }),
     });
     lib.linkLibC();
     lib.addCSourceFiles(.{
andy@ark ~/d/a/zlib (main)> zig build --release
andy@ark ~/d/a/zlib (main)> zig build --release=small
andy@ark ~/d/a/zlib (main)>

This selection also can very smartly be dwelling even supposing the mission’s operate script doesn’t explicitly reveal an optimization
configuration option.

Steer sure of Fetching in Machine Mode §

--system prevents Zig from fetching functions. As an different, a directory of functions
is equipped, populated presumably by the intention equipment supervisor.

Shell
[nix-shell:~/dev/2Pew]$ zig build --system ~/tmp/p -fno-sys=SDL2
error: lazy dependency package not found: /home/andy/tmp/p/1220c5360c9c71c215baa41b46ec18d0711059b48416a2b1cf96c7c2d87b2e8e4cf6
info: remote package fetching disabled due to --system mode
info: dependencies might be avoidable depending on build configuration

[nix-shell:~/dev/2Pew]$ zig build --system ~/tmp/p

[nix-shell:~/dev/2Pew]$ mv ~/.cache/zig/p/1220c5360c9c71c215baa41b46ec18d0711059b48416a2b1cf96c7c2d87b2e8e4cf6 ~/tmp/p

[nix-shell:~/dev/2Pew]$ zig build --system ~/tmp/p -fno-sys=SDL2
steps [5/8] zig build-lib SDL2 ReleaseFast native... Compile C Objects [75/128] e_atan2... ^C

[nix-shell:~/dev/2Pew]$

Sluggish Dependencies §

--- a/build.zig
+++ b/build.zig
-    const groove_dep = b.dependency("groove", .{
-        .optimize = libgroove_optimize_mode orelse .ReleaseFast,
-        .target = target,
-    });
+    if (b.lazyDependency("groove", .{
+        .optimize = libgroove_optimize_mode orelse .ReleaseFast,
+        .target = target,
+    })) |groove_dep| {
+        server.linkLibrary(groove_dep.artifact("groove"));
+    }
--- a/build.zig.zon
+++ b/build.zig.zon
@@ -5,6 +5,7 @@
         .groove = .{
             .url = "https://github.com/andrewrk/libgroove/archive/66745eae734e986cd478e7220664f2de902d10a1.tar.gz",
             .hash = "1220285f0f6b2be336519a0e612a11617c655f78b0efe1cac12fc73fc1e50c7b3e14",
+            .lazy = true,
         },
     },
     .paths = .{
    

This makes the dependency easiest get fetched if it’s in actuality dilapidated. The
operate runner will be rebuilt if any missing slothful dependencies are
encountered.

There would possibly maybe be an error for the spend of dependency() as an different of lazyDependency():

Shell
$ zig build -h
thread 2904684 panic: dependency 'groove' is marked as lazy in build.zig.zon which means it must use the lazyDependency function instead
/home/andy/Downloads/zig/lib/std/debug.zig:434:22: 0x11901a9 in panicExtra__anon_18741 (build)
    std.builtin.panic(msg, trace, ret_addr);
                     ^
/home/andy/Downloads/zig/lib/std/debug.zig:409:15: 0x1167399 in panic__anon_18199 (build)
    panicExtra(null, null, format, args);
              ^
/home/andy/Downloads/zig/lib/std/Build.zig:1861:32: 0x1136dca in dependency__anon_16705 (build)
                std.debug.panic("dependency '{s}{s}' is marked as lazy in build.zig.zon which means it must use the lazyDependency function instead", .{ b.dep_prefix, name });
                               ^
/home/andy/dev/groovebasin/build.zig:33:40: 0x10e8865 in build (build)
        const groove_dep = b.dependency("groove", .{
                                       ^
/home/andy/Downloads/zig/lib/std/Build.zig:1982:33: 0x10ca783 in runBuild__anon_8952 (build)
        .Void => build_zig.build(b),
                                ^
/home/andy/Downloads/zig/lib/build_runner.zig:310:29: 0x10c6708 in main (build)
        try builder.runBuild(root);
                            ^
/home/andy/Downloads/zig/lib/std/start.zig:585:37: 0x10af845 in posixCallMainAndExit (build)
            const result = root.main() catch |err| {
                                    ^
/home/andy/Downloads/zig/lib/std/start.zig:253:5: 0x10af331 in _start (build)
    asm volatile (switch (native_arch) {
    ^
???:?:?: 0x8 in ??? (???)
Unwind information for `???:0x8` was not available, trace may be incomplete

error: the following build command crashed:
/home/andy/dev/groovebasin/zig-cache/o/20af710f8e0e96a0ccc68c47688b2d0d/build /home/andy/Downloads/zig/build-release/stage3/bin/zig /home/andy/dev/groovebasin /home/andy/dev/groovebasin/zig-cache /home/andy/.cache/zig --seed 0x513e8ce9 -Z4472a09906216280 -h

It be allowed to realize the reverse – lazyDependency() when the manifest file doesn’t trace it as slothful.

It be doubtlessly most attention-grabbing tell to frequently spend lazyDependency() in operate.zig.

introduce b.route; deprecate LazyPath.relative §

This provides the *std.Build proprietor to LazyPath so
that slothful paths returned from a dependency would possibly maybe perchance perchance perchance even be dilapidated in the utility’s
operate script with out friction or footguns.

Migration recordsdata:

Source-Relative LazyPath:

sample_code
.root_source_file = .{ .path = "src/main.zig" },

sample_code
.root_source_file = b.path("src/main.zig"),

LazyPath.relative

sample_code
.root_source_file = LazyPath.relative("src/main.zig"),

sample_code
.root_source_file = b.path("src/main.zig"),

Test Runner

sample_code
.test_runner = "path/to/test_runner.zig",

sample_code
.test_runner = b.path("path/to/test_runner.zig"),

The intent for Compile.installHeader and company has frequently been to
bundle the headers alongside an artifact, gather them be set in collectively
with the artifact and get automatically added to the encompass search paths
of modules that hyperlink with the artifact.

In Zig 0.11.0, however, these functions modified the default
install high-stage step of the builder, result in a decision of
sudden results similar to placing in or no longer placing in the headers
looking out on which high-stage operate steps are invoked.

Zig 0.12.0 adjustments it in reveal that set in headers are added to the compile
step itself as an different of editing the high-stage set up step. To contend with the
building of the encompass search route for dependent linking modules, an
middleman WriteFile step responsible for developing the staunch
encompass tree is created and dwelling up the first time a module hyperlinks to an
artifact.

Migration recordsdata:

installHeader now takes a LazyPath:

sample_code
for (headers) |h| lib.installHeader(h, h);

sample_code
for (headers) |h| lib.installHeader(b.path(h), h);

Compile.installConfigHeader has had its second argument eliminated and now
uses the stamp of include_path as its sub route, for parity with
Module.addConfigHeader. Employ
artifact.installHeader(config_h.getOutput(), "foo.h")
in reveal so that you just can dwelling the sub route to something varied.

sample_code
lib.installConfigHeader(avconfig_h, .{});

sample_code
lib.installConfigHeader(avconfig_h);

Compile.installHeadersDirectory/installHeadersDirectoryOptions
gather been consolidated into Compile.installHeadersDirectory, which takes a
LazyPath and permits exclude/encompass filters staunch like InstallDir.

sample_code
lib.installHeadersDirectoryOptions(.{
        .source_dir = upstream.path(""),
        .install_dir = .header,
        .install_subdir = "",
        .include_extensions = &.{
            "zconf.h",
            "zlib.h",
        },
    });

sample_code
lib.installHeadersDirectory(upstream.path(""), "", .{
        .include_extensions = &.{
            "zconf.h",
            "zlib.h",
        },
    });
  • [Breaking] b.addInstallHeaderFile now takes a LazyPath.
  • [Breaking] As a workaround for
    resurrect emit-h, the generated
    -femit-h header is now never emitted even when the user specifies an
    override for h_dir. When you fully need the emitted header, you now
    must attain install_artifact.emitted_h = artifact.getEmittedH() until
    -femit-h is mounted.
  • Added WriteFile.addCopyDirectory, which functions very similar to InstallDir.
  • InstallArtifact has been updated to set up the bundled headers alongide the artifact. The bundled headers are set in to the directory specified by h_dir (which is zig-out/include by default).

dependencyFromBuildZig §

Given a struct that corresponds to the operate.zig of a dependency, b.dependencyFromBuildZig returns that very same dependency. In varied phrases, whenever you occur to’ve already a @imported a depdency’s operate.zig, it’s doubtless you’ll perchance perchance perchance maybe spend this selection to get the corresponding Dependency:

sample_code
// in consumer build.zig
const foo_dep = b.dependencyFromBuildZig(@import("foo"), .{});

This feature will likely be significant for functions that reveal functions from their operate.zig recordsdata that must make spend of their corresponding Dependency (as an instance, for equipment-relative paths, or for working intention instructions and returning the output as slothful paths). This would possibly maybe well perchance perchance perchance be finished by:

sample_code
// in dependency build.zig
pub fn getImportantFile(b: *std.Build) std.Build.LazyPath {
    const this_dep = b.dependencyFromBuildZig(@This(), .{});
    return this_dep.path("file.txt");
}

// in consumer build.zig
const file = @import("foo").getImportantFile(b);

Compiler §

x86 Backend §

The x86 backend is now passing 1765/1828 (97%) of the behavior take a look at suite, compared with the LLVM backend.
It’s far satisfactory alongside that it’s every so usually life like whereas developing, mainly due to the actual fact that it
provides dramatically sooner compilation velocity:

Benchmark 1 (8 runs): zig-0.12.0 build-exe hello.zig
  measurement          mean ± σ            min … max           outliers         delta
  wall_time           667ms ± 26.7ms     643ms …  729ms          1 (13%)        0%
  peak_rss            175MB ± 19.3MB     168MB …  223MB          1 (13%)        0%
  cpu_cycles         3.42G  ±  532M     3.21G  … 4.74G           1 (13%)        0%
  instructions       6.20G  ± 1.05G     5.83G  … 8.79G           1 (13%)        0%
  cache_references    241M  ± 19.9M      234M  …  291M           1 (13%)        0%
  cache_misses       48.3M  ± 1.26M     47.7M  … 51.4M           1 (13%)        0%
  branch_misses      35.3M  ± 4.07M     33.7M  … 45.4M           1 (13%)        0%
Benchmark 2 (26 runs): zig-0.12.0 build-exe hello.zig -fno-llvm -fno-lld
  measurement          mean ± σ            min … max           outliers         delta
  wall_time           196ms ± 5.77ms     187ms …  208ms          0 ( 0%)        ⚡- 70.6% ±  1.7%
  peak_rss           88.7MB ±  721KB    87.8MB … 90.4MB          2 ( 8%)        ⚡- 49.3% ±  4.3%
  cpu_cycles          842M  ± 6.01M      836M  …  866M           1 ( 4%)        ⚡- 75.4% ±  6.0%
  instructions       1.60G  ± 9.62K     1.60G  … 1.60G           0 ( 0%)        ⚡- 74.1% ±  6.5%
  cache_references   56.6M  ±  378K     56.0M  … 57.3M           0 ( 0%)        ⚡- 76.6% ±  3.2%
  cache_misses       8.43M  ±  104K     8.30M  … 8.79M           2 ( 8%)        ⚡- 82.5% ±  1.0%
  branch_misses      7.20M  ± 30.2K     7.15M  … 7.28M           2 ( 8%)        ⚡- 79.6% ±  4.4%

This backend would possibly maybe perchance perchance perchance even be accessed when compiling for an x86_64 aim by passing the CLI choices
-fno-llvm -fno-lld, or by environment the operate intention
flags use_llvm and use_lld on
std.Build.Step.Compile to false. This backend is
now ready to compile many Zig projects, at the side of the compiler itself.

Excellent initiatives until it would possibly perchance perchance perchance even be selected by default as an different of LLVM for debug builds:

  • 100% behavior assessments passing
  • Improved debug info
  • Improved runtime performance

Windows Belongings §

Zig now helps compiling (and execrable-compiling) Windows resource scripts (.rc recordsdata) and .manifest recordsdata, and linking the resulting .res recordsdata into the resource desk of PE/COFF binaries.

  • Add a .rc -> .res compiler to the Zig compiler
  • Add zig rc subcommand, a (execrable-platform) topple-in substitute for rc.exe
  • Add preliminary make stronger for Windows .manifest recordsdata

Look Zig is now also a Windows resource compiler for some spend-cases of this characteristic and little print of how to make spend of it.

Linker §

Zig now helps ELF linking for x86_64, aarch64, and partial make stronger for riscv64.

Dependency on LLD is anticipated to be dropped at some level of the following free up cycle.

The -fno-lld flag would possibly maybe perchance perchance perchance even be dilapidated to make spend of Zig’s linker the place it’s no longer for the time being the default.

Cache Machine §

This moderately anxious bug is mounted now: error: StreamTooLong when recompiling; reproduction provide recordsdata in cache manifest

The fix, which deduplicates recordsdata listed in the cache manifest, makes cache hits very much sooner.
Information level: cache hit building hello world with static musl libc

Benchmark 1 (61 runs): master/zig build-exe hello.c -target native-native-musl -lc
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          81.4ms ± 1.76ms    77.7ms … 87.1ms          1 ( 2%)        0%
  peak_rss           64.6MB ± 77.7KB    64.4MB … 64.7MB          0 ( 0%)        0%
  cpu_cycles         97.2M  ± 1.04M     95.1M  …  101M           1 ( 2%)        0%
  instructions        153M  ± 11.1K      152M  …  153M           0 ( 0%)        0%
  cache_references   2.21M  ± 97.1K     2.05M  … 2.54M           2 ( 3%)        0%
  cache_misses        529K  ± 24.4K      486K  …  600K           4 ( 7%)        0%
  branch_misses       409K  ± 6.45K      397K  …  437K           1 ( 2%)        0%
Benchmark 2 (189 runs): cache-dedup/zig build-exe hello.c -target native-native-musl -lc
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          25.8ms ± 1.26ms    23.9ms … 30.7ms         11 ( 6%)        ⚡- 68.4% ±  0.5%
  peak_rss           65.2MB ± 61.8KB    65.1MB … 65.4MB          2 ( 1%)        💩+  1.0% ±  0.0%
  cpu_cycles         41.2M  ±  608K     40.1M  … 46.3M           4 ( 2%)        ⚡- 57.6% ±  0.2%
  instructions       64.3M  ± 12.6K     64.3M  … 64.4M           2 ( 1%)        ⚡- 57.8% ±  0.0%
  cache_references   1.28M  ± 34.5K     1.21M  … 1.35M           0 ( 0%)        ⚡- 41.9% ±  0.7%
  cache_misses        348K  ± 18.6K      297K  …  396K           0 ( 0%)        ⚡- 34.2% ±  1.1%
  branch_misses       199K  ± 1.34K      197K  …  206K           6 ( 3%)        ⚡- 51.2% ±  0.2%

Bug Fixes §

Stout list of the 502 bug experiences closed at some level of this free up cycle.

Many bugs had been both launched and resolved within this free up cycle.
Most bug fixes are omitted from these free up notes for the sake of brevity.

Comptime Pointer Catch admission to §

Zig has had quite so much of prolonged-standing bugs touching on to accessing pointers at compile time. When trying to access
pointers in a non-trivial methodology, similar to loading a nick of an array or reinterpreting memory, it’s doubtless you’ll perchance perchance perchance maybe at cases
be greeted with a faux sure compile error stating that the comptime dereference required a favorable form to
gather a smartly-outlined layout.

The merge of #19630 resolves this concern. In Zig 0.12.0,
the compiler must now no longer emit incorrect compile errors when doing advanced issues with comptime memory.
This trade also entails some fixes to the common sense for comptime @bitCast; in particular,
bitcasting aggregates containing pointers now no longer incorrectly forces the operation to occur at runtime.

This Delivery Incorporates Bugs §

Zig has
known bugs
and even some
miscompilations.

Zig is immature. Even with Zig 0.12.0, working on a non-trivial mission the spend of Zig will
likely require taking fragment in the improvement route of.

When Zig reaches 1.0.0, Tier 1 Make stronger will operate a bug protection as an additional
requirement.

LLVM 17 §

This free up of Zig upgrades to
LLVM 17.0.6.

Zig now generates LLVM bitcode module recordsdata without lengthen and then passes these to LLVM. This
manner that a Zig compiler constructed with out LLVM libraries can mute make .bc recordsdata,
that will then be passed to clang for compilation.

musl 1.2.4 §

Though musl v1.2.5 is now accessible upstream, this version of Zig
continues to give v1.2.4. The next free up of Zig is anticipated to assemble
the updated musl.

glibc 2.38 §

glibc variations 2.35, 2.36, 2.37, and 2.38 for the time being will likely be found when execrable-compiling.

mingw-w64 §

Essentially primarily based totally on a proposal from Martin Storsjö, Zig now
tracks the latest master division commit of mingw-w64.

Roadmap §

The main theme of the 0.13.0 free up cycle will be compilation velocity.

Some upcoming milestones we are in a position to be practising in the 0.13.0 free up cycle:

  • Making the x86 Backend the default backend for debug mode.
  • Linker make stronger for COFF. Catch rid of dependency on LLD.
  • Enabling incremental compilation for fast rebuilds.
  • Introduce Concurrency to semantic diagnosis to further lengthen compilation velocity.

The postulate right here is that prioritizing sooner compilation will lengthen
model velocity on the Compiler itself, resulting in extra bugs
mounted and aspects finished in the following free up cycles.

It also would possibly maybe perchance perchance perchance doubtlessly result in language adjustments that unblock quick compilation.

Async/Await Characteristic Standing §

Async functions regressed with the free up of 0.11.0 (the earlier
free as much as this one). Their future in the Zig language is unclear due to
extra than one unsolved concerns:

  • LLVM’s inability to optimize them.
  • Third-birthday celebration debuggers’ inability to debug them.
  • The cancellation train.
  • Async feature pointers stopping the stack size from being known.

These concerns are surmountable, however it completely will plot end time. The Zig team is
for the time being bearing in mind varied priorities.

Thank You Contributors! §

Listed right here are the final these that landed no longer much less than one contribution into this free up:

  • Andrew Kelley
  • Jakub Konka
  • Jacob Younger
  • Matthew Lugg
  • Robin Voetter
  • Igor Anić
  • Ryan Liptak
  • Veikka Tuominen
  • antlilja
  • Carl Åstholm
  • Luuk de Gram
  • Michael Dusan
  • Dominic
  • Krzysztof Wolicki
  • Casey Banner
  • Ali Chraghi
  • Nameless
  • Ian Johnson
  • David Rubin
  • Meghan Denny
  • Marc Tiehuis
  • Techatrix
  • Xavier Bouchoux
  • Bogdan Romanyuk
  • Pat Tullmann
  • Frank Denis
  • Tristan Ross
  • Loris Cro
  • Stephen Gregoratto
  • xdBronch
  • Evan Haas
  • John Schmidt
  • Ryan Zezeski
  • expikr
  • Elaine Gibson
  • MrDmitry
  • e4m2
  • Adam Goertz
  • Jan Philipp Hafer
  • Jay Petacat
  • Jonathan Marler
  • Travis Staloch
  • Wooster
  • XXIV
  • joadnacer
  • Jae B
  • Kai Jellinghaus
  • Linus Groh
  • frmdstryr
  • Garrett Beck
  • Josh Wolfe
  • Karl Seguin
  • Sahnvour
  • february cozzocrea
  • fn ⌃ ⌥
  • Carter Snook
  • Eric Joldasov
  • Erik Arvstedt
  • Gordon Cassie
  • HydroH
  • JustinWayland
  • Lucas Santos
  • Luis Cáceres
  • Motiejus Jakštys
  • Nguyễn Gia Phong
  • Paul Berg
  • Pavel Verigo
  • Piotr Szlachciak
  • Prokop Randáček
  • Ratakor
  • Stevie Hryciw
  • SuperAuguste
  • Zachary Raineri
  • amp-59
  • garrisonhh
  • Alex Kladov
  • Ben Crist
  • Eric Eastwood
  • Jan200101
  • Jari Vetoniemi
  • Jeremy Volkman
  • Kang Seonghoon
  • Manlio Perillo
  • Markus F.X.J. Oberhumer
  • Michael Ortmann
  • Pascal S. de Kloe
  • Philipp Lühmann
  • Ruben Dimas
  • Sean
  • Tobias Simetsreiter
  • Tom Read Lowering
  • Tw
  • Vlad Pănăzan
  • cipharius
  • jimying
  • nikneym
  • none
  • ocrap7
  • riverbl
  • snoire
  • tjog
  • xEgoist
  • Abhinav Gupta
  • Adrià Arrufat
  • Ahmed
  • Alex
  • Alexander Heinrich
  • AlliedEnvy
  • Ambareesh “Amby” Balaji
  • Amir Alawi
  • Andre Herbst
  • Andre Weissflog
  • Andreas Herrmann
  • Anubhab Ghosh
  • Arnau
  • Artem Kolichenkov
  • Aven Bross
  • Banacial
  • Becker A
  • Ben Sinclair
  • Brandon Gloomy
  • Brandon Botsch
  • CPestka
  • Chadwain Holness
  • Chris Boesch
  • Chris Burgess
  • Christian Flicker
  • Christiano Haesbaert
  • Christofer Nolander
  • Constantin Bilz
  • Constantin Pestka
  • Craig O’Connor
  • Curtis Tate Wilkinson
  • Daniel A.C. Martin
  • Daniel Guzman
  • David Gonzalez Martin
  • DilithiumNitrate
  • Dillen Meijboom
  • DraagrenKirneh
  • Emil Lerch
  • Emil Tywoniak
  • F3real
  • Federico Stra
  • Felix Kollmann
  • Gregory Anders
  • Gregory Mullen
  • Guillaume Wenzek
  • Gustavo C. Viegas
  • Hashi364
  • Hong Shick Pak
  • Ian Kerins
  • Igor Sadikov
  • IntegratedQuantum
  • Jacob G-W
  • James Chen-Smith
  • Jan Weidner
  • Jeremia Dominguez
  • Jiacai Liu
  • Jim Calabro
  • Joachim Schmidt
  • Joel Gustafson
  • Johan Jansson
  • John Benediktsson
  • Jordyfel
  • Justus Klausecker
  • Kamil T
  • Karl Böhlmark
  • Khang Nguyen Duy
  • Kirk Scheibelhut
  • Koakuma
  • Lateef Jackson
  • Lauri Tirkkonen
  • Lee Cannon
  • Leo Emar-Kar
  • Leonardo Gatti
  • Lewis Gaul
  • LinuxUserGD
  • Littleote
  • Liviu Dudau
  • LordMZTE
  • Luca Ivaldi
  • Lucas Culverhouse
  • Maciej ‘vesim’ Kuliński
  • Marcius
  • Mason Remaley
  • Matt Knight
  • Matthew Wozniak
  • Maximilian
  • Michael Bradshaw
  • Michael Lynch
  • Michael Pfaff
  • Michael Scott
  • Michal Ziulek
  • Mikko Kaihlavirta
  • Minsoo Choo
  • Mustafa Uzun
  • Naboris
  • Nan Zhong
  • Niles Salter
  • Nitin Prakash
  • OK Ryoko
  • PanSashko
  • Paul Jimenez
  • PauloCampana
  • Peng He
  • Phil Richards
  • Prcuvu
  • Purrie
  • Pyry Kovanen
  • Qusai Hroub
  • Rafael Fernández López
  • Rahul Prabhu
  • Reokodoku
  • Robinson Collado
  • Roman Frołow
  • Ryan Barth
  • Samuel Fiedler
  • Samuel Nevarez
  • Scott Schwarz
  • Sebastien Marie
  • Simon Brown
  • Stefan Su
  • Stephen Gutekanst
  • Tim Culverhouse
  • Tobias Simetsreiter
  • Tomasz Lisowski
  • Vitalijus Valantiejus
  • Frosty weather
  • andrewkraevskii
  • arbrk1
  • bfredl
  • binarycraft007
  • castholm
  • cdrmack
  • cfillion
  • crayon
  • cryptocode
  • danielsan901998
  • davideger
  • dbandstra
  • dhash
  • dundargoc
  • emberfade
  • hdert
  • iwVerve
  • jacwil
  • jaina heartles
  • jd
  • leap123
  • lockbox
  • loris
  • mataha
  • melonedo
  • mllken
  • ndbn
  • notcancername
  • pancelor
  • paoda
  • radar roark
  • regeliv
  • salo-dea
  • sammy j
  • tinusgraglin
  • tison
  • vinnichase
  • yunsh1
  • zhylmzr
  • Андрей Краевский

Special due to of us that sponsor Zig.
Because of of ordinary donations, Zig is pushed by the originate provide neighborhood, moderately
than the neutral of developing profit. Severely, these just appropriate-wanting of us sponsor Zig
for $50/month or extra:

  • Josh
    Wolfe
  • Matt Knight
  • Stevie
    Hryciw
  • Jethro
    Nederhof
  • Karrick
    McDermott
  • José M
    Rico
  • drfuchs
  • Joran Dirk Greef
  • Rui
    Ueyama
  • bfredl
  • Simon A.
    Nielsen Knights
  • Stephen
    Gutekanst
  • Derek
    Collison
  • Daniele
    Cocca
  • Rafael
    Batiati
  • Aras
    Pranckevičius
  • Terin Inventory
  • Loïc Tosser
  • Kirk
    Scheibelhut
  • Mitchell
    Hashimoto
  • Brian
    Gold
  • Paul
    Harrington
  • Clark
    Gaebel
  • Bun
  • Marcus
    Eagan
  • Ken
    Chilton
  • Sebastian
  • Will
    Manning
  • Fulcrum Labs
  • Alex Mackenzie at
    Tapestry VC
  • Alok
    Parlikar
  • Viktor
    Tratsevskyy
  • johnpyp
  • Huly® Platform™
  • Reuben Dunnington
  • Isaac Yonemoto
  • Luuk de Gram
  • Auguste Rame
  • Jay Petacat
  • Dirk de Visser
  • Santiago Andaluz
  • Andrew Mangogna
  • Yaroslav Zhavoronkov
  • Christian Wesselhoeft
  • Anton Kochkov
  • Max Bernstein
  • James McGill
  • Luke Champine
  • AG.王爱国
  • Wojtek Mach
  • Nicola Larosa
  • Daniel Hensley
  • cryptocode
  • Erik Mållberg
  • Collin Kemper
  • Fabio Arnold
  • Tom Read Lowering
  • Ross Rheingans-Yoo
  • Emily A. Bellows
  • Justin “J.R.” Hill
  • Mykhailo Tsiuptsiun
  • Kiril Mihaylov
  • Brett Slatkin
  • Sean Carey
  • Yurii Rashkovskii
  • Benjamin Ebby
  • Ralph Brorsen
  • OM PropTech GmbH
  • Alex Sergeev
  • Pierre Curto
  • Kemal Akkoyun
  • Marco Munizaga
  • Josh Ashby
  • Chris 1st Earl Baldwin of Bewdley
  • Malcolm Soundless
  • Viktor Hellström
  • Francis Bouvier
  • Fawzi Mohamed
  • Alve Larsson
  • Nicolas Goy
  • Ian Johnson
  • Carlos Pizano Uribe
  • Rene Schallner
  • Linus Groh
  • Jinkyu Yi
  • jake hemmerle
  • Will Pragnell
  • Nathan Youngman
  • Peter Snelgrove
  • Jeff Fowler
  • Nate
  • Samu
  • foxnne
  • Christian Gibson
  • 11sync.web
  • impactaky
  • Dylan Conway
  • Hlib Kanunnikov
  • merkleplant
  • Omar AlSuwaidi

Read More

Leave a Reply

Your email address will not be published. Required fields are marked *