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

Suggested lint: avoid &mut to *const coercions #12791

Open
joshlf opened this issue May 12, 2024 · 6 comments
Open

Suggested lint: avoid &mut to *const coercions #12791

joshlf opened this issue May 12, 2024 · 6 comments
Labels
A-lint Area: New lints

Comments

@joshlf
Copy link

joshlf commented May 12, 2024

What it does

Recommends avoiding &mut to *const coercions

Advantage

As described in rust-lang/rust#56604, these coercions have surprising behavior that can result in unsoundness in unsafe code. They implicitly first coerce to a shared reference (&), with the result that the resulting raw pointer may have different semantics than a seemingly-equivalent raw pointer produced by first coercing to *mut and then casting to *const. (I say "may" because this depends on how references are formalized in Rust - Stacked Borrows, Tree Borrows, etc.)

Drawbacks

Authors might be relying on this behavior. It strikes me as unlikely to be common - anecdotally, seasoned unsafe programmers I've spoken did not know about this behavior.

Example

let x = &mut 0;
let y: *const i32 = x;

Could be written as:

let x = &mut 0;
let y: *mut i32 = x;
let y = y.cast_const();

cc @RalfJung @jswrenn

@RalfJung
Copy link
Member

As described in rust-lang/rust#56604, these coercions have surprising behavior that can result in unsoundness in unsafe code.

FWIW, I consider this a bug in our spec that I want to fix. Not sure if it's worth making clippy deal with that.

@joshlf
Copy link
Author

joshlf commented May 13, 2024

Agreed, but do we have a concrete timeline on this? My experience with Rust (as with many open source projects) is that it's hard to make promises about how quickly things will move since it's mostly volunteers, and so it's risky to say "let's not do this because soon it won't matter" since "soon" could end up being multiple years.

In order to deal with this reality, I usually prefer to put all of the irons in the fire at the same time so that hopefully something will pan out in relatively short order. E.g., in google/zerocopy#29, we needed some way of computing layout information for an unsized type. Since we weren't sure what we could stabilize at what pace, we "raced" three different approaches (see the "Support deriving KnownLayout for unsized types" bullet):

In the end, we managed to stabilize offset_of!, but we didn't make progress on getting it to support unsized types. We didn't make much progress on stabilizing {size,align}_of_val_raw. We ended up taking the approach of reimplementing the repr(C) layout algorithm manually.

My point in mentioning that example is just to suggest that we might want to write this lint anyway as a hedge unless we're confident that the spec bug will be fixed in a reliably short time frame.

@RalfJung
Copy link
Member

It seems strange to land a lint for something that largely only exists in an experimental, never-approved memory model I proposed.

Are you saying having this issue affect Miri executions (as that's the only thing it affects) is bad enough to warrant a lint?

@joshlf
Copy link
Author

joshlf commented May 13, 2024

I'm confused - does rust-lang/rust#56604 not apply to the current language semantics?

@RalfJung
Copy link
Member

RalfJung commented May 13, 2024

What do you mean by "current language semantics"? We have no aliasing model, other than the experiments implemented in Miri (SB, TB).

It doesn't affect LLVM codegen.

@joshlf
Copy link
Author

joshlf commented May 13, 2024

My point is that the implicit &mut to & coercion does happen on today's Rust, right?

IIUC, your point is that &mut as *mut as *const and & as *const are semantically identical on today's Rust, and that they are only semantically distinguished under SB (and maybe also TB?), so the implicit &mut to & coercion is true-but-irrelevant on today's Rust?

If that's right, then my thinking was that this is a forwards-compatibility issue. But I suppose if we promise to not formally adopt SB or TB (or something else) without first resolving this issue, then I agree that this is probably premature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints
Projects
None yet
Development

No branches or pull requests

2 participants