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

cast to usize poses a portability hazard #10669

Open
oconnor663 opened this issue Jan 22, 2022 · 7 comments
Open

cast to usize poses a portability hazard #10669

oconnor663 opened this issue Jan 22, 2022 · 7 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@oconnor663
Copy link

oconnor663 commented Jan 22, 2022

Zig Version

0.9.0

Steps to Reproduce

Consider this example:

pub fn main() void {
    var x: u64 = 5;
    var y: usize = x;
    _ = y;
}

That compiles just fine on my x86-64 laptop, where usize is 64 bits. But if I run zig build-exe test.zig -target i386-linux for example, it fails to compile, because now usize is 32 btis:

./test.zig:3:20: error: expected type 'usize', found 'u64'
    var y: usize = x;
                   ^
./test.zig:3:20: note: unsigned 32-bit int cannot represent all possible unsigned 64-bit values
    var y: usize = x;
                   ^

The same can also work in reverse. The following example build with -target i386-linux but fails when I target my own machine:

pub fn main() void {
    var x: usize = 5;
    var y: u32 = x;
    _ = y;
}

Expected Behavior

I think usize should be defensive about this. It could assume some minimum and maximum size, and only allow implicit casts that would be valid across its entire cross-platform range. For example, casting a u8 to a usize is presumably always fine, and casting a usize to a u64 is presumably always fine. The most practical range might be 32-64 bits? (#7469 makes it sound like 16-bit support is a question mark, but even if 16-bit support is added, it could still make sense to prioritize 99% of the world's convenience over automatic portability to 16-bit?)

Actual Behavior

See above.

@oconnor663 oconnor663 added the bug Observed behavior contradicts documented or intended behavior label Jan 22, 2022
@Deecellar
Copy link
Contributor

While I agree, this is more on the side of the use wouldn't it.
usize is just the size of the pointer in the platform, and probably need to behave, zig as the language is not the issue in this case, but design for libraries and executables, but it's just my opinion

@InKryption
Copy link
Contributor

@Deecellar

usize is just the size of the pointer in the platform

I mean, it's not just the size of a pointer, it's an operable, arithmetic integer type, which has the same number of bits as a pointer. Coercion like this should likely behave in the cross-platform manner which is expected.

@AssortedFantasy
Copy link

I disagree with the bug tag being used here. I think this is more of a proposal.

As I understand you want the casting rules of usize changed to:
Promotes implicitly only to u64 or larger + will only implicitly promote from a u32 a or smaller.

This makes them somewhat more restrictive than other integer types, and would presumably help prevent people from
writing non-portable code because it would error on both 32 bit and 64 bit platforms.

Its not a terrible idea, but honestly at first glance this seems like a janky rule. If code was meant to be portable presumably diligent authors are already trying to compile it for all platforms they care about and would notice compile errors for other platforms.

Enforcing that library authors not just implicitly forget about 32 bit platforms might be nice. But I still think this isn't a particularly elegant way to do things.

Maybe you could also just totally drop implicitly promotion rules to and from usize / isize. Any casts treating them as an integer must be explicit. But that maybe is taking things too far.

@oconnor663
Copy link
Author

oconnor663 commented Jan 24, 2022

I disagree with the bug tag being used here. I think this is more of a proposal.

I think you're right. My mistake. I think someone with more permissions than me needs to switch it over?

If code was meant to be portable presumably diligent authors are already trying to compile it for all platforms they care about and would notice compile errors for other platforms.

One use case I'm thinking of is "script" code that doesn't usually have dedicated test coverage. Things like build scripts, code generation, and other little utilities that tend to crop up in larger projects. Even a relatively well-tested project might only ever run its build scripts on 64-bit macOS/Windows/Linux, even if it's testing cross-platform builds that include 32-bit targets. It's rare to test a self-hosted build on a 32-bit target like an older Raspberry Pi, since doing that isn't usually supported on e.g. Github Actions. But then when some hobbyist comes along and wants to get something working on their Pi-hole, it turns out that dozens or hundreds of little build breaks have accumulated in the scripts over time.

Similarly, libraries that start out as casual projects often don't include this sort of broad platform coverage (if they include CI testing at all). They may not have any experienced developers involved, until they happen to gain some popularity and pick up contributors. At that point there needs to be an overhaul where all the 32-bit compatibility breaks that have accumulated over time get fixed. In the long term, this issue could turn into a well-known "gotcha" that makes it onto a lot of "best practices" blog posts. That could be fine, as it's realtively easy to fix. But if we see a gotcha coming ahead of time, it's an opportunity to make those future blog posts shorter :)

But I still think this isn't a particularly elegant way to do things.

Yeah I see what you mean. One alternative is that it could just be a warning. That would at least make it easier to change it over time, if the supported platforms lists changes.

@InKryption
Copy link
Contributor

Note:

One alternative is that it could just be a warning.

Zig doesn't have warnings, and it doesn't seem like it will anytime soon, so that certainly doesn't seem viable.

@oconnor663
Copy link
Author

Woops, showing my inexperience here :)

@Vexu Vexu added proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. and removed bug Observed behavior contradicts documented or intended behavior labels Jan 29, 2022
@Vexu Vexu added this to the 0.11.0 milestone Jan 29, 2022
@nektro
Copy link
Contributor

nektro commented Jan 30, 2022

makes it sound like 16-bit support is a question mark, but even if 16-bit support is added, it could still make sense to prioritize 99% of the world's convenience over automatic portability to 16-bit?

no. this lack of portability is in the design of usize/isize and Zig cares about not prioritizing convenience over completeness. this is working as intended.

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

6 participants