-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Remove use of uninitialized() in Weak::new() #51851
Conversation
r? @bluss (rust_highfive has picked a reviewer for you, use r? to override) |
src/liballoc/arc.rs
Outdated
.unwrap_or_else(|_| handle_alloc_error(layout)) | ||
.cast::<ArcInner<T>>(); | ||
ptr.as_mut().strong = atomic::AtomicUsize::new(0); | ||
ptr.as_mut().weak = atomic::AtomicUsize::new(1); |
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.
Using =
rather than ptr::write
would be incorrect in a generic context, but I believe it is fine here since AtomicUsize: !Drop
.
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.
IMO: a cute trick that unnecessarily hinges on a technicality. Depending on the exact definitions this line might be doing a (no-op) drop and that (no-op) drop might technically involve a read. I find it hard to imagine that would ever actually lead to a miscompile, but personally I'd stick with ptr::write
for the sake of avoiding that headache and for consistency.
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.
Fair point. Replaced with ptr::write
.
This still constructs an instance of a type which contains an uninhabited value - that is intrinsically undefined behavior. IIRC the actual cause of the crash with |
Ah interesting, I didn’t realize that Should we have a code path for |
We'd need to make sure all of the code that interacts with the inner value realizes that it needs to use |
#![feature(never_type)]
use std::sync::atomic;
struct ArcInner<T: ?Sized> {
strong: atomic::AtomicUsize,
// the value usize::MAX acts as a sentinel for temporarily "locking" the
// ability to upgrade weak pointers or downgrade strong ones; this is used
// to avoid races in `make_mut` and `get_mut`.
weak: atomic::AtomicUsize,
data: T,
}
fn main() {
println!("{}", std::mem::size_of::<ArcInner<!>>());
} |
That was not the case in March, and I wouldn't want to depend on that being the case in the future: #48493 (comment). |
It would be better to not leave |
This avoids the question of whether `uninitialized::<T>()` is necessarily UB when `T = !`
02719d9
to
7dc00b5
Compare
This was already the case before this PR, |
Yes. I even said so myself but it appears that got lost in editing.
Yes, lots of other unsafe code may also have to be updated if we'll end up being very strict about uninitialized memory. (minor point: I think it's more likely for Rc's code fulfills or will fulfill whatever preconditions the unsafe code guidelines specify for when you need valid memory than for Vec's code)
Sure, those are fine, it's only an issue for non-ZSTs. |
Oops never mind, I can when enabling optimizations. This PR fixes it though :) |
☔ The latest upstream changes (presumably #50357) made this pull request unmergeable. Please resolve the merge conflicts. |
This seems to be superseded by #50357 for |
This is indeed superseded, closing. I’ll make another PR later for applying to change to |
(Unless someone else beats me to it ;) |
This avoids the question of whether
uninitialized::<T>()
is necessarily UB whenT = !
Fixes #48493