-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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.
Hm, just makes me wonder if there are any other wrong assumptions encoded in the lint...
|
8c137f7
to
573ee3f
Compare
@rfcbot reviewed |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
Since we haven't heard from the reviewer... r? compiler |
This comment has been minimized.
This comment has been minimized.
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).
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.
@@ -1,8 +0,0 @@ | |||
// Tests that transmuting from &T to &mut T is Undefined Behavior. |
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 is this test removed?
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.
Maybe because there's more comprehensive testing in another file now?
@@ -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?
@@ -224,9 +225,39 @@ pub(crate) struct BuiltinConstNoMangle { | |||
pub suggestion: Span, | |||
} | |||
|
|||
// This would be more convenient as `from: String` and `to: String`, but then we'll ICE for formatting a `Ty` | |||
// when the lint is `#[allow]`ed. |
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 read this comment several times, but I still don't really understand it. Explain some more, perhaps? Also, the comment talks about "from"/"to" but the fields are "before"/"after", which is confusing.
@@ -0,0 +1,718 @@ | |||
//! This module check that we are not transmuting `&T` to `&mut T` or `&UnsafeCell<T>`. |
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 module check that we are not transmuting `&T` to `&mut T` or `&UnsafeCell<T>`. | |
//! This module checks that we are not transmuting `&T` to `&mut T` or `&UnsafeCell<T>`. |
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.
Does it check casting as well?
referent.translate_for_diagnostics(cx, &mut after_ty, reference_ty); | ||
} else { | ||
before_ty = "*"; | ||
reference.translate_for_diagnostics(cx, &mut after_ty, top_ty); |
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.
These two lines are shared with the if
block and can be factored out.
}; | ||
debug!(?offset, ?layout, "check_overlapping"); | ||
|
||
// Then, for any entry that we overlap with (there can be many as our size can be bigger than one, |
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.
// Then, for any entry that we overlap with (there can be many as our size can be bigger than one, | |
// Then, for any entry that we overlap with (there can be many because our size can be bigger than one, |
(I had to read this sentence twice to understand it. This is a pet peeve of mine, "because" is almost always clearer than "as".)
cx.tcx.is_intrinsic(def_id, sym::transmute) | ||
} | ||
|
||
/// Checks for transmutes via `&*(reference as *const _ as *const _)` and lints. |
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.
That's a cast, not a transmute...
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.
For the reasons described here, I would actually call this a transmute. It's using a cast to effect a transmutation. So it's a transmute via a cast.
} | ||
|
||
declare_lint! { | ||
/// The `mutable_transmutes` lint catches transmuting from `&T` to `&mut |
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 one only mentions transmuting...
} | ||
|
||
declare_lint! { | ||
/// The `unsafe_cell_transmutes` lint catches transmuting or casting from `&T` to [`&UnsafeCell<T>`] |
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 one mentions transmuting or casting...
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 |
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