Open withoutboats opened 6 years ago
AFAIK, you'll need double-boxing if you want to store unsized data with a single-width pointer. Presumably you're getting the size to dealloc from vtable
? I don't believe there's a user-facing way to free an object of a dynamic size, but @dtolnay would know better.
You could still do struct Inner { backtrace: Backtrace, data: Box<Fail> }
.
AFAIK, you'll need double-boxing if you want to store unsized data with a single-width pointer.
Aren't we essentially going to be leaking the data (because of the bitmasking) and then reconstructing the address of it every time? We can make the second pointer null (and then swap it with the vtable pointer)?
Stuff about how to free the object is a good question, we would probably want to store the size inline.
Basically what we're talking about doing is reimplementing dynamic dispatch in unsafe code instead of using real trait objects.
This isn't really related but its also about doing unsafe vtable shenanigans:
it would be great to be able to follow the std::error::Error::cause
chain to its conclusion instead of just bottoming out at the first non-Fail
error we come to. We could do that if we could manufacture a fake vtable somehow.
The Fail vtable has two methods: backtrace (which in the fake one would use the default implementation) and cause. cause is the tricky method. We'd have to call the std::Error::Error::cause
method from the original vtable and then perform this very same vtable swap on the result.
No idea how to implement this even if it were possible on stable today.
In theory, error could:
To accomplish this goal, error would look like this:
This usize would be a pointer to a heap allocation or a vtable. Which kind of pointer it is would be stored using the extra bits of space that alignment guarantees give us on each platform.
The heap allocation would have this layout:
I'm not sure its even possible to write this with unsafe code on stable Rust.
cc @cramertj @dtolnay #9 #20.