#Why does std.math.pow is using unreachable for ints?

1 messages · Page 1 of 1 (latest)

sullen quarry
#

I am still learning zig so probably I don't really get the exact use cases of unreachable yet.

I check the source code of std.math.pow and I see it only accepts integers and floats to work with.

For integers it simply passes to std.math.powi which is a function that can return an overflow error. However, std.math.pow is using unreachable when there is an error from powi instead of returning that error.

Is there a specific reason for that? I don't really get the reasoning there.

flint forge
#

my guess is that std.math.powi is for cases where the exponentiation may overflow, and std.math.pow is for cases where you know the result will never overflow - kinda like + is for additions that are known to never overflow, and std.math.add is for cases where the addition can overflow

sullen quarry
#

So unreachable forces developer to make sure those cases never happen. Is that what it is for?

flint forge
#

unreachable marks that a certain execution path will never occur - this is you, the programmer, guaranteeing to Zig that you know better than the type system, and some invariant will always hold.
in safe builds (debug, release-safe), Zig does not believe you, and will insert a call to panic if unreachable is somehow reached. in unsafe builds (release-fast, release-safe), Zig will assume you're always correct, and will use unreachable annotations while optimising the code.

sullen quarry
#

I see thanks a lot. I aalready think of some good use cases for it. 😛

flint forge
#

there are many

#

there's also std.debug.assert, which internally is just unreachable. the more of them you sprinkle around, the more optimisations Zig (actually, LLVM) can do, and on debug runs, you can be more confident that your code is correct

sullen quarry
#

I get it. Thanks a lot

#

Ok so one more question to make sure I got unreachable correct.

I used it like below. printErrorAndExit simply exits the process with code 1 however type of readBytes is not narrowed down automatically so compiler doesn't build when I use it as a ?[]u8 . So I know that printErrorAndExit will exit program when there is an error while reading, so I just used unreachable after my function call to get rid of the incorrect error union type there.

What do you think?

    const readBytes = reader.readUntilDelimiterOrEofAlloc(allocator, '\n', std.math.maxInt(i64)) catch {
        printErrorAndExit("Error reading your input");
        unreachable;
    };
flint forge
# sullen quarry Ok so one more question to make sure I got unreachable correct. I used it like ...

that's a nice use of unreachable. if you know that a function will never return under certain conditions, you can put unreachable in the line after.
however! in this case, if printErrorAndExit always terminates the process, it might be better to change its return type. Zig has the type noreturn, which is the canonical uninhabited type, it's a type that has zero values (u8 has 256 possible values, bool has 2, void has 1, noreturn has 0)
it is used to indicate, in a type-system-aware manner, that some computation will diverge, and never terminate normally. a function that never returns (be it because it exits the process, or because it loops forever) can be marked noreturn, making the unreachable unneeded.

noreturn is a weird type to most programmers (most never heard of it!), and so many languages do not have such type within their type system. Zig also does not handle this type perfectly, some open proposals attempt to fix that. if you need further clarification feel free to @ me, there's also this Wikipedia article on it