Skip to content

Document the behavior of pointer to smaller int casts #729

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

Open
gnzlbg opened this issue Dec 13, 2019 · 5 comments
Open

Document the behavior of pointer to smaller int casts #729

gnzlbg opened this issue Dec 13, 2019 · 5 comments

Comments

@gnzlbg
Copy link
Contributor

gnzlbg commented Dec 13, 2019

Playground:

let x = 42;
let z = &x as *const _ as u8;

As @rkruppe pointed out, this snippet casts a pointer to an int in which the pointer does not fit. AFAICT, the behavior of this operation is not guaranteed anywhere - I suppose it does a truncation. We should document what it does.

cc @Centril @RalfJung


I personally would probably prefer if it was at least a warning that suggests people to write as X as u8 instead, where X is a type in which the pointer precisely fits, e.g., usize and/or u{target_pointer_width} (e.g. u64) - if that is what that cast actually happens to mean, but this is an issue that should be better discussed in rust-lang/rust, once we know what that cast means.

@RalfJung
Copy link
Member

In Miri, this is implemented as truncation. But honestly I had no idea this was even allowed, so I'd be all in favor of linting against this, maybe even as a future-compat lint with the goal of deprecating such casts.

@gnzlbg
Copy link
Contributor Author

gnzlbg commented Dec 13, 2019

Shall we ping the lang team about this?

A related issue is what's the behavior of a pointer to integer cast, where the integer is larger than the pointer. Do we get a zero-extension or a sign-extension, and is the behavior of ptr as usize the same as ptr as isize ?

@Centril
Copy link
Contributor

Centril commented Dec 13, 2019

Truncation does seem reasonable. cc @rust-lang/lang
Before linting or whatnot, we should also figure out how widely used of a pattern this is (with crater).
If it's not used at all, we could e.g. turn this into a hard error immediately.

@petrochenkov
Copy link
Contributor

Some history - rust-lang/rfcs#1052 (comment) and below.

@gnzlbg
Copy link
Contributor Author

gnzlbg commented Dec 13, 2019

@petrochenkov thanks, I'm sadly don't think I'm able to follow that discussion without IRC logs. Things that are hard to follow for me:

  • @arielb1 here argues that "libc does conversions from pointers to size_t a lot", but libc only specifies extern "C" declarations, and has zero code doing ptr-to-address casts. So maybe they are referring to "users of libc" and not libc itself? If so, @petrochenkov is correct here that we do not guarantee that usize matches size_t, which would be a guarantee that's incompatible with our guarantee that usize is pointer-sized, such that users doing FFI actually want to convert pointers to uintptr_t and not size_t. So if that pattern exists, as @petrochenkov argues there, it is an incorrect one, and should be ideally diagnosed at compile-time. (that would be an argument against supporting ptr as {any integer}.

  • @nrc argues here that conversions from pointers to non-pointer-sized integers should be allowed for practical and historical reasons, because they make FFI code simpler to write. I've never seen any code in Rust, C, or C++ that needs to do ptr as u8 to truncate the pointer address, and have a very hard time imagining that such code would be so common that ptr as usize as u8 becomes an ergonomic hurdle that needs fixing.

  • @nikomatsakis explains here that the decision was to allow conversions to any integer type, but have target-dependent lints, which seems like a reasonable stance to have. I guess those lints just never materialized? Is there a tracking issue for those?

I suppose all of this was debated more in detail on IRC, and arguments were given there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants