Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: remove @boolToInt in favor of @bitCast #15794

Closed
wooster0 opened this issue May 20, 2023 · 9 comments
Closed

Proposal: remove @boolToInt in favor of @bitCast #15794

wooster0 opened this issue May 20, 2023 · 9 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@wooster0
Copy link
Contributor

wooster0 commented May 20, 2023

As @ifreund pointed out in #7950, @bitCast can serve the function of @boolToInt just fine: #7950 (comment):

const std = @import("std");

pub fn main() void {
    std.debug.print("{}\n", .{@bitCast(u1, true)}); // 1
    std.debug.print("{}\n", .{@bitCast(u1, false)}); // 0
}

The purpose of @boolToInt is to serve as a branchless alternative to if (x) 1 else 0 because in that case you have to depend on the optimizer to not emit a branch.

Advantages

  • Language simplification and easier implementation
  • One less way to do something; @bitCast(u1, x) already works
  • One less thing to keep in your head if you keep the builtins in your head
  • You always know what you get: a u1, whereas with @boolToInt currently you can get u1 or comptime_int
  • Logical and straightforward
  • Encourages the use of @bitCast for doing other things the smart way, too
  • Don't make a simple boolean to integer conversion seem special; it's not. It's one of many other things @bitCast can do easily.

Disadvantages

  • Non-existence of the specialized @boolToInt might make it harder to remember that you should use @bitCast/@boolToInt instead of if (x) 1 else 0. But one could argue if you don't keep all builtins in your head this doesn't matter anyway.
    If we wanted to remind people we could even add a little note to the docs of @bitCast in the langref but ultimately this is just one of many things that are expected to work with @bitCast so I wouldn't even say this is noteworthy. So, this point can basically be disregarded.
  • 2 more characters and 1 more keystroke:
    @bitCast(u1, x) // 19 keystrokes
    @boolToInt(x)   // 18 keystrokes

If, like the other @*to* builtins, @boolToInt provided additional safety I would understand its existence but as it stands it doesn't really provide anything that @bitCast doesn't.

@Jarred-Sumner
Copy link
Contributor

Jarred-Sumner commented May 21, 2023

I wish it would expand the size if you add two together when the destination type is a larger size.

This code panics:

pub export var counter: usize = 0;
pub export var dynamic_bool: bool = true;

test {
    counter += @boolToInt(dynamic_bool) + @boolToInt(dynamic_bool);
}

Similarly, I wish it was @as instead of @bitCast or @boolToInt

@mlugg
Copy link
Member

mlugg commented May 21, 2023

@Jarred-Sumner

I wish it would expand the size if you add two together when the destination type is a larger size.

That's essentially widening arithmetic, which is a completely separate proposal, unrelated to @boolToInt itself.

Similarly, I wish it was @as instead of @bitCast or @boolToInt

This would either a) break the very basic rule that @as is equivalent to implicit coercion or b) hugely weaken type safety around bools (which I doubt is something anyone wants). For clarity's sake, converting a bool to an int should not be an implicit operation.

@Jarred-Sumner
Copy link
Contributor

Jarred-Sumner commented May 21, 2023

@Jarred-Sumner

I wish it would expand the size if you add two together when the destination type is a larger size.

That's essentially widening arithmetic, which is a completely separate proposal, unrelated to @boolToInt itself.

Similarly, I wish it was @as instead of @bitCast or @boolToInt

This would either a) break the very basic rule that @as is equivalent to implicit coercion or b) hugely weaken type safety around bools (which I doubt is something anyone wants). For clarity's sake, converting a bool to an int should not be an implicit operation.

The status quo is that adding two runtime-known bool's will crash your program or cause undefined behavior. That is a footgun.

I'm not super opinionated about the solution, only that this is a small thing that makes it harder to write reliable software in Zig.

@tisonkun
Copy link
Contributor

tisonkun commented May 21, 2023

You always know what you get: a u1, whereas with @boolToInt currently you can get u1 or comptime_int

I'm working on #15701 so that @boolToInt always returns u1. This can be a pioneer step for this proposal (to ensure all usage of @boolToInt expect a u1, we found several issue in #15701).

BTW, to "simplify" the language means also we should clean up existing code dependency to @boolToInt.

To be clear, I'm +1 for this proposal as it works like a charm - I like it.

@recursivetree
Copy link

I'm not in favor of this, @boolToInt is way more descriptive of what it does than @bitCast. Additionally, is it guaranteed that a bool will always be represented as an integer internally? I haven't studied the wasm or spirv backend, but it wouldn't surprise me if they support bools natively rather than just bits

@ifreund ifreund added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label May 21, 2023
@ifreund ifreund added this to the 0.12.0 milestone May 21, 2023
@andrewrk
Copy link
Member

@bitCast from bool to u1 should indeed work.

However, remember that #5909 is also accepted, which means that @bitCast will lose its destination type parameter. This will make @boolToInt be more useful than @bitCast for bools for two reasons:

  1. In the common situation that the destination type is a wider integer than 1-bit, @boolToInt would have the desired behavior, while @bitCast would be a compile error, or require @as(u1, @bitCast(b)) in order to be equivalent.
  2. @boolToInt makes it become a compile error if the operand changes from bool to another type, whereas @bitCast would continue to convert between the types even though the operand is no longer a bool. Sometimes this is what you want, sometimes it's not. And that's why there are two ways to do it.

@andrewrk andrewrk closed this as not planned Won't fix, can't repro, duplicate, stale May 23, 2023
@andrewrk andrewrk modified the milestones: 0.12.0, 0.11.0 May 23, 2023
@Flecart
Copy link

Flecart commented Sep 16, 2023

Hello, I can't find the function @boolToInt anymore, has it been removed?

@Vexu
Copy link
Member

Vexu commented Sep 16, 2023

It was renamed to @intFromBool.

@Flecart
Copy link

Flecart commented Sep 16, 2023

@Vexu thank you

@tuket tuket mentioned this issue Aug 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

9 participants