@@ -914,106 +914,109 @@ impl dyn Error + Send + Sync {
914914/// thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: SuperError is here!: SuperErrorSideKick is here!', src/error.rs:34:40
915915/// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
916916/// ```
917- // /// TODO: Report doesn't yet support return from `main` gracefully, fix in followup (yaahc)
918- // /// ## Return from `main`
919- // ///
920- // /// `Report` also implements `From` for all types that implement [`Error`], this when combined with
921- // /// the `Debug` output means `Report` is an ideal starting place for formatting errors returned
922- // /// from `main`.
923- // ///
924- // /// ```
925- // /// #![feature(error_reporter)]
926- // /// use std::error::Report;
927- // /// # use std::error::Error;
928- // /// # use std::fmt;
929- // /// # #[derive(Debug)]
930- // /// # struct SuperError {
931- // /// # source: SuperErrorSideKick,
932- // /// # }
933- // /// # impl fmt::Display for SuperError {
934- // /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
935- // /// # write!(f, "SuperError is here!")
936- // /// # }
937- // /// # }
938- // /// # impl Error for SuperError {
939- // /// # fn source(&self) -> Option<&(dyn Error + 'static)> {
940- // /// # Some(&self.source)
941- // /// # }
942- // /// # }
943- // /// # #[derive(Debug)]
944- // /// # struct SuperErrorSideKick;
945- // /// # impl fmt::Display for SuperErrorSideKick {
946- // /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
947- // /// # write!(f, "SuperErrorSideKick is here!")
948- // /// # }
949- // /// # }
950- // /// # impl Error for SuperErrorSideKick {}
951- // /// # fn get_super_error() -> Result<(), SuperError> {
952- // /// # Err(SuperError { source: SuperErrorSideKick })
953- // /// # }
954- // ///
955- // /// fn main() -> Result<(), Report> {
956- // /// get_super_error()?;
957- // /// }
958- // /// ```
959- // ///
960- // /// This example produces the following output:
961- // ///
962- // /// ```console
963- // /// thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: SuperError is here!: SuperErrorSideKick is here!', src/error.rs:34:40
964- // /// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
965- // /// ```
966- // ///
967- // /// **Note**: `Report`s constructed via `?` and `From` will be configured to use the single line
968- // /// output format, if you want to make sure your `Report`s are pretty printed and include backtrace
969- // /// you will need to manually convert and enable those flags.
970- // ///
971- // /// ```
972- // /// #![feature(error_reporter)]
973- // /// use std::error::Report;
974- // /// # use std::error::Error;
975- // /// # use std::fmt;
976- // /// # #[derive(Debug)]
977- // /// # struct SuperError {
978- // /// # source: SuperErrorSideKick,
979- // /// # }
980- // /// # impl fmt::Display for SuperError {
981- // /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
982- // /// # write!(f, "SuperError is here!")
983- // /// # }
984- // /// # }
985- // /// # impl Error for SuperError {
986- // /// # fn source(&self) -> Option<&(dyn Error + 'static)> {
987- // /// # Some(&self.source)
988- // /// # }
989- // /// # }
990- // /// # #[derive(Debug)]
991- // /// # struct SuperErrorSideKick;
992- // /// # impl fmt::Display for SuperErrorSideKick {
993- // /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
994- // /// # write!(f, "SuperErrorSideKick is here!")
995- // /// # }
996- // /// # }
997- // /// # impl Error for SuperErrorSideKick {}
998- // /// # fn get_super_error() -> Result<(), SuperError> {
999- // /// # Err(SuperError { source: SuperErrorSideKick })
1000- // /// # }
1001- // ///
1002- // /// fn main() -> Result<(), Report> {
1003- // /// get_super_error()
1004- // /// .map_err(Report::new)
1005- // /// .map_err(|r| r.pretty(true).show_backtrace(true))?;
1006- // /// }
1007- // /// ```
1008- // ///
1009- // /// This example produces the following output:
1010- // ///
1011- // /// ```console
1012- // /// thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: SuperError is here!: SuperErrorSideKick is here!', src/error.rs:34:40
1013- // /// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
1014- // /// ```
917+ ///
918+ /// ## Return from `main`
919+ ///
920+ /// `Report` also implements `From` for all types that implement [`Error`], this when combined with
921+ /// the `Debug` output means `Report` is an ideal starting place for formatting errors returned
922+ /// from `main`.
923+ ///
924+ /// ```should_panic
925+ /// #![feature(error_reporter)]
926+ /// use std::error::Report;
927+ /// # use std::error::Error;
928+ /// # use std::fmt;
929+ /// # #[derive(Debug)]
930+ /// # struct SuperError {
931+ /// # source: SuperErrorSideKick,
932+ /// # }
933+ /// # impl fmt::Display for SuperError {
934+ /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
935+ /// # write!(f, "SuperError is here!")
936+ /// # }
937+ /// # }
938+ /// # impl Error for SuperError {
939+ /// # fn source(&self) -> Option<&(dyn Error + 'static)> {
940+ /// # Some(&self.source)
941+ /// # }
942+ /// # }
943+ /// # #[derive(Debug)]
944+ /// # struct SuperErrorSideKick;
945+ /// # impl fmt::Display for SuperErrorSideKick {
946+ /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
947+ /// # write!(f, "SuperErrorSideKick is here!")
948+ /// # }
949+ /// # }
950+ /// # impl Error for SuperErrorSideKick {}
951+ /// # fn get_super_error() -> Result<(), SuperError> {
952+ /// # Err(SuperError { source: SuperErrorSideKick })
953+ /// # }
954+ ///
955+ /// fn main() -> Result<(), Report> {
956+ /// get_super_error()?;
957+ /// Ok(())
958+ /// }
959+ /// ```
960+ ///
961+ /// This example produces the following output:
962+ ///
963+ /// ```console
964+ /// Error: SuperError is here!: SuperErrorSideKick is here!
965+ /// ```
966+ ///
967+ /// **Note**: `Report`s constructed via `?` and `From` will be configured to use the single line
968+ /// output format, if you want to make sure your `Report`s are pretty printed and include backtrace
969+ /// you will need to manually convert and enable those flags.
970+ ///
971+ /// ```should_panic
972+ /// #![feature(error_reporter)]
973+ /// use std::error::Report;
974+ /// # use std::error::Error;
975+ /// # use std::fmt;
976+ /// # #[derive(Debug)]
977+ /// # struct SuperError {
978+ /// # source: SuperErrorSideKick,
979+ /// # }
980+ /// # impl fmt::Display for SuperError {
981+ /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
982+ /// # write!(f, "SuperError is here!")
983+ /// # }
984+ /// # }
985+ /// # impl Error for SuperError {
986+ /// # fn source(&self) -> Option<&(dyn Error + 'static)> {
987+ /// # Some(&self.source)
988+ /// # }
989+ /// # }
990+ /// # #[derive(Debug)]
991+ /// # struct SuperErrorSideKick;
992+ /// # impl fmt::Display for SuperErrorSideKick {
993+ /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
994+ /// # write!(f, "SuperErrorSideKick is here!")
995+ /// # }
996+ /// # }
997+ /// # impl Error for SuperErrorSideKick {}
998+ /// # fn get_super_error() -> Result<(), SuperError> {
999+ /// # Err(SuperError { source: SuperErrorSideKick })
1000+ /// # }
1001+ ///
1002+ /// fn main() -> Result<(), Report> {
1003+ /// get_super_error()
1004+ /// .map_err(Report::from)
1005+ /// .map_err(|r| r.pretty(true).show_backtrace(true))?;
1006+ /// Ok(())
1007+ /// }
1008+ /// ```
1009+ ///
1010+ /// This example produces the following output:
1011+ ///
1012+ /// ```console
1013+ /// Error: SuperError is here!
1014+ ///
1015+ /// Caused by:
1016+ /// SuperErrorSideKick is here!
1017+ /// ```
10151018#[ unstable( feature = "error_reporter" , issue = "90172" ) ]
1016- pub struct Report < E > {
1019+ pub struct Report < E = Box < dyn Error > > {
10171020 /// The error being reported.
10181021 error : E ,
10191022 /// Whether a backtrace should be included as part of the report.
@@ -1024,14 +1027,16 @@ pub struct Report<E> {
10241027
10251028impl < E > Report < E >
10261029where
1027- E : Error ,
1030+ Report < E > : From < E > ,
10281031{
10291032 /// Create a new `Report` from an input error.
10301033 #[ unstable( feature = "error_reporter" , issue = "90172" ) ]
10311034 pub fn new ( error : E ) -> Report < E > {
1032- Report { error , show_backtrace : false , pretty : false }
1035+ Self :: from ( error )
10331036 }
1037+ }
10341038
1039+ impl < E > Report < E > {
10351040 /// Enable pretty-printing the report across multiple lines.
10361041 ///
10371042 /// # Examples
@@ -1232,7 +1237,81 @@ where
12321237 self . show_backtrace = show_backtrace;
12331238 self
12341239 }
1240+ }
1241+
1242+ impl < E > Report < E >
1243+ where
1244+ E : Error ,
1245+ {
1246+ fn backtrace ( & self ) -> Option < & Backtrace > {
1247+ // have to grab the backtrace on the first error directly since that error may not be
1248+ // 'static
1249+ let backtrace = self . error . backtrace ( ) ;
1250+ let backtrace = backtrace. or_else ( || {
1251+ self . error
1252+ . source ( )
1253+ . map ( |source| source. chain ( ) . find_map ( |source| source. backtrace ( ) ) )
1254+ . flatten ( )
1255+ } ) ;
1256+ backtrace
1257+ }
1258+
1259+ /// Format the report as a single line.
1260+ #[ unstable( feature = "error_reporter" , issue = "90172" ) ]
1261+ fn fmt_singleline ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1262+ write ! ( f, "{}" , self . error) ?;
1263+
1264+ let sources = self . error . source ( ) . into_iter ( ) . flat_map ( <dyn Error >:: chain) ;
1265+
1266+ for cause in sources {
1267+ write ! ( f, ": {}" , cause) ?;
1268+ }
1269+
1270+ Ok ( ( ) )
1271+ }
1272+
1273+ /// Format the report as multiple lines, with each error cause on its own line.
1274+ #[ unstable( feature = "error_reporter" , issue = "90172" ) ]
1275+ fn fmt_multiline ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1276+ let error = & self . error ;
1277+
1278+ write ! ( f, "{}" , error) ?;
1279+
1280+ if let Some ( cause) = error. source ( ) {
1281+ write ! ( f, "\n \n Caused by:" ) ?;
1282+
1283+ let multiple = cause. source ( ) . is_some ( ) ;
1284+
1285+ for ( ind, error) in cause. chain ( ) . enumerate ( ) {
1286+ writeln ! ( f) ?;
1287+ let mut indented = Indented {
1288+ inner : f,
1289+ } ;
1290+ if multiple {
1291+ write ! ( indented, "{: >4}: {}" , ind, error) ?;
1292+ } else {
1293+ write ! ( indented, " {}" , error) ?;
1294+ }
1295+ }
1296+ }
1297+
1298+ if self . show_backtrace {
1299+ let backtrace = self . backtrace ( ) ;
1300+
1301+ if let Some ( backtrace) = backtrace {
1302+ let backtrace = backtrace. to_string ( ) ;
1303+
1304+ f. write_str ( "\n \n Stack backtrace:\n " ) ?;
1305+ f. write_str ( backtrace. trim_end ( ) ) ?;
1306+ }
1307+ }
1308+
1309+ Ok ( ( ) )
1310+ }
1311+ }
12351312
1313+ impl Report < Box < dyn Error > >
1314+ {
12361315 fn backtrace ( & self ) -> Option < & Backtrace > {
12371316 // have to grab the backtrace on the first error directly since that error may not be
12381317 // 'static
@@ -1306,7 +1385,18 @@ where
13061385 E : Error ,
13071386{
13081387 fn from ( error : E ) -> Self {
1309- Report :: new ( error)
1388+ Report { error, show_backtrace : false , pretty : false }
1389+ }
1390+ }
1391+
1392+ #[ unstable( feature = "error_reporter" , issue = "90172" ) ]
1393+ impl < ' a , E > From < E > for Report < Box < dyn Error + ' a > >
1394+ where
1395+ E : Error + ' a ,
1396+ {
1397+ fn from ( error : E ) -> Self {
1398+ let error = box error;
1399+ Report { error, show_backtrace : false , pretty : false }
13101400 }
13111401}
13121402
@@ -1320,12 +1410,20 @@ where
13201410 }
13211411}
13221412
1413+ #[ unstable( feature = "error_reporter" , issue = "90172" ) ]
1414+ impl fmt:: Display for Report < Box < dyn Error > >
1415+ {
1416+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1417+ if self . pretty { self . fmt_multiline ( f) } else { self . fmt_singleline ( f) }
1418+ }
1419+ }
1420+
13231421// This type intentionally outputs the same format for `Display` and `Debug`for
13241422// situations where you unwrap a `Report` or return it from main.
13251423#[ unstable( feature = "error_reporter" , issue = "90172" ) ]
13261424impl < E > fmt:: Debug for Report < E >
13271425where
1328- E : Error ,
1426+ Report < E > : fmt :: Display ,
13291427{
13301428 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
13311429 fmt:: Display :: fmt ( self , f)
0 commit comments