-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Lint against &T
to &mut T
and &T
to &UnsafeCell<T>
transmutes
#128351
base: master
Are you sure you want to change the base?
Lint against &T
to &mut T
and &T
to &UnsafeCell<T>
transmutes
#128351
Conversation
The Miri subtree was changed cc @rust-lang/miri |
This comment was marked as resolved.
This comment was marked as resolved.
f27dba0
to
d20e89c
Compare
@bors try |
d20e89c
to
5c1d66e
Compare
…e-cell, r= [crater] Lint against &T to &mut T and &T to &UnsafeCell<T> transmutes Needs a (check-only) crater run as per https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Lint.20against.20.60.26.60-.3E.60.26UnsafeCell.60.20transmutes/near/454868964. r? ghost
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
💔 Test failed - checks-actions |
5c1d66e
to
b62dc4c
Compare
This comment has been minimized.
This comment has been minimized.
b62dc4c
to
59c22c3
Compare
@bors try |
…e-cell, r=<try> [crater] Lint against &T to &mut T and &T to &UnsafeCell<T> transmutes Needs a (check-only) crater run as per https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Lint.20against.20.60.26.60-.3E.60.26UnsafeCell.60.20transmutes/near/454868964. r? ghost
This comment has been minimized.
This comment has been minimized.
59c22c3
to
cc72a92
Compare
This comment was marked as resolved.
This comment was marked as resolved.
@bors try |
…e-cell, r=<try> [crater] Lint against &T to &mut T and &T to &UnsafeCell<T> transmutes Needs a (check-only) crater run as per https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Lint.20against.20.60.26.60-.3E.60.26UnsafeCell.60.20transmutes/near/454868964. r? ghost
☀️ Try build successful - checks-actions |
@craterbot check |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
This comment has been minimized.
This comment has been minimized.
573ee3f
to
2ea0578
Compare
@oli-obk: would you be willing to review? This is covering lots of territory I don't know well, and I imagine there are subtleties that I could easily overlook. |
😭 that's a lot of new code to review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels like it's heading in the right direction.
My main observation is about terminology. To me:
- "casting" is a specific thing, done via
as
orcast
- "transmuting" is a different specific thing, done only via
mem::transmute
- "converting" is an imprecise term that possibly covers both "casting" and "transmuting".
Is that correct? It aligns with the Type Conversions chapter of the Rustonomicon. But this PR tends to use "cast" and "transmute" imprecisely and somewhat interchangeably.
- I think
mutable_transmutes
only triggers onmem::transmute
, butunsafe_cell_transmutes
triggers on bothmem::transmute
and casting. - The crater result mentions
unsafe_cell_reference_casting
. Is that an old name forunsafe_cell_transmutes
? - The error message only mention transmuting.
- The lint descriptions (in doc comments) mention both transmuting and casting in a way that matches my understanding.
is_type_cast
seems to cover both casting and transmuting.
I feel like this needs to be clarified, and the whole commit needs a once-over to ensure these terms are being used precisely and consistently. Should unsafe_cell_transmutes
should be renamed unsafe_cell_conversions
?
Beyond that, mutable_transmutes.rs
has most of the new code. I reviewed it and it seems reasonable, but that kind of traversal is not my forte so it's possible I missed stuff. All the breadcrumb code is quite complicated, and I do I wonder if something like that already exists elsewhere in the compiler for some other kind of error message.
@@ -0,0 +1,163 @@ | |||
use std::cell::UnsafeCell; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests/ui/lint/mutable_transmutes
directory name is slightly misleading because it contains tests that cover both mutable_transmutes
and unsafe_cell_transmutes
. I'm not sure how to fix it, though, and whether it's worth fixing.
#[derive(LintDiagnostic)] | ||
#[diag(lint_builtin_mutable_transmutes)] | ||
pub(crate) struct BuiltinMutablesTransmutes; | ||
#[note] | ||
pub(crate) struct BuiltinMutablesTransmutes<'a> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this one have a Builtin
prefix but UnsafeCellTransmutes
does not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what the Builtin
prefix means (some lints include it while some don't), so I just randomly chose not to include it for the new lint, but not change the existing one.
I'd take a somewhat more broad view of transmuting. Probably I think of that as essentially synonymous with reinterpreting some sequence of bytes as some other type without the presence of any automatic mechanism to reject invalid reinterpretations or to adjust the bytes as needed. So whether we do that with |
I find it bizarre to say that transmuting covers anything other than But even if we accept your definition, this PR lacks internal consistency in its terminology. Sometimes it talks about casts, sometimes about transmuting, sometimes it mentions both. @ChayimFriedman2, can you talk about your understanding of these words and how you have used them? |
Agreed definitely that this PR should be more consistent on this point -- I should have mentioned that. So +1 for catching that in review.
I don't know. I reviewed the Reference text, and I think my definition aligns with it. E.g., it says:
That's directly in line with my remark that:
Elsewhere, it says:
If we were to narrowly define Similarly, in the Nomicon, at the bottom of the page about transmutes, it says:
If we were to say that it's only a "transmute" if you call |
This adds the lint against `&T`->`&UnsafeCell<T>` transmutes, and also check in struct fields, and reference casts (`&*(&a as *const u8 as *const UnsafeCell<u8>)`). The code is quite complex; I've tried my best to simplify and comment it. This is missing one parts: array transmutes. When transmuting an array, this only consider the first element. The reason for that is that the code is already quite complex, and I didn't want to complicate it more. This catches the most common pattern of transmuting an array into an array of the same length with type of the same size; more complex cases are likely not properly handled. We could take a bigger sample, for example the first and last elements to increase the chance that the lint will catch mistakes, but then the runtime complexity becomes exponential with the nesting of the arrays (`[[[[[T; 2]; 2]; 2]; 2]; 2]` has complexity of O(2**5), for instance).
2ea0578
to
ff6a3db
Compare
To me "transmute" is any conversion that changes structures but leaves the bits as-is, and "cast" is specific to |
The job Click to see the possible cause of the failure (guessed by this bot)
|
@rustbot labels +I-lang-nominated The lang FCPed included approval of the name of the lint, so that can't be changed without lang assent. Nominating to discuss. Also, overall, I feel like we've made this PR worse by switching everything to use the word "conversion" when that word is so much more broad. |
Personally I have never seen the word "transmute" used to mean "specifically the function
the
and then uses the word "transmuting" to mean the general concept of a bitwise equivalent value with a different type in future documentation (of which there is a lot) additionally the very start of the docs says
(where this So I would find it odd that you have to use a different phrase to include all semantically equivalent options, even though the namesake of "transmuting" says its equivalent. |
In @rust-lang/opsem we also often use "transmute" to refer to any form of type punning / byte-level reinterpretation of the underlying representation, be it via the |
"It's only a transmute if it's from the transmute region of std; otherwise it's just sparkling unsafety." In all seriousness: I think we should defer to the framing of @rust-lang/opsem here and let "transmute" refer to anything equivalent to a transmute. |
I agree; if it's equivalent to a transmute it's fine to call it a transmute. Especially now that https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/syntax/enum.CastKind.html#variant.Transmute exists in MIR as well, so post-optimization it's possible for things to end up as "literally transmute" even if nobody wrote |
@rustbot labels -I-lang-nominated We discussed this in the lang call today. We agreed that a "transmute" represents the language-level concept, however expressed. We see the library function, For this PR to move forward, the name of the lint should be changed back to that which was FCPed, |
@ChayimFriedman2 I am looking at the diff. Is there a way to refactor this work to make it easier to review? Can this patch be split into smaller, easier to review bits? See our review guidelines. Thanks. |
Much of the discussion can boil down the the following two examples.
The first one is clearly a transmute. AIUI, everyone is saying the second one is also a transmute, albeit one that involves casts (of a pointer, and subsequent dereferencing of that pointer). I guess it makes sense, but I still would find an error message that describes the second one as transmuting a bit surprising. I still think the At this point I will bow out of review duties because I'm about to go on vacation for five weeks. I'm definitely not a T-opsem person, as this whole discussion indicates. My earlier attempt to find an alternative reviewer was met with a crying emoji so I'll let somebody else decide who should review this. Apologies for all the confusion. |
Conversion from
&
to&mut
are and always were immediate UB, and we already lint against them, but until now the lint did not catch the case were the reference was in a field.Conversion from
&
to&UnsafeCell
is more nuanced: Stacked Borrows makes it immediate UB, but in Tree Borrows it is sound.However, even in Tree Borrows it is UB to write into that reference (if the original value was
Freeze
). In all cases crater found where the lint triggered, the reference was written into.Lints (
mutable_transmutes
existed before):Crater summary is below.
cc #111229
r? compiler