@@ -159,6 +159,8 @@ impl Error {
159
159
object_mut : object_mut :: < E > ,
160
160
#[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
161
161
object_boxed : object_boxed :: < E > ,
162
+ #[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
163
+ object_reallocate_boxed : object_reallocate_boxed :: < E > ,
162
164
object_downcast : object_downcast :: < E > ,
163
165
#[ cfg( anyhow_no_ptr_addr_of) ]
164
166
object_downcast_mut : object_downcast_mut :: < E > ,
@@ -188,6 +190,8 @@ impl Error {
188
190
object_mut : object_mut :: < MessageError < M > > ,
189
191
#[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
190
192
object_boxed : object_boxed :: < MessageError < M > > ,
193
+ #[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
194
+ object_reallocate_boxed : object_reallocate_boxed :: < MessageError < M > > ,
191
195
object_downcast : object_downcast :: < M > ,
192
196
#[ cfg( anyhow_no_ptr_addr_of) ]
193
197
object_downcast_mut : object_downcast_mut :: < M > ,
@@ -218,6 +222,8 @@ impl Error {
218
222
object_mut : object_mut :: < DisplayError < M > > ,
219
223
#[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
220
224
object_boxed : object_boxed :: < DisplayError < M > > ,
225
+ #[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
226
+ object_reallocate_boxed : object_reallocate_boxed :: < DisplayError < M > > ,
221
227
object_downcast : object_downcast :: < M > ,
222
228
#[ cfg( anyhow_no_ptr_addr_of) ]
223
229
object_downcast_mut : object_downcast_mut :: < M > ,
@@ -254,6 +260,8 @@ impl Error {
254
260
object_mut : object_mut :: < ContextError < C , E > > ,
255
261
#[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
256
262
object_boxed : object_boxed :: < ContextError < C , E > > ,
263
+ #[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
264
+ object_reallocate_boxed : object_reallocate_boxed :: < ContextError < C , E > > ,
257
265
object_downcast : context_downcast :: < C , E > ,
258
266
#[ cfg( anyhow_no_ptr_addr_of) ]
259
267
object_downcast_mut : context_downcast_mut :: < C , E > ,
@@ -284,6 +292,8 @@ impl Error {
284
292
object_mut : object_mut :: < BoxedError > ,
285
293
#[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
286
294
object_boxed : object_boxed :: < BoxedError > ,
295
+ #[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
296
+ object_reallocate_boxed : object_reallocate_boxed :: < BoxedError > ,
287
297
object_downcast : object_downcast :: < Box < dyn StdError + Send + Sync > > ,
288
298
#[ cfg( anyhow_no_ptr_addr_of) ]
289
299
object_downcast_mut : object_downcast_mut :: < Box < dyn StdError + Send + Sync > > ,
@@ -401,6 +411,8 @@ impl Error {
401
411
object_mut : object_mut :: < ContextError < C , Error > > ,
402
412
#[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
403
413
object_boxed : object_boxed :: < ContextError < C , Error > > ,
414
+ #[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
415
+ object_reallocate_boxed : object_reallocate_boxed :: < ContextError < C , Error > > ,
404
416
object_downcast : context_chain_downcast :: < C > ,
405
417
#[ cfg( anyhow_no_ptr_addr_of) ]
406
418
object_downcast_mut : context_chain_downcast_mut :: < C > ,
@@ -609,6 +621,98 @@ impl Error {
609
621
}
610
622
}
611
623
624
+ /// Convert to a standard library error trait object.
625
+ ///
626
+ /// This is implemented as a cheap pointer cast that does not allocate or
627
+ /// deallocate memory. Like [`anyhow::Error::from_boxed`], it's useful for
628
+ /// interop with other error libraries.
629
+ ///
630
+ /// The same conversion is also available as
631
+ /// <code style="display:inline;white-space:normal;">impl From<anyhow::Error>
632
+ /// for Box<dyn Error + Send + Sync + 'static></code>.
633
+ ///
634
+ /// If a backtrace was collected during construction of the `anyhow::Error`,
635
+ /// that backtrace remains accessible using the standard library `Error`
636
+ /// trait's provider API, but as a consequence, the resulting boxed error
637
+ /// can no longer be downcast to its original underlying type.
638
+ ///
639
+ /// ```
640
+ #[ cfg_attr( not( error_generic_member_access) , doc = "# _ = stringify! {" ) ]
641
+ /// #![feature(error_generic_member_access)]
642
+ ///
643
+ /// use anyhow::anyhow;
644
+ /// use std::backtrace::Backtrace;
645
+ /// use thiserror::Error;
646
+ ///
647
+ /// #[derive(Error, Debug)]
648
+ /// #[error("...")]
649
+ /// struct MyError;
650
+ ///
651
+ /// let anyhow_error = anyhow!(MyError);
652
+ /// println!("{}", anyhow_error.backtrace()); // has Backtrace
653
+ /// assert!(anyhow_error.downcast_ref::<MyError>().is_some()); // can downcast
654
+ ///
655
+ /// let boxed_dyn_error = anyhow_error.into_boxed_dyn_error();
656
+ /// assert!(std::error::request_ref::<Backtrace>(&*boxed_dyn_error).is_some()); // has Backtrace
657
+ /// assert!(boxed_dyn_error.downcast_ref::<MyError>().is_none()); // can no longer downcast
658
+ #[ cfg_attr( not( error_generic_member_access) , doc = "# };" ) ]
659
+ /// ```
660
+ ///
661
+ /// [`anyhow::Error::from_boxed`]: Self::from_boxed
662
+ #[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
663
+ #[ must_use]
664
+ pub fn into_boxed_dyn_error ( self ) -> Box < dyn StdError + Send + Sync + ' static > {
665
+ let outer = ManuallyDrop :: new ( self ) ;
666
+ unsafe {
667
+ // Use vtable to attach ErrorImpl<E>'s native StdError vtable for
668
+ // the right original type E.
669
+ ( vtable ( outer. inner . ptr ) . object_boxed ) ( outer. inner )
670
+ }
671
+ }
672
+
673
+ /// Convert to a standard library error trait object.
674
+ ///
675
+ /// Unlike `self.into_boxed_dyn_error()`, this method relocates the
676
+ /// underlying error into a new allocation in order to make it downcastable
677
+ /// to `&E` or `Box<E>` for its original underlying error type. Any
678
+ /// backtrace collected during construction of the `anyhow::Error` is
679
+ /// discarded.
680
+ ///
681
+ /// ```
682
+ #[ cfg_attr( not( error_generic_member_access) , doc = "# _ = stringify!{" ) ]
683
+ /// #![feature(error_generic_member_access)]
684
+ ///
685
+ /// use anyhow::anyhow;
686
+ /// use std::backtrace::Backtrace;
687
+ /// use thiserror::Error;
688
+ ///
689
+ /// #[derive(Error, Debug)]
690
+ /// #[error("...")]
691
+ /// struct MyError;
692
+ ///
693
+ /// let anyhow_error = anyhow!(MyError);
694
+ /// println!("{}", anyhow_error.backtrace()); // has Backtrace
695
+ /// assert!(anyhow_error.downcast_ref::<MyError>().is_some()); // can downcast
696
+ ///
697
+ /// let boxed_dyn_error = anyhow_error.reallocate_into_boxed_dyn_error_without_backtrace();
698
+ /// assert!(std::error::request_ref::<Backtrace>(&*boxed_dyn_error).is_none()); // Backtrace lost
699
+ /// assert!(boxed_dyn_error.downcast_ref::<MyError>().is_some()); // can downcast to &MyError
700
+ /// assert!(boxed_dyn_error.downcast::<MyError>().is_ok()); // can downcast to Box<MyError>
701
+ #[ cfg_attr( not( error_generic_member_access) , doc = "# };" ) ]
702
+ /// ```
703
+ #[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
704
+ #[ must_use]
705
+ pub fn reallocate_into_boxed_dyn_error_without_backtrace (
706
+ self ,
707
+ ) -> Box < dyn StdError + Send + Sync + ' static > {
708
+ let outer = ManuallyDrop :: new ( self ) ;
709
+ unsafe {
710
+ // Use vtable to attach E's native StdError vtable for the right
711
+ // original type E.
712
+ ( vtable ( outer. inner . ptr ) . object_reallocate_boxed ) ( outer. inner )
713
+ }
714
+ }
715
+
612
716
#[ cfg( error_generic_member_access) ]
613
717
pub ( crate ) fn provide < ' a > ( & ' a self , request : & mut Request < ' a > ) {
614
718
unsafe { ErrorImpl :: provide ( self . inner . by_ref ( ) , request) }
@@ -682,6 +786,8 @@ struct ErrorVTable {
682
786
object_mut : unsafe fn ( Mut < ErrorImpl > ) -> & mut ( dyn StdError + Send + Sync + ' static ) ,
683
787
#[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
684
788
object_boxed : unsafe fn ( Own < ErrorImpl > ) -> Box < dyn StdError + Send + Sync + ' static > ,
789
+ #[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
790
+ object_reallocate_boxed : unsafe fn ( Own < ErrorImpl > ) -> Box < dyn StdError + Send + Sync + ' static > ,
685
791
object_downcast : unsafe fn ( Ref < ErrorImpl > , TypeId ) -> Option < Ref < ( ) > > ,
686
792
#[ cfg( anyhow_no_ptr_addr_of) ]
687
793
object_downcast_mut : unsafe fn ( Mut < ErrorImpl > , TypeId ) -> Option < Mut < ( ) > > ,
@@ -752,6 +858,17 @@ where
752
858
unsafe { unerased_own. boxed ( ) }
753
859
}
754
860
861
+ // Safety: requires layout of *e to match ErrorImpl<E>.
862
+ #[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
863
+ unsafe fn object_reallocate_boxed < E > ( e : Own < ErrorImpl > ) -> Box < dyn StdError + Send + Sync + ' static >
864
+ where
865
+ E : StdError + Send + Sync + ' static ,
866
+ {
867
+ // Attach E's native StdError vtable.
868
+ let unerased_own = e. cast :: < ErrorImpl < E > > ( ) ;
869
+ Box :: new ( unsafe { unerased_own. boxed ( ) } . _object )
870
+ }
871
+
755
872
// Safety: requires layout of *e to match ErrorImpl<E>.
756
873
unsafe fn object_downcast < E > ( e : Ref < ErrorImpl > , target : TypeId ) -> Option < Ref < ( ) > >
757
874
where
@@ -1060,26 +1177,23 @@ where
1060
1177
impl From < Error > for Box < dyn StdError + Send + Sync + ' static > {
1061
1178
#[ cold]
1062
1179
fn from ( error : Error ) -> Self {
1063
- let outer = ManuallyDrop :: new ( error) ;
1064
- unsafe {
1065
- // Use vtable to attach ErrorImpl<E>'s native StdError vtable for
1066
- // the right original type E.
1067
- ( vtable ( outer. inner . ptr ) . object_boxed ) ( outer. inner )
1068
- }
1180
+ error. into_boxed_dyn_error ( )
1069
1181
}
1070
1182
}
1071
1183
1072
1184
#[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
1073
1185
impl From < Error > for Box < dyn StdError + Send + ' static > {
1186
+ #[ cold]
1074
1187
fn from ( error : Error ) -> Self {
1075
- Box :: < dyn StdError + Send + Sync > :: from ( error)
1188
+ error. into_boxed_dyn_error ( )
1076
1189
}
1077
1190
}
1078
1191
1079
1192
#[ cfg( any( feature = "std" , not( anyhow_no_core_error) ) ) ]
1080
1193
impl From < Error > for Box < dyn StdError + ' static > {
1194
+ #[ cold]
1081
1195
fn from ( error : Error ) -> Self {
1082
- Box :: < dyn StdError + Send + Sync > :: from ( error)
1196
+ error. into_boxed_dyn_error ( )
1083
1197
}
1084
1198
}
1085
1199
0 commit comments