mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Rollup merge of #122298 - RalfJung:raw-vec-into-box, r=cuviper
RawVec::into_box: avoid unnecessary intermediate reference Fixes the problem described [here](https://github.com/rust-lang/miri/issues/3341#issuecomment-1987207195).
This commit is contained in:
commit
eb1ebbfc92
@ -5,7 +5,6 @@ use core::cmp;
|
|||||||
use core::hint;
|
use core::hint;
|
||||||
use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
|
use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
|
||||||
use core::ptr::{self, NonNull, Unique};
|
use core::ptr::{self, NonNull, Unique};
|
||||||
use core::slice;
|
|
||||||
|
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[cfg(not(no_global_oom_handling))]
|
||||||
use crate::alloc::handle_alloc_error;
|
use crate::alloc::handle_alloc_error;
|
||||||
@ -192,7 +191,7 @@ impl<T, A: Allocator> RawVec<T, A> {
|
|||||||
|
|
||||||
let me = ManuallyDrop::new(self);
|
let me = ManuallyDrop::new(self);
|
||||||
unsafe {
|
unsafe {
|
||||||
let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len);
|
let slice = ptr::slice_from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len);
|
||||||
Box::from_raw_in(slice, ptr::read(&me.alloc))
|
Box::from_raw_in(slice, ptr::read(&me.alloc))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,8 @@ unsafe impl Allocator for MyAllocator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
|
unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
|
||||||
|
// Make sure accesses via `self` don't disturb anything.
|
||||||
|
let _val = self.bins[0].top.get();
|
||||||
// Since manually finding the corresponding bin of `ptr` is very expensive,
|
// Since manually finding the corresponding bin of `ptr` is very expensive,
|
||||||
// doing pointer arithmetics is preferred.
|
// doing pointer arithmetics is preferred.
|
||||||
// But this means we access `top` via `ptr` rather than `self`!
|
// But this means we access `top` via `ptr` rather than `self`!
|
||||||
@ -101,22 +103,30 @@ unsafe impl Allocator for MyAllocator {
|
|||||||
if self.thread_id == thread_id {
|
if self.thread_id == thread_id {
|
||||||
unsafe { (*their_bin).push(ptr) };
|
unsafe { (*their_bin).push(ptr) };
|
||||||
} else {
|
} else {
|
||||||
todo!("Deallocating from another thread")
|
todo!("Deallocating from another thread");
|
||||||
}
|
}
|
||||||
|
// Make sure we can also still access this via `self` after the rest is done.
|
||||||
|
let _val = self.bins[0].top.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure to involve `Box` in allocating these,
|
// Make sure to involve `Box` in allocating these,
|
||||||
// as that's where `noalias` may come from.
|
// as that's where `noalias` may come from.
|
||||||
fn v<T, A: Allocator>(t: T, a: A) -> Vec<T, A> {
|
fn v1<T, A: Allocator>(t: T, a: A) -> Vec<T, A> {
|
||||||
(Box::new_in([t], a) as Box<[T], A>).into_vec()
|
(Box::new_in([t], a) as Box<[T], A>).into_vec()
|
||||||
}
|
}
|
||||||
|
fn v2<T, A: Allocator>(t: T, a: A) -> Vec<T, A> {
|
||||||
|
let v = v1(t, a);
|
||||||
|
// There was a bug in `into_boxed_slice` that caused aliasing issues,
|
||||||
|
// so round-trip through that as well.
|
||||||
|
v.into_boxed_slice().into_vec()
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
assert!(mem::size_of::<MyBin>() <= 128); // if it grows bigger, the trick to access the "header" no longer works
|
assert!(mem::size_of::<MyBin>() <= 128); // if it grows bigger, the trick to access the "header" no longer works
|
||||||
let my_alloc = MyAllocator::new();
|
let my_alloc = MyAllocator::new();
|
||||||
let a = v(1usize, &my_alloc);
|
let a = v1(1usize, &my_alloc);
|
||||||
let b = v(2usize, &my_alloc);
|
let b = v2(2usize, &my_alloc);
|
||||||
assert_eq!(a[0] + 1, b[0]);
|
assert_eq!(a[0] + 1, b[0]);
|
||||||
assert_eq!(addr_of!(a[0]).wrapping_add(1), addr_of!(b[0]));
|
assert_eq!(addr_of!(a[0]).wrapping_add(1), addr_of!(b[0]));
|
||||||
drop((a, b));
|
drop((a, b));
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//@ run-fail
|
//@ run-fail
|
||||||
//@ check-run-results
|
//@ check-run-results
|
||||||
//@ exec-env:RUST_BACKTRACE=0
|
//@ exec-env:RUST_BACKTRACE=0
|
||||||
|
//@ normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC"
|
||||||
//
|
//
|
||||||
// Regression test for issue #70963
|
// Regression test for issue #70963
|
||||||
// The captured stderr from this test reports a location
|
// The captured stderr from this test reports a location
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
thread 'main' panicked at library/alloc/src/raw_vec.rs:26:5:
|
thread 'main' panicked at library/alloc/src/raw_vec.rs:LL:CC:
|
||||||
capacity overflow
|
capacity overflow
|
||||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||||
|
Loading…
Reference in New Issue
Block a user