4 ms·
> Is it an `if` resolved at compile time causing the uncompileable code to be unused and disappear after the Zir stage? Yes. It's exactly that, because Zig ver
by TUSF 4y ago
> Is it an `if` resolved at compile time causing the uncompileable code to be unused and disappear after the Zir stage?
Yes. It's exactly that, because Zig very aggressively evaluates values that are known at compile time. It's as simple as:
if (builtin.os.tag == .linux) {
// Everything here only exists if compiling for Linux.
}
The standard library uses this quite a lot for OS/CPU specific things.
- dleslie 4y agoThat's elegant. It's also not so different than a preprocessor gate, or a function attribute.
- Kwpolska 4y agoI don’t agree that it’s elegant. A preprocessor directive or a function attribute makes it more obvious that the code it covers may be valid only in some conditions. On the other hand, if the language optimizes some `if` statements out, you may have invalid code without noticing — and not only in the case of OS-specific code, but possibly also regular code whose `if` condition became a compile-time constant, even unintentionally/temporarily/by mistake.
- wtetzner 4y agoI think it’s elegant, but it seems to me that the check shouldn’t be evaluated until after type checking. But I’m probably missing something about the way Zig works.
- insanitybit 4y agoI think types are generated via const, so that wouldn't be possible.
- anonymoushn 4y agoThis won't work because the conditionally-compiled platform-specific code is expected to not typecheck (or to use fields that do not exist, etc.) The same feature is also used for specializing generic containers to specific types (an idea that became famous after the resounding success of std::vector<bool>) so that for example arraylists of u8 expose a Writer but arraylists of f64 do not. Most code that is conditional on T == u8 won't typecheck if T != u8. I guess more generally these features are used for implementing fmt, json encoders and decoders, etc. None of these thing would work if code conditional on the type had to typecheck for all types.
- deleted 4y ago[deleted]
- nyberg 4y agoThat's the nice part, it can eliminate switch cases, for loops, while loops, and, or, and all forms of conditional control flow if it's comptime-known without changing the behaviour of the code. This also plays well with `inline for`, `inline while`, and `switch (x) { inline else => |c| {} }` which generate code where the captured value is comptime known; if comptime branching wasn't dealt with as such then you'd end up with code bloat when using the `inline` forms. If it's a comptime constant by "mistake" then it would have resulted in the same wrong behaviour at runtime.
- kllrnohj 4y agoC++ has the same basic thing but in a better way with `if constexpr`. There you're opting in to lazy evaluation and can scrutinize it better without having all your branches everywhere be lazy evaluation such that wrong code is allowed.
- insanitybit 4y agoCan one guarantee this? It makes me think of constexpr in C++, which does something similar and it makes things really confusing about when something is, isn't, or should be constexpr (is_constant_evaluated/is_const).
- anonymoushn 4y agoIt's guaranteed for any values that are comptime-known.