To be more specific, why doesn't Arc<T>
implement from_raw
with a dynamically sized T
while Box<T>
does?
use std::sync::Arc;
fn main() {
let x = vec![1, 2, 3].into_boxed_slice();
let y = Box::into_raw(x);
let z = unsafe { Arc::from_raw(y) }; // ERROR
}
(play)
As pointed out in the comments, Arc::from_raw
must be used with a pointer from Arc::into_raw
, so the above example doesn't make sense. My original question (Is it possible to create an Arc<[T]>
from a Vec<T>
) remains: is this possible, and if not, why?
As of Rust 1.21.0, you can do this:
let thing: Arc<[i32]> = vec![1, 2, 3].into();
This was enabled by RFC 1845:
In addition:
From<Vec<T>> for Rc<[T]>
andFrom<Box<T: ?Sized>> for Rc<T>
will be added.Identical APIs will also be added for
Arc
.
Internally, this uses a method called copy_from_slice
, so the allocation of the Vec
is not reused. For the details why, check out DK.'s answer.
No.
First of all, as already noted in comments, you can't toss raw pointers around willy-nilly like that. To quote the documentation of Arc::from_raw
:
The raw pointer must have been previously returned by a call to a
Arc::into_raw
.
You absolutely must read the documentation any time you're using an unsafe
method.
Secondly, the conversion you want is impossible. Vec<T>
→ Box<[T]>
works because, internally, Vec<T>
is effectively a (Box<[T]>, usize)
pair. So, all the method does is give you access to that internal Box<[T]>
pointer [1]. Arc<[T]>
, however, is not physically compatible with a Box<[T]>
, because it has to contain the reference counts. The thing being pointed to by Arc<T>
has a different size and layout to the thing being pointed to by Box<T>
.
The only way you could get from Vec<T>
to Arc<[T]>
would be to reallocate the contents of the vector in a reference-counted allocation... which I'm not aware of any way to do. I don't believe there's any particular reason it couldn't be implemented, it just hasn't [2].
All that said, I believe not being able to use dynamically sized types with Arc::into_raw
/Arc::from_raw
is a bug. It's certainly possible to get Arc
s with dynamically sized types... though only by casting from pointers to fixed-sized types.
[1]: Not quite. Vec<T>
doesn't actually have a Box<[T]>
inside it, but it has something compatible. It also has to shrink the slice to not contain uninitialised elements.
[2]: Rust does not, on the whole, have good support for allocating dynamically sized things in general. It's possible that part of the reason for this hole in particular is that Box<T>
also can't allocate arrays directly, which is possibly because Vec<T>
exists, because Vec<T>
used to be part of the language itself, and why would you add array allocation to Box
when Vec
already exists? "Why not have ArcVec<T>
, then?" Because you'd never be able to construct one due to shared ownership.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With