@@ -914,106 +914,109 @@ impl dyn Error + Send + Sync {
914
914
/// thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: SuperError is here!: SuperErrorSideKick is here!', src/error.rs:34:40
915
915
/// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
916
916
/// ```
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
+ /// ```
1015
1018
#[ unstable( feature = "error_reporter" , issue = "90172" ) ]
1016
- pub struct Report < E > {
1019
+ pub struct Report < E = Box < dyn Error > > {
1017
1020
/// The error being reported.
1018
1021
error : E ,
1019
1022
/// Whether a backtrace should be included as part of the report.
@@ -1024,14 +1027,16 @@ pub struct Report<E> {
1024
1027
1025
1028
impl < E > Report < E >
1026
1029
where
1027
- E : Error ,
1030
+ Report < E > : From < E > ,
1028
1031
{
1029
1032
/// Create a new `Report` from an input error.
1030
1033
#[ unstable( feature = "error_reporter" , issue = "90172" ) ]
1031
1034
pub fn new ( error : E ) -> Report < E > {
1032
- Report { error , show_backtrace : false , pretty : false }
1035
+ Self :: from ( error )
1033
1036
}
1037
+ }
1034
1038
1039
+ impl < E > Report < E > {
1035
1040
/// Enable pretty-printing the report across multiple lines.
1036
1041
///
1037
1042
/// # Examples
@@ -1232,7 +1237,81 @@ where
1232
1237
self . show_backtrace = show_backtrace;
1233
1238
self
1234
1239
}
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
+ }
1235
1312
1313
+ impl Report < Box < dyn Error > >
1314
+ {
1236
1315
fn backtrace ( & self ) -> Option < & Backtrace > {
1237
1316
// have to grab the backtrace on the first error directly since that error may not be
1238
1317
// 'static
@@ -1306,7 +1385,18 @@ where
1306
1385
E : Error ,
1307
1386
{
1308
1387
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 }
1310
1400
}
1311
1401
}
1312
1402
@@ -1320,12 +1410,20 @@ where
1320
1410
}
1321
1411
}
1322
1412
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
+
1323
1421
// This type intentionally outputs the same format for `Display` and `Debug`for
1324
1422
// situations where you unwrap a `Report` or return it from main.
1325
1423
#[ unstable( feature = "error_reporter" , issue = "90172" ) ]
1326
1424
impl < E > fmt:: Debug for Report < E >
1327
1425
where
1328
- E : Error ,
1426
+ Report < E > : fmt :: Display ,
1329
1427
{
1330
1428
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1331
1429
fmt:: Display :: fmt ( self , f)
0 commit comments