@@ -158,6 +158,7 @@ impl Error {
158158 #[ cfg( anyhow_no_ptr_addr_of) ]
159159 object_mut : object_mut :: < E > ,
160160 object_boxed : object_boxed :: < E > ,
161+ object_reallocate_boxed : object_reallocate_boxed :: < E > ,
161162 object_downcast : object_downcast :: < E > ,
162163 #[ cfg( anyhow_no_ptr_addr_of) ]
163164 object_downcast_mut : object_downcast_mut :: < E > ,
@@ -186,6 +187,7 @@ impl Error {
186187 #[ cfg( all( any( feature = "std" , not( anyhow_no_core_error) ) , anyhow_no_ptr_addr_of) ) ]
187188 object_mut : object_mut :: < MessageError < M > > ,
188189 object_boxed : object_boxed :: < MessageError < M > > ,
190+ object_reallocate_boxed : object_reallocate_boxed :: < MessageError < M > > ,
189191 object_downcast : object_downcast :: < M > ,
190192 #[ cfg( anyhow_no_ptr_addr_of) ]
191193 object_downcast_mut : object_downcast_mut :: < M > ,
@@ -215,6 +217,7 @@ impl Error {
215217 #[ cfg( all( any( feature = "std" , not( anyhow_no_core_error) ) , anyhow_no_ptr_addr_of) ) ]
216218 object_mut : object_mut :: < DisplayError < M > > ,
217219 object_boxed : object_boxed :: < DisplayError < M > > ,
220+ object_reallocate_boxed : object_reallocate_boxed :: < DisplayError < M > > ,
218221 object_downcast : object_downcast :: < M > ,
219222 #[ cfg( anyhow_no_ptr_addr_of) ]
220223 object_downcast_mut : object_downcast_mut :: < M > ,
@@ -250,6 +253,7 @@ impl Error {
250253 #[ cfg( anyhow_no_ptr_addr_of) ]
251254 object_mut : object_mut :: < ContextError < C , E > > ,
252255 object_boxed : object_boxed :: < ContextError < C , E > > ,
256+ object_reallocate_boxed : object_reallocate_boxed :: < ContextError < C , E > > ,
253257 object_downcast : context_downcast :: < C , E > ,
254258 #[ cfg( anyhow_no_ptr_addr_of) ]
255259 object_downcast_mut : context_downcast_mut :: < C , E > ,
@@ -279,6 +283,7 @@ impl Error {
279283 #[ cfg( anyhow_no_ptr_addr_of) ]
280284 object_mut : object_mut :: < BoxedError > ,
281285 object_boxed : object_boxed :: < BoxedError > ,
286+ object_reallocate_boxed : object_reallocate_boxed :: < BoxedError > ,
282287 object_downcast : object_downcast :: < Box < dyn StdError + Send + Sync > > ,
283288 #[ cfg( anyhow_no_ptr_addr_of) ]
284289 object_downcast_mut : object_downcast_mut :: < Box < dyn StdError + Send + Sync > > ,
@@ -395,6 +400,7 @@ impl Error {
395400 #[ cfg( all( any( feature = "std" , not( anyhow_no_core_error) ) , anyhow_no_ptr_addr_of) ) ]
396401 object_mut : object_mut :: < ContextError < C , Error > > ,
397402 object_boxed : object_boxed :: < ContextError < C , Error > > ,
403+ object_reallocate_boxed : object_reallocate_boxed :: < ContextError < C , Error > > ,
398404 object_downcast : context_chain_downcast :: < C > ,
399405 #[ cfg( anyhow_no_ptr_addr_of) ]
400406 object_downcast_mut : context_chain_downcast_mut :: < C > ,
@@ -603,6 +609,94 @@ impl Error {
603609 }
604610 }
605611
612+ /// Convert to a standard library error trait object.
613+ ///
614+ /// This is implemented as a cheap pointer cast that does not allocate or
615+ /// deallocate memory. Like [`anyhow::Error::from_boxed`], it's useful for
616+ /// interop with other error libraries.
617+ ///
618+ /// The same conversion is also available as
619+ /// <code style="display:inline;white-space:normal;">impl From<anyhow::Error>
620+ /// for Box<dyn Error + Send + Sync + 'static></code>.
621+ ///
622+ /// If a backtrace was collected during construction of the `anyhow::Error`,
623+ /// that backtrace remains accessible using the standard library `Error`
624+ /// trait's provider API, but as a consequence, the resulting boxed error
625+ /// can no longer be downcast to its original underlying type.
626+ ///
627+ /// ```
628+ #[ cfg_attr( not( error_generic_member_access) , doc = "# const _: &str = stringify! {" ) ]
629+ /// #![feature(error_generic_member_access)]
630+ ///
631+ /// use anyhow::anyhow;
632+ /// use std::backtrace::Backtrace;
633+ /// use thiserror::Error;
634+ ///
635+ /// #[derive(Error, Debug)]
636+ /// #[error("...")]
637+ /// struct MyError;
638+ ///
639+ /// let anyhow_error = anyhow!(MyError);
640+ /// println!("{}", anyhow_error.backtrace()); // has Backtrace
641+ /// assert!(anyhow_error.downcast_ref::<MyError>().is_some()); // can downcast
642+ ///
643+ /// let boxed_dyn_error = anyhow_error.into_boxed_dyn_error();
644+ /// assert!(std::error::request_ref::<Backtrace>(&*boxed_dyn_error).is_some()); // has Backtrace
645+ /// assert!(boxed_dyn_error.downcast_ref::<MyError>().is_none()); // can no longer downcast
646+ #[ cfg_attr( not( error_generic_member_access) , doc = "# };" ) ]
647+ /// ```
648+ ///
649+ /// [`anyhow::Error::from_boxed`]: Self::from_boxed
650+ pub fn into_boxed_dyn_error ( self ) -> Box < dyn StdError + Send + Sync + ' static > {
651+ let outer = ManuallyDrop :: new ( self ) ;
652+ unsafe {
653+ // Use vtable to attach ErrorImpl<E>'s native StdError vtable for
654+ // the right original type E.
655+ ( vtable ( outer. inner . ptr ) . object_boxed ) ( outer. inner )
656+ }
657+ }
658+
659+ /// Convert to a standard library error trait object.
660+ ///
661+ /// Unlike `self.into_boxed_dyn_error()`, this method relocates the
662+ /// underlying error into a new allocation in order to make it downcastable
663+ /// to `&E` or `Box<E>` for its original underlying error type. Any
664+ /// backtrace collected during construction of the `anyhow::Error` is
665+ /// discarded.
666+ ///
667+ /// ```
668+ #[ cfg_attr( not( error_generic_member_access) , doc = "# const _: &str = stringify! {" ) ]
669+ /// #![feature(error_generic_member_access)]
670+ ///
671+ /// use anyhow::anyhow;
672+ /// use std::backtrace::Backtrace;
673+ /// use thiserror::Error;
674+ ///
675+ /// #[derive(Error, Debug)]
676+ /// #[error("...")]
677+ /// struct MyError;
678+ ///
679+ /// let anyhow_error = anyhow!(MyError);
680+ /// println!("{}", anyhow_error.backtrace()); // has Backtrace
681+ /// assert!(anyhow_error.downcast_ref::<MyError>().is_some()); // can downcast
682+ ///
683+ /// let boxed_dyn_error = anyhow_error.reallocate_into_boxed_dyn_error_without_backtrace();
684+ /// assert!(std::error::request_ref::<Backtrace>(&*boxed_dyn_error).is_none()); // Backtrace lost
685+ /// assert!(boxed_dyn_error.downcast_ref::<MyError>().is_some()); // can downcast to &MyError
686+ /// assert!(boxed_dyn_error.downcast::<MyError>().is_ok()); // can downcast to Box<MyError>
687+ #[ cfg_attr( not( error_generic_member_access) , doc = "# };" ) ]
688+ /// ```
689+ pub fn reallocate_into_boxed_dyn_error_without_backtrace (
690+ self ,
691+ ) -> Box < dyn StdError + Send + Sync + ' static > {
692+ let outer = ManuallyDrop :: new ( self ) ;
693+ unsafe {
694+ // Use vtable to attach E's native StdError vtable for the right
695+ // original type E.
696+ ( vtable ( outer. inner . ptr ) . object_reallocate_boxed ) ( outer. inner )
697+ }
698+ }
699+
606700 #[ cfg( error_generic_member_access) ]
607701 pub ( crate ) fn provide < ' a > ( & ' a self , request : & mut Request < ' a > ) {
608702 unsafe { ErrorImpl :: provide ( self . inner . by_ref ( ) , request) }
@@ -675,6 +769,7 @@ struct ErrorVTable {
675769 #[ cfg( all( any( feature = "std" , not( anyhow_no_core_error) ) , anyhow_no_ptr_addr_of) ) ]
676770 object_mut : unsafe fn ( Mut < ErrorImpl > ) -> & mut ( dyn StdError + Send + Sync + ' static ) ,
677771 object_boxed : unsafe fn ( Own < ErrorImpl > ) -> Box < dyn StdError + Send + Sync + ' static > ,
772+ object_reallocate_boxed : unsafe fn ( Own < ErrorImpl > ) -> Box < dyn StdError + Send + Sync + ' static > ,
678773 object_downcast : unsafe fn ( Ref < ErrorImpl > , TypeId ) -> Option < Ref < ( ) > > ,
679774 #[ cfg( anyhow_no_ptr_addr_of) ]
680775 object_downcast_mut : unsafe fn ( Mut < ErrorImpl > , TypeId ) -> Option < Mut < ( ) > > ,
@@ -744,6 +839,16 @@ where
744839 unsafe { unerased_own. boxed ( ) }
745840}
746841
842+ // Safety: requires layout of *e to match ErrorImpl<E>.
843+ unsafe fn object_reallocate_boxed < E > ( e : Own < ErrorImpl > ) -> Box < dyn StdError + Send + Sync + ' static >
844+ where
845+ E : StdError + Send + Sync + ' static ,
846+ {
847+ // Attach E's native StdError vtable.
848+ let unerased_own = e. cast :: < ErrorImpl < E > > ( ) ;
849+ Box :: new ( unsafe { unerased_own. boxed ( ) } . _object )
850+ }
851+
747852// Safety: requires layout of *e to match ErrorImpl<E>.
748853unsafe fn object_downcast < E > ( e : Ref < ErrorImpl > , target : TypeId ) -> Option < Ref < ( ) > >
749854where
@@ -1051,24 +1156,21 @@ where
10511156impl From < Error > for Box < dyn StdError + Send + Sync + ' static > {
10521157 #[ cold]
10531158 fn from ( error : Error ) -> Self {
1054- let outer = ManuallyDrop :: new ( error) ;
1055- unsafe {
1056- // Use vtable to attach ErrorImpl<E>'s native StdError vtable for
1057- // the right original type E.
1058- ( vtable ( outer. inner . ptr ) . object_boxed ) ( outer. inner )
1059- }
1159+ error. into_boxed_dyn_error ( )
10601160 }
10611161}
10621162
10631163impl From < Error > for Box < dyn StdError + Send + ' static > {
1164+ #[ cold]
10641165 fn from ( error : Error ) -> Self {
1065- Box :: < dyn StdError + Send + Sync > :: from ( error)
1166+ error. into_boxed_dyn_error ( )
10661167 }
10671168}
10681169
10691170impl From < Error > for Box < dyn StdError + ' static > {
1171+ #[ cold]
10701172 fn from ( error : Error ) -> Self {
1071- Box :: < dyn StdError + Send + Sync > :: from ( error)
1173+ error. into_boxed_dyn_error ( )
10721174 }
10731175}
10741176
0 commit comments