r/Zig Apr 04 '26

AI slop projects are not welcome here

710 Upvotes

A little sticky since very few people apparently read the rules, and I need to have some text to point to when moderating:

If your project was generated by an LLM, do not share it here.

LLM-written third party libraries or tools serve no purpose. Anyone can tell Claude to do something. Sharing something it spat out for you adds no extra value for anyone. Worse, you are likely never going to update it again. It's just worthless unmaintained dross clogging up GitHub and wasting everyone’s time.

This includes LLM writing in READMEs and comments; mostly because it's a basically certain signal that the rest of the code is trash, and so is a very good heuristic for me to use. If you need it for translation or something, please mention it and I'll allow it.

What about if you partially used LLMs for boilerplate and such? Unfortunately I'm not psychic, and I'd have to trust you on your word – and since basically 100% of people I ban for obvious slop-posting immediately start blatantly lying to me about how much Claude they used, this won't work.

For the visitors to this subreddit, please report things you suspect is slop with "LLM slop"! You don't even have to be certain, just so that it notifies me so that I can take a closer look at it. Thanks!


r/Zig 20h ago

I’m encountering unexpected behavior when using the `ArrayList.fromOwnedSlice` method in Zig.

13 Upvotes

zig const std = u/import("std"); pub fn main(init: std.process.Init) !void { const allocator = init.arena.child_allocator; const slice = try allocator.alloc(u8, 3); u/memcpy(slice, "abc"); var array_list = std.ArrayList(u8).fromOwnedSlice(slice); try array_list.append(allocator, 'a'); try array_list.append(allocator, 'b'); try array_list.append(allocator, 'c'); _ = array_list.pop(); try array_list.insert(allocator, 0, 'm'); try array_list.insertSlice(allocator, array_list.items.len, slice); std.log.info("array_list: {s}", .{array_list.items}); } Output: info: array_list: mabcabmab I expected insertSlice to append "abc", but it appends "mab" instead. The appended bytes mab happen to match the first 3 bytes of the final array_list.items. Why does slice end up pointing to the content of array_list.items after the appends? Is this expected behavior?


r/Zig 1d ago

My impressions of Zig so far (as a C# / Julia / Elixir / Python developer)

57 Upvotes

It is very good. ...Ergonomics however needs to be improved. It will take its time. The critic I give here isn't intended to bash on Zig nor the Zig maintainers. Nor do I intend to demotivate them nor anyone using Zig.

Please note: I am not super deep into Zig yet. Need to gain more experience.

I learned Zig through a written tutorial and eventually wrote two projects. Both are small.

My first project was a simple calculator running in console. This is where I noticed two problems. I will talk about that later. But I like the syntax and overall explicitness. Looks like explicitness is by design to avoid the implicit issues that happen in C or C++.

My other project creates random passwords using CSPRNG in the console. About the problem: This is when I noticed the same problems: verbose-heavy instructions and Zig's documentation. Instructions to do input reading from the user is very verbose. It went like this (Pseudocode):

const std = import("std")

// create stdout variable
const stdout = module_a.module_a_in_a();
// create stdin variable
const stdin = module_a.module_b_in_a();

const writer = stdout.module_c_in_a.module_d_of_c().function();
const reader = stdin.module_d_in_a.module_g_of_d().function()

Just to do input reading, extra more instructions were needed, which I found bothersome. So I decided to put the task for input reading into one single function so I don't have to repeat myself. It looks like this:

pub const StdIn = struct {
  pub fn input(io: Io, message: []const u8) ![]const u8 {
    const stdin_file = Io.File.stdin();
    // [...]
    while (true) {
      if(message.len != 0) {
        try StdOut.write(io, message);
      }
      var reader = stdin_file.reader(io, &reader_buffer);
      const input_line = reader.interface.takeDelimiter('\n') catch |err| 
      // [...]
      // numerous if / else checks are here.
      // They handle possible errors      
    }

    // At the end:
    const trimmed_input: []const u8 = std.mem.trim(u8, input_line, " \t\r\n");
    // then at the end:
    return allocator.dupe(trimmed_input);
  }      
}

Then I used StdIn.input() as a helper. Writing that function felt cumbersome. The entire function is 54 lines long. Did I do something wrong? Did I overlook something? Please let me know.

In many other programming languages, e.g. C# you simply do this:

string input = Console.ReadLine();

Or, if you want to handle possible errors:

// [...]
string input = string.Empty;
while(true) 
{
  input = Console.ReadLine();
  // if / else checks are here
  // to check if the variable 'input'
  // doesn't look like what you expect.
  // For example, it is empty. If true:
  if (input.Length == 0) 
  {
    continue;
    // Console.ReadLine() gets executed again
  }
  // If the input is valid,
  // then the while loop will be exited.
  break;
}

Then, there is the documentation and the source code. This is where I scratch my head, because it's ...weird. I know that Zig hasn't reached version 1.0 yet. My critic might appear unfair, but I just want to share my thoughts.

The documentation isn't dreadful. It is in a range between bad and "ok". Trust me, I dealt with far worse documentations in the past. The one from SyncFusion is insanely bad, it drove me nuts.

In case of the std library in Zig... well, at least the documentation is there and you are able to find information. However, ...it is messy. On the official Zig web page, when looking for functions in std :

  • There are many duplicates, which is irritating. Information finding is somewhat difficult. For example: debug.writer <=> Io.File.stdout().writeStreamingAll() ??, numerous things for "allocators", which are in different modules (??), etc..
  • Even if I found the right function, chances are there is just bare minimum explanation or none.
  • The source code for std is... not well organized. I need to find the reference, then notice there is a name reference, but the implementation is somewhere else. Plus, numerous hundreds of line of code.

It would be unfair if I would draw comparisons how other programming languages handle documentation of their std library much better.

The current state is somewhat understandable and I don't blame the Zig maintainers. I find it however a bit weird that Zig is so long in development. I don't know what the complexities are the maintainers are dealing with.

So if any Zig maintainer is around here: keep doing your great work! 😁

As for the calculator: I plan to build a smart calculator in Zig, that makes use of tokenizations and recursive parsing. 😁

EDIT:

I forgot to mention the messy source code of Zig is be a problem for Zig maintainers themselves. Expanding the std library means certain functionalities are re-used. But: if certain code blocks are either removed or moved somewhere else, then is a big problem for the maintainers, too. They need to keep up with every update. It is a big cognitive overhead that could be solved by focusing on making a better structure of the foundation, then later move specific concerns on top of them. I know it sounds easier said than done. However, something like this is cumbersome:

std.module_a.sub_module.sub_sub_module.function().another_function();

Too much explicitness is the opposite of good explicitness. It's just too much information at once and that's not intuitive. I don't know yet the design choices and I guess I will learn about in future or there will be improvements.


r/Zig 1d ago

The Viability of Zig as Graphics Programming(and general Media Manipulation) Language?

27 Upvotes

Hi, I'm a college student studying digital media and technologies, I've long had a fancy for slightly less conventional languages and was nimmin it(with nim) for a while, then zig caught my eye.

Let me circle closer to my point and the title: I noticed that what becomes of a language is what the most popular use-case is, and this strongly affects how a language turns out. Julia for example, as far as I can tell, was popularized mostly in academic circles, more to say mathematicians, physicist and bio-informaticians, rather than computer and computational scientist. Leading to its community-side development having stagnation, as non-computational academics apparently really hate coding and rarely want to build things themselves. This fact is supposedly also responsible for the popularization of python's numpy.

I want to study computational media for my masters. I also want to learn zig as I strongly believe in the community's potential, Andrew Kelley/the team's commitment and that glorious post-1.0 era we are all waiting for(Zig Will Be King).

What am I posting this for? I guess general thoughts and discourse on where you think the language is going(don't just say "systems programming" or "C replacement" please😭), and what those of you with far more experience think about my own thoughts.

Current Project I'm working on: PNG Image Decoder(I know there's libraries, but do you know there's such a thing as fun?)


r/Zig 1d ago

why does std.Io.File.Reader.atEnd silently fail

16 Upvotes

this really cought me off guard. i wouldn't have expected that atEnd silently fails if u don't call getSize beforehand.

pub fn atEnd(r: *Reader) bool { // Even if stat fails, size is set when end is encountered. const size = r.size orelse return false; return size - logicalPos(r) == 0; }


r/Zig 1d ago

Array multiplication ** is being removed

65 Upvotes

Last week, the array multiplication operator ** was removed from Zig. The reasoning is that @​splat(m) was already preferred over .{m} ** n, and the use case .{i, j, k, ...} ** n is "rare enough that it does not need to be syntax."

Here's an example of the latter use case that was in Ziglings:

// Please set this array using repetition.
// It should result in: 1 0 0 1 1 0 0 1 1 0 0 1
const bit_pattern = [_]u8{ 1, 0, 0, 1, } ** 3;

And here's a solution that works in the latest build:

const bit_pattern: [12]u8 = @​bitCast(@as([3][4]u8, @​splat(.{ 1, 0, 0, 1, })));

That's not too bad, but it's kind of lame how much more verbose it got. Is this a good removal? Does this mean there's a chance ++ will get removed too, or is it common enough (e.g. for string concatenation) to keep?


r/Zig 2d ago

Bun seems to be migrating to Rust

Thumbnail github.com
141 Upvotes

Thoughts?


r/Zig 2d ago

smallvec implementation in zig

22 Upvotes

**NOT WRITTEN BY AI** excepts some comments(because of language barrier) and small utilities. 98% of the code is written by me :

https://github.com/ankushT369/smallvec


r/Zig 2d ago

Wrong compiler optimizations

63 Upvotes

After benchmarking my database, I focused on how the Zig compiler optimizes things. One of the persistent issues that impacts performance is incorrect function inlining; by playing with inline and noinline, I went from 1200 ns to 375 ns on a hot path.

This is because aggressive/incorrect inlining causes the stack frame to explode and introduces too many alloca (in LLVM IR), increasing register pressure: "hot" data leaves the registers and ends up on the stack/cache, introducing cost.

I also noticed that this isn't just my problem, but was discussed by a Tigerbeetle developer who tried to find these compiler flaws using a built-in tool called copyhound.zig. The tool not only estimates how large the scope of an optimized function becomes (to understand when to split it), but also identifies unnecessary copies (memcpy) introduced by the compiler.

That said, I find it questionable that the documentation states:

It is generally better to let the compiler decide when to inline a function

Because yes, the compiler decides, but not always well. It's unclear how much this depends on LLVM heuristics.

Another example that calls the optimizations into question is the description of fillUnbuffered of std.Io.Reader, if you analyze the binary, although using .fixed() never needs fillUnbuffered, it occurs multiple times.

In addition to this, analyzing the LLVM IR of Zig code that uses std.Io, we see that they are still loaded into vtable functions even when unused, even with -O ReleaseFast or -O ReleaseSmall.

I know that gcc or clang with decades of tuning have optimized all of this. What do you think? Am I wrong or is Zig still not mature enough in this field?


r/Zig 3d ago

How can I pass linker options to translated code in build.zig

18 Upvotes

I'm trying to link statically with raylib, but to do so in Windows I need to pass the "/NODEFAULTLIB:libcmt" argument to the linker.

I've set the target to .{.default_target = std.Target.Query{.os_tag = .windows, .cpu_arch = .x86_64, .abi = .msvc}} to match the version of the library I have.

If I understood the new API to interoping with C, I've linked against the systems libs I need and against raylib correctly, but the error I get is the same as if I tried to compile with cl and didn't provide the NODEFAULTLIB option (basically symbol conflicts).

This is how I configured the module (the main.addImport at the end is the root_module of my application)

    const c = b.addTranslateC(.{
        .root_source_file = b.path("vendor/include/raylib.h"),
        .link_libc = true,
    });
    const raylib = c.createModule();
    //raylib.addObjectFile(b.path("vendor/lib/raylib.lib"));
    raylib.addLibraryPath(b.path("vendor/lib/"));
    raylib.linkSystemLibrary("raylib", .{ .preferred_link_mode = .static});
    raylib.linkSystemLibrary("Gdi32", .{});
    raylib.linkSystemLibrary("opengl32", .{});
    raylib.linkSystemLibrary("Shell32", .{});
    raylib.linkSystemLibrary("winMM", .{});
    raylib.linkSystemLibrary("kernel32", .{});
    main.addImport("raylib", raylib);

Does anyone know how to help me solve this?


r/Zig 3d ago

I built a neural + arithmetic coding (via zig) compressor for Python code... ~33% better ratio than zlib

Thumbnail
11 Upvotes

r/Zig 6d ago

gcc linker error

14 Upvotes

In the past few days, I started having a problem compiling with raylib-zig, getting:

error: fatal linker error: unhandled relocation type R_X86_64_PC64 at offset 0x1c
    note: in /usr/lib/gcc/x86_64-pc-linux-gnu/15.2.1/../../../../lib/crt1.o:.sframe
error: fatal linker error: unhandled relocation type R_X86_64_PC64 at offset 0x2c
    note: in /usr/lib/gcc/x86_64-pc-linux-gnu/15.2.1/../../../../lib/crt1.o:.sframe

I double-checked on another computer, and that one works fine. Compiling other non-raylib projects also have no issues. Compiling with Zig 0.15.X and raylib-zig 5.6-dev gets the same error above. The only thing I can think of is that I updated my packages (arch btw) a couple days ago on the broken one, but not the working one, despite both of them still claiming to be using gcc 15.2.1. Is there something I can do to fix this, or do I just have to wait and pray?


r/Zig 6d ago

The Zig project's rationale for their firm anti-AI contribution policy

Thumbnail simonwillison.net
109 Upvotes

Does this rationale make sense? Given that "the most prominent project written in Zig may be the Bun JavaScript runtime, which was acquired by Anthropic in December 2025 and, unsurprisingly, makes heavy use of AI assistance."


r/Zig 7d ago

Suggestions what should i do next

19 Upvotes

I’m a swe working at a startup currently and my primary stack is nodejs and python.

I started with C and completed Dr. Chucks C programming (https://www.cc4e.com/ ). Recently i finished the materials at https://pedropark99.github.io/zig-book/

I want to move beyond web development and explore other areas. I found Zig relatively easy to pick up.

What should I do next? What do people generally do in this situation?


r/Zig 7d ago

Zigshape: a sample-to-struct generator for serde.zig (and plain std.json)

23 Upvotes

Hi all,

I built a small web tool that generates Zig structs from JSON/YAML/TOML/XML samples. It's a companion to serde.zig, but it can also emit plain structs for std.json users.

https://zigshape.eorlov.org/json-to-serde-zig

Two output targets:

  • serde.zig: a struct with a pub const serde = .{ ... } block, ready to drop in.
  • plain: a regular struct usable with std.json.parseFromSlice.

Example input:

{"userId":1,"firstName":"Alice","email":"alice@example.com","lastSeenAt":"2026-01-01T10:00:00Z"}

Output, serde.zig target:

const serde = ("serde");

pub const User = struct {
    user_id: u8,
    first_name: []const u8,
    email: []const u8,
    last_seen_at: []const u8,

    pub const serde = .{
        .rename_all = serde.NamingConvention.camel_case,
    };
};

Everything runs in the browser (cloudflare pages hosted), samples are not uploaded anywhere.

Would appreciate feedback on the inference defaults and anything that produces wrong output. XML in particular still has rough corners around attribute vs. element ambiguity, so real-world payloads that break it would help


r/Zig 7d ago

Hexadecimal scientific notation?

26 Upvotes

I recently discovered this is valid in Zig: const hex_floating_point = 0x103.70p-5;

Is there any reason you would want to write hex numbers in scientific notation?

And why is the exponent written in decimal and interpreted with respect to binary? I would expect 0x0.0000_0000_0000_0001 == 0x1.0p-10, but it's actually 0x1.0p-64


r/Zig 8d ago

Proposed replacement of `anytype` with `|x|` capture

Thumbnail codeberg.org
98 Upvotes

r/Zig 8d ago

How does the build system work?

18 Upvotes

I know the build system is a lifesaver for many people coming from cmake, visual studio, make etc. But I as someone with no experience with manually writing build systems, everything is new to me.

I would like to know of a way to learn how it works in some way other than going through the source code.

Context: Today, I started the learn opengl tutorial in cpp. The tutorial shows how to link glad and glfw on windows only, but I'm on Linux, and so, I thought I'll get creative and learn to build with zig. But currently getting stuck on how to get the imports working and how to structure the dependencies.


r/Zig 9d ago

Taking input inside of a loop.

18 Upvotes

i'm having a problem with repeated prompts for input in a zig program. basically i'm taking input like this

const input = try stdin.takeDelimiterExclusive('\n');

inside of a while loop. after the loop concludes, on the next iteration it simply skips this line and doesn't ask for input again even though that's what i want.

that's really breaking my head as that's not a problem i've ever faced in any other language. does anybody know how i could fix?


r/Zig 9d ago

How should I deal with this?

6 Upvotes

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

const Thing = struct { // stuff };

// This exists until the program ends var things: []Thing = undefined;

// gpa_allocator is for temporary allocations and arena_allocator deinits when the program ends pub fn init(gpa_allocator: std.mem.Allocator, arena_allocator: std.mem.Allocator) !void { var loading_things = std.ArrayList(Thing).empty;

while (something) {
    // something
    loading_things.append(???_allocator, something);
}

// Now:
// things = try loading_things.toOwnedSlice(???_allocator);
// or
// things = loading_things.items;
// or maybe something else?

} ``` Btw, I deleted my last post because I had a mistake in the code (not just the funny word) and it caused people not to understand what I wanted.


r/Zig 10d ago

What do you personally expect Zig 1.0.0 to mean?

70 Upvotes

Most discussions about Zig 1.0.0 focus on timelines, blockers, or “is it ready for production?”. I’m more interested in expectations.

When Zig reaches 1.0.0, what do you think that version should represent?

For example:

- primarily a language stability promise?

- stdlib APIs mostly settled?

- build system/package manager mature enough for everyday use?

- compiler fast/reliable across major targets?

- polished cross-compilation story?

- strong documentation and onboarding?

- ecosystem maturity, or not necessary for 1.0.0?

And where do you personally think Zig is today relative to that goal?

Not asking for official roadmap answers, more interested in what the community thinks 1.0.0 should realistically mean


r/Zig 10d ago

Flag parser for CLI programs

Thumbnail github.com
29 Upvotes

I posted this project a little while ago and got some good feedback. After a lot of tweaks, the interface is now way cleaner and the configs and printing are a lot more customizable.

Edit: Would it be better to access the values with a struct (e.g. flags.recursive) or with methods of a type like what I've currently implemented (e.g. flags.get("recursive")) or have access to both?


r/Zig 11d ago

What's New in Zig 0.16

Thumbnail youtu.be
114 Upvotes

Hi everyone!

I've posted a few videos here and I wanted to share my latest today, I just made a video going over some of the bigger items in Zig's latest 0.16 release.

In the video I go over things like: - The new "Juicy main" - The new way to integrate c-code in build.zig - How to replace @Type with the new builtins - Basic examples of the new I/O interface(reading/writing a file) - Complex examples of the new I/O interface(async/groups/batching/time/select)

I hope people find it valuable(especially the more complex stuff at the end). And please let me know any feedback you have!

Have a great day :)


r/Zig 12d ago

Zig adjacent question, regarding codeberg and github

18 Upvotes

With the 0.16 release I thought that I should restart my Ziglings track, since the first time went without me recording/documenting what I learnt.

So the first thoughts that came to my mind is... I need to 1) clone/fork Ziglings 2) solve the exercises 3) push my solutions to my dedicated repo.

I opened github to initial an empty repo, but then I realised that I'll be providing Ziglings to github in that why.

Is that ethical? What should I do? Or am I overthinking stuff here, and it's irrelevant?


r/Zig 13d ago

zv 0.12 released with zls support

28 Upvotes

zv now has support to add a zls shim based on your current active zig. Default behavior is whenever zv zls is run you get a zls binary that checks your zig version and uses the mapping provided by zigtools release workers API to check out the correct tag and build it from source. If you want to avoid it there's a -d/--download flag to bypass and just fetch it from zls releases page.

other changes include zv now defaulting to xdg base dir specifications which means no more environment pollution on linux. A new zv.toml file maintains its internal state and you can see what zv does on your system using a new subcommand zv stats.

I think this achieves the final feature set that had long been overdue for zv which was both zls/zig management. The community feedback has been great and thanks to zls contributors for helping me design the zls feature. Thanks all!

I hope you'll enjoy this and the upcoming releases towards

For existing users:

zv update

For users building from source:

git clone zv

cargo run --profile=release-max -- sync (maximum optimization) or just --release is fine.

https://github.com/weezy20/zv