Open vorner opened 3 years ago
You can perhaps do something like
let x = arena.alloc(x);
let x = x as &mut dyn Debug;
let x = unsafe { BumpBox::from_raw(x) };
Otherwise, you can use the cargo feature to enable Bump
implementing the nightly Allocator
trait and use the nightly feature to expose custom allocators with std
types, and then the original example should work.
I'd say neither is usable in a "production" project that disallows both nightly and unsafe :-(. If I really needed that (instead of preferring not to allocate on the heap), I'd go with creating a separate crate to isolate that unsafe, but that's probably not worth it.
Would it be OK to put such code into a method inside bumpalo? Can I send a PR?
Unfortunately it is impossible to make a generic version of that snippet in today's Rust:
dyn T
where T
is a trait.as
conversions, so the second line is impossible to write in a generic context.Well, the dyn Trait
is a type in its own right, so at least the first part is not really true. There also is a conversion for unsizing, but it's unstable :-(. This code demonstrates this:
#![feature(unsize)]
use std::fmt::Debug;
use std::marker::Unsize;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
fn box_it<'a, T, U>(arena: &'a Bump, x: T) -> BumpBox<'a, U>
where
T: Unsize<U>,
U: ?Sized + 'static,
{
let x = arena.alloc(x);
let x = x as &mut _;
let x = unsafe { BumpBox::from_raw(x) };
x
}
fn main() {
let bump = Bump::new();
let x = box_it::<usize, dyn Debug>(&bump, 42);
}
I wonder if there might be some other conversion trait that would also be usable. But it seems &'a mut T: Into<&'a mut U>
is not available here.
I guess there would be a possibility of a macro to hide the unsafety, but that's ugly :-(.
Is there any good work around for Box<dyn FnOnce>
? This got stabilized for stable rust's Box
, but I don't think those changes ever trickled into Bumpalo.
I think it is all about variance of type. AFAIU, if Box
stores not a mutable reference, but raw pointer, such a Box would be covariant and such type coertion would be possible.
https://doc.rust-lang.org/nomicon/subtyping.html
A related issue is that even if you manage to construct a Box<dyn FnOnce()>
, AFAICT it's not possible to call it because it can't be moved from:
fn f(b: bumpalo::boxed::Box<'_, dyn FnOnce()>) {
b();
}
cannot move out of dereference of `bumpalo::boxed::Box<'_, dyn FnOnce()>`
and Box::into_inner(b)()
doesn't work as it's unsized.
The former works with the stdlib Box
, which I think has some special case deref magic?
Otherwise, you can use the cargo feature to enable
Bump
implementing the nightlyAllocator
trait and use the nightly feature to expose custom allocators withstd
types, and then the original example should work.
This doesn't work for my use case as the stdlib box is Send + Sync
only if the allocator is.
EDIT: I ended up writing an allocator wrapper with a no-op deallocate()
:
Then used that with the stdlib Box
and manually implemented Send
for the type containing it. A little ugly but it should be sound as Box
doesn't realloc so it avoids the data race on the Bump
.
Hello
It seems the bumpalo's Box doesn't implement CoerceUnsize, like the usual
Box
does. I'm not sure how one should be able to create upcastable smart pointers, as that's a nightly-only API :-(.This code does not compile (and I can't figure out any equivalent that does):
This fails with
mismatched types
. Tryinginto()
and similar doesn't help.I've looked at this example around
downcast
and I'm pretty sure the example uses the ordinarystd::boxed::Box
, not the bumpalo's one.Is there a way to do the upcast I'm not seeing? Should the example be modified to use that?