mirror of
https://github.com/eyre-rs/eyre.git
synced 2025-10-02 15:26:08 +00:00
Deallocate with the right Layout during downcast
This commit is contained in:
parent
8895b006a7
commit
22c2608a84
20
src/error.rs
20
src/error.rs
@ -82,6 +82,7 @@ impl Error {
|
|||||||
{
|
{
|
||||||
let vtable = &ErrorVTable {
|
let vtable = &ErrorVTable {
|
||||||
object_drop: object_drop::<E>,
|
object_drop: object_drop::<E>,
|
||||||
|
object_drop_front: object_drop_front::<E>,
|
||||||
object_raw: object_raw::<E>,
|
object_raw: object_raw::<E>,
|
||||||
object_mut_raw: object_mut_raw::<E>,
|
object_mut_raw: object_mut_raw::<E>,
|
||||||
};
|
};
|
||||||
@ -237,11 +238,13 @@ impl Error {
|
|||||||
where
|
where
|
||||||
E: Display + Debug + Send + Sync + 'static,
|
E: Display + Debug + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
if let Some(error) = self.downcast_ref::<E>() {
|
if self.is::<E>() {
|
||||||
|
let outer = ManuallyDrop::new(self);
|
||||||
unsafe {
|
unsafe {
|
||||||
let error = ptr::read(error);
|
let error = ptr::read(&outer.inner.error as *const () as *const E);
|
||||||
drop(ptr::read(&self.inner));
|
let inner = ptr::read(&outer.inner);
|
||||||
mem::forget(self);
|
let erased = ManuallyDrop::into_inner(inner);
|
||||||
|
(erased.vtable.object_drop_front)(erased);
|
||||||
Ok(error)
|
Ok(error)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -393,6 +396,7 @@ impl Drop for Error {
|
|||||||
|
|
||||||
struct ErrorVTable {
|
struct ErrorVTable {
|
||||||
object_drop: unsafe fn(Box<ErrorImpl<()>>),
|
object_drop: unsafe fn(Box<ErrorImpl<()>>),
|
||||||
|
object_drop_front: unsafe fn(Box<ErrorImpl<()>>),
|
||||||
object_raw: fn(*const ()) -> *const (dyn StdError + Send + Sync + 'static),
|
object_raw: fn(*const ()) -> *const (dyn StdError + Send + Sync + 'static),
|
||||||
object_mut_raw: fn(*mut ()) -> *mut (dyn StdError + Send + Sync + 'static),
|
object_mut_raw: fn(*mut ()) -> *mut (dyn StdError + Send + Sync + 'static),
|
||||||
}
|
}
|
||||||
@ -404,6 +408,14 @@ unsafe fn object_drop<E>(e: Box<ErrorImpl<()>>) {
|
|||||||
drop(unerased);
|
drop(unerased);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn object_drop_front<E>(e: Box<ErrorImpl<()>>) {
|
||||||
|
// Drop the fields of ErrorImpl other than E as well as the Box allocation,
|
||||||
|
// without dropping E itself. This is used by downcast after doing a
|
||||||
|
// ptr::read to take ownership of the E.
|
||||||
|
let unerased = mem::transmute::<Box<ErrorImpl<()>>, Box<ErrorImpl<ManuallyDrop<E>>>>(e);
|
||||||
|
drop(unerased);
|
||||||
|
}
|
||||||
|
|
||||||
fn object_raw<E>(e: *const ()) -> *const (dyn StdError + Send + Sync + 'static)
|
fn object_raw<E>(e: *const ()) -> *const (dyn StdError + Send + Sync + 'static)
|
||||||
where
|
where
|
||||||
E: StdError + Send + Sync + 'static,
|
E: StdError + Send + Sync + 'static,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user