@@ -25,7 +25,7 @@ use crate::backtrace::Backtrace;
2525use crate :: borrow:: Cow ;
2626use crate :: cell;
2727use crate :: char;
28- use crate :: fmt:: { self , Debug , Display , Write } ;
28+ use crate :: fmt:: { self , Debug , Display } ;
2929use crate :: mem:: transmute;
3030use crate :: num;
3131use crate :: str;
@@ -816,6 +816,7 @@ impl dyn Error + Send + Sync {
816816///
817817/// ```
818818/// #![feature(error_reporter)]
819+ /// #![feature(negative_impls)]
819820///
820821/// use std::error::{Error, Report};
821822/// use std::fmt;
@@ -848,17 +849,48 @@ impl dyn Error + Send + Sync {
848849///
849850/// impl Error for SuperErrorSideKick {}
850851///
852+ /// // Note that the error doesn't need to be `Send` or `Sync`.
853+ /// impl !Send for SuperError {}
854+ /// impl !Sync for SuperError {}
855+ ///
851856/// fn main() {
852857/// let error = SuperError { side: SuperErrorSideKick };
853858/// let report = Report::new(&error).pretty(true);
854859///
855860/// println!("{}", report);
856861/// }
857862/// ```
863+ ///
864+ /// `Report` only requires that the wrapped error implements `Error`. It doesn't require that the
865+ /// wrapped error be `Send`, `Sync`, or `'static`.
866+ ///
867+ /// ```rust
868+ /// # #![feature(error_reporter)]
869+ /// # use std::fmt;
870+ /// # use std::error::{Error, Report};
871+ /// #[derive(Debug)]
872+ /// struct SuperError<'a> {
873+ /// side: &'a str,
874+ /// }
875+ /// impl<'a> fmt::Display for SuperError<'a> {
876+ /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
877+ /// write!(f, "SuperError is here: {}", self.side)
878+ /// }
879+ /// }
880+ /// impl<'a> Error for SuperError<'a> {}
881+ /// fn main() {
882+ /// let msg = String::from("Huzzah!");
883+ /// let report = Report::new(SuperError { side: &msg });
884+ /// println!("{}", report);
885+ /// }
886+ /// ```
858887#[ unstable( feature = "error_reporter" , issue = "90172" ) ]
859888pub struct Report < E > {
889+ /// The error being reported.
860890 error : E ,
891+ /// Whether a backtrace should be included as part of the report.
861892 show_backtrace : bool ,
893+ /// Whether the report should be pretty-printed.
862894 pretty : bool ,
863895}
864896
@@ -911,33 +943,26 @@ where
911943 write ! ( f, "\n \n Caused by:" ) ?;
912944
913945 let multiple = cause. source ( ) . is_some ( ) ;
914- let format = if multiple {
915- Format :: Numbered { ind : 0 }
916- } else {
917- Format :: Uniform { indentation : " " }
918- } ;
919946
920- for error in cause. chain ( ) {
947+ for ( ind , error) in cause. chain ( ) . enumerate ( ) {
921948 writeln ! ( f) ?;
922949
923- let mut indented = Indented { inner : f, needs_indent : true , format } ;
924-
925- write ! ( indented, "{}" , error) ?;
950+ if multiple {
951+ write ! ( f, "{: >4}: {}" , ind, Indented { source: error } ) ?;
952+ } else {
953+ write ! ( f, " {}" , error) ?;
954+ }
926955 }
927956 }
928957
929958 if self . show_backtrace {
930959 let backtrace = error. backtrace ( ) ;
931960
932961 if let Some ( backtrace) = backtrace {
933- let mut backtrace = backtrace. to_string ( ) ;
934-
935- write ! ( f, "\n \n " ) ?;
936- writeln ! ( f, "Stack backtrace:" ) ?;
962+ let backtrace = backtrace. to_string ( ) ;
937963
938- backtrace. truncate ( backtrace. trim_end ( ) . len ( ) ) ;
939-
940- write ! ( f, "{}" , backtrace) ?;
964+ f. write_str ( "\n \n Stack backtrace:\n " ) ?;
965+ f. write_str ( backtrace. trim_end ( ) ) ?;
941966 }
942967 }
943968
@@ -977,76 +1002,26 @@ where
9771002 }
9781003}
9791004
980- /// Encapsulates how error sources are indented and formatted.
981- struct Indented < ' a , D : ?Sized > {
982- inner : & ' a mut D ,
983- needs_indent : bool ,
984- format : Format ,
985- }
986-
987- /// The possible variants that error sources can be formatted as.
988- #[ derive( Clone , Copy ) ]
989- enum Format {
990- /// Insert uniform indentation before every line.
991- ///
992- /// This format takes a static string as input and inserts it after every newline.
993- Uniform {
994- /// The string to insert as indentation.
995- indentation : & ' static str ,
996- } ,
997- /// Inserts a number before the first line.
998- ///
999- /// This format hard codes the indentation level to match the indentation from
1000- /// `std::backtrace::Backtrace`.
1001- Numbered {
1002- /// The index to insert before the first line of output.
1003- ind : usize ,
1004- } ,
1005+ /// Wrapper type for indenting the inner source.
1006+ struct Indented < D > {
1007+ source : D ,
10051008}
10061009
1007- impl < D > Write for Indented < ' _ , D >
1010+ impl < D > fmt :: Display for Indented < D >
10081011where
1009- D : Write + ? Sized ,
1012+ D : fmt :: Display ,
10101013{
1011- fn write_str ( & mut self , s : & str ) -> fmt:: Result {
1012- for ( ind, line) in s. split ( '\n' ) . enumerate ( ) {
1013- if ind > 0 {
1014- self . inner . write_char ( '\n' ) ?;
1015- self . needs_indent = true ;
1016- }
1017-
1018- if self . needs_indent {
1019- if line. is_empty ( ) {
1020- continue ;
1021- }
1014+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1015+ let source = self . source . to_string ( ) ;
10221016
1023- self . format . insert_indentation ( ind, & mut self . inner ) ?;
1024- self . needs_indent = false ;
1017+ for ( ind, line) in source. trim ( ) . split ( '\n' ) . filter ( |l| !l. is_empty ( ) ) . enumerate ( ) {
1018+ if ind > 0 {
1019+ write ! ( f, "\n {}" , line) ?;
1020+ } else {
1021+ write ! ( f, "{}" , line) ?;
10251022 }
1026-
1027- self . inner . write_fmt ( format_args ! ( "{}" , line) ) ?;
10281023 }
10291024
10301025 Ok ( ( ) )
10311026 }
10321027}
1033-
1034- impl Format {
1035- /// Write the specified formatting to the write buffer.
1036- fn insert_indentation ( & mut self , line : usize , f : & mut dyn Write ) -> fmt:: Result {
1037- match self {
1038- Format :: Uniform { indentation } => {
1039- write ! ( f, "{}" , indentation)
1040- }
1041- Format :: Numbered { ind } => {
1042- if line == 0 {
1043- write ! ( f, "{: >4}: " , ind) ?;
1044- * ind += 1 ;
1045- Ok ( ( ) )
1046- } else {
1047- write ! ( f, " " )
1048- }
1049- }
1050- }
1051- }
1052- }
0 commit comments