Hacker Newsnew | past | comments | ask | show | jobs | submit | AndyKelley's commentslogin

Originally, Zig's type system was less disciplined in terms of the "zero" type (also known as "noreturn").

This was proposed, discussed, and accepted here: https://github.com/ziglang/zig/issues/3257

Later, Matthew Lugg made a follow-up proposal, which was discussed both publicly and in ZSF core team meetings. https://github.com/ziglang/zig/issues/15909

He writes:

> A (fairly uncontroversial) subset of this behavior was implemented in [the changeset we are discussing]. I'll close this for now, though I'll probably end up revisiting these semantics more precisely at some point, in which case I'll open a new issue on Codeberg.

I don't know how evident this is to the casual HN reader, but to me this changeset very obviously moves Zig the language from experimental territory a large degree towards being formally specified, because it makes type resolution a Directed Acyclic Graph. Just look at how many bugs it resolved to get a feel for it. This changeset alone will make the next release of the compiler significantly more robust.

Now, I like talking about its design and development, but all that being said, Zig project does not aim for full transparency. It says right there in the README:

> Zig is Free and Open Source Software. We welcome bug reports and patches from everyone. However, keep in mind that Zig governance is BDFN (Benevolent Dictator For Now) which means that Andrew Kelley has final say on the design and implementation of everything.

It's up to you to decide whether the language and project are in trustworthy hands. I can tell you this much: we (the dev team) have a strong vision and we care deeply about the project, both to fulfill our own dreams as well as those of our esteemed users whom we serve[1]. Furthermore, as a 501(c)(3) non-profit we have no motive to enshittify.

[1]: https://ziglang.org/documentation/master/#Zen

It's been incredible working with Matthew. I hope I can have the pleasure to continue to call him my colleague for many years to come.


Where does the name "zero type" come from? In type theory this is called an "empty" type because the set of values of this type is empty and I couldn't find (though I have no idea where to start) mention of it as a "zero" type.

This stuff is foundational and so it's certainly a priority to get it right (which C++ didn't and will be paying for until it finally collapses under its own weight) but it's easier to follow as an outsider when people use conventional terminology.


I think rust calls them "zero sized types".

The ZSTs are unit types. They have one value, which we usually write as just the type name, so e.g.

    struct Goose;

    let x = Goose; // The variable x has type Goose, but also value Goose, the only value of that type
The choice to underscore that Rust's unit types have size zero is to contrast with languages like C or C++ where these types, which don't need representing, must nevertheless take up a whole byte of storage and it's just wasted.

But what we're talking about here are empty types. In Rust we'd write this:

    enum Donkey {}

    // We can't make any variables with the Donkey type, because there are no values of this type and a variable needs a value

No, that’s a different thing. “noreturn” is like Rust’s “never” type (spelled as an exclamation mark, !). Also known as an “uninhabited type” in programming language theory.

Note that Rust's ! isn't stabilized, however you can (in stable Rust, today) make your own empty/ uninhabited types, yours just isn't "the" canonical empty type for the language, and so the type arithmetic won't necessarily see that it's the same thing in some cases if that matters.

Rust's core::convert::Infallible is such a type, representing in that case the error type for conversions which have no errors. For example, we can try to convert most numeric types into a 16-bit unsigned type, and obviously most of them can fail because your value was too big or negative or whatever. u16 however obviously never fails, the conversion is a no-op, nevertheless it would be stupid if we can't write generic code to convert it - so of course we can, and if we wrote generic error handling code, that code is dead for the u16 case, we can't fail, the use of empty types here justifies the compiler saying OK, that code is dead, don't emit it. Likewise converting u8 to u16 can't fail - although it's slightly more than a no-op in some sense - and so again the error handling is dead code.


I see. I can not give more insightful answer here then. From personal experience, I've noticed with 0.16 with the std.Io async stuff that you cannot do:

   io.concurrent(foo, .{});
where foo's return type is `error{foobar}!noreturn`, because the compiler crashes when it tries to use that type as a std.Io.Future(T)'s struct field. Might be related or not.

It is indeed (somewhat) related, and in fact that was fixed by this PR: https://github.com/ziglang/zig/issues/25771

Thanks for the reply Andrew, I certainly did not mean to imply any issues with trustworthiness for Zig users or prospective adopters. Also, I absolutely did not intend to imply any negatives toward Zog’s evolution or this particular development on the compiler’s internals.

I enjoy all of the process and implementation content, i.e. videos, podcast, and blogs that yourself and contributors have provided through various platforms over the years. I made a comment from a relatively u informed place and it seems to have been taken as a negative remark on Zig or the language and compiler’s development. Apologies if it was seen that way yourself or other contributors.

As for Matthew, the work both planning and implementing these changes was clearly a large undertaking and I certainly applaud that and hope no one thought otherwise.


Zog? What the hell man.

I don't use Zig (is not a language for me), but I like to read/watch about it, when you or others talk about the language design and the reasons behind the changes.

Thanks for your and the Zig team work.


> Zig the language from experimental territory a large degree towards being formally specified

Great to hear; I look forward to reading the language spec one day.


You're the man Kelley, don't let the doomers get to you

It's not a great tip because there are features that exist specifically to reduce development iteration cycle latency without compiling for the wrong target.

Please refer to https://ziglang.org/download/0.15.1/release-notes.html#Incre...

This has nothing to do with agentic engineering. This is just normal software development. Everybody wants faster compilation speed


I propose let's break up a bunch of these monopolies to give you and your colleagues more options, more competition for your resume.

invitation tree. lobste.rs already has it, works great.


bitpacked structs, good enums, arbitrary sized integers, optionals + non-nullable pointers, fast compiler, zig fmt, unit testing, ability to use standard library and the rest of the third-party ecosystem on freestanding, std.ArrayList, std.AutoArrayHashMap, std.MultiArrayList, std.crypto, more productive type system, comptime, SIMD, slices, labeled switch continue, error handling, custom panic handler, stack traces on freestanding, error return traces, zero bit types, the build system, package management, aligned pointers, untagged union safety, multi-object for loops, inline switch cases, semantically guaranteed inline functions, inline loops


In Zig, error codes are fundamentally a control flow construct, not a reporting mechanism.

The pattern here is to return something like error.Diagnostics for all errors that have been reported via diagnostics.

The only reason you'd have a different error code would be if the control flow should be different. For example error.OutOfMemory makes sense to be separate because it's a retryable error, which means it should be handled by different control flow.


Thanks Andy.

Would you endorse the pattern I described in my article if the calling code could have other uses for the diagnostic info than just logging?

In my project I decided that the CLI main should be the place with a reporting mechanism. All the internal code is agnostic to how errors are handled. Many errors could be retried, even if they are currently not, and in some cases you also need extra diagnostic data in order to retry. For example if 1/4 plugins fails to load, I would need to know which one failed to ask the user interactively where to find it or whether to skip it before retrying. There's a few different errors like this, and layers between the handling code and the error source code, which is how I ended up with the union(enum) diagnostic keyed by error code pattern.

It seems that "error codes aren't a reporting mechanism", practically speaking, means that internal application code should just log its own error and return a generic error code that bubbles up unhandled out of main. You decided that this wasn't ok for allocation failures and encourage retrying those, which I find to be inspiring, but apparently most types of application errors are fine to essentially log and ignore. So that is confusing.

I love Zig, and look up to you a lot, so thanks for all your efforts over the years!


Do you think it would fundamentally be a mistake to thread data along with error type through the error return path, or is it just that it costs too much say from a calling convention perspective or some other technical reason? Is it related to ownership?


100% agreed.


flagged for being slop


Sorry to bother you, but I couldn't find any news on this, only a comment you made back in 2018 on GitHub; do you know if the HTTP APIs in Zig's standard library are here to stay, or if some of them might be removed? Another commenter wrote that the HTTP client is used for Zig's package management, but there is also the HTTP server.


HTTP client and server stay for sure.


No ads on Wikipedia tho, not even after 25 years.


The first fundraising banner on wikipedia was in 2003. That is unquestionably an advertisement, and not even an ethical one given the misleading nature of their campaigns these days.


I’m going to say this is a different ballpark. They are fundraising for themselves.. on their own website..

That’s quite different from shoving ads in your face where it doesn’t belong. Like an ad for Copilot on a YouTube video.

IMO it’s distinct.


never thought I’d see fundraising compared to ads but here we are… :)


Do you not think those intrusive banners and popups implying that Wikipedia is about to imminently go broke unless you give them money, are ads?


I think you're letting pedantry hinder you from seeing a useful pattern.


I shall take that as a no, then.

I don't think it takes pedantry to think advertising in order to solicit funds for a non-profit is still advertising.

If anything the criteria I would apply is does it diminish the user experience while attempting to motivate the viewer to act in a manner that benefits the advertiser.

May I ask why you do not consider it advertising? Is it because it is asking for donations? Because it is a non-profit? If so, why would those factors exempt them?

I am certainly not alone in thinking their fundraising campaigns are intrusive https://news.ycombinator.com/item?id=33175098


As an example, a line that they don't cross, but a for-profit company absolutely would, is compromising the integrity of the encyclopedia articles. For example, a marketing department would pay a lot of money for Wikipedia to delete or soften https://en.wikipedia.org/wiki/Controversies_of_Nestl%C3%A9 but they'll never do that, not for profit at least.


It's about who they're fundraising for. Wikipedia fundraising for Wikipedia is fundamentally different than selling out ad space to the highest bidder.


I've always admired your work, Walter. Keep it up!


Thank you for the kind words, Andy!


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: