Skip to content

Commit 59df6c8

Browse files
committed
Try commiting again
1 parent 547a6ff commit 59df6c8

File tree

1 file changed

+244
-1
lines changed

1 file changed

+244
-1
lines changed

library/std/src/error.rs

Lines changed: 244 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::backtrace::Backtrace;
2525
use crate::borrow::Cow;
2626
use crate::cell;
2727
use crate::char;
28-
use crate::fmt::{self, Debug, Display};
28+
use crate::fmt::{self, Debug, Display, Write};
2929
use crate::mem::transmute;
3030
use crate::num;
3131
use crate::str;
@@ -807,3 +807,246 @@ impl dyn Error + Send + Sync {
807807
})
808808
}
809809
}
810+
811+
/// An error reporter that exposes the entire error chain for printing.
812+
/// It also exposes options for formatting the error chain, either entirely on a single line,
813+
/// or in multi-line format with each cause in the error chain on a new line.
814+
///
815+
/// # Examples
816+
///
817+
/// ```
818+
/// #![feature(error_reporter)]
819+
///
820+
/// use std::error::{Error, Report};
821+
/// use std::fmt;
822+
///
823+
/// #[derive(Debug)]
824+
/// struct SuperError {
825+
/// side: SuperErrorSideKick,
826+
/// }
827+
///
828+
/// impl fmt::Display for SuperError {
829+
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
830+
/// write!(f, "SuperError is here!")
831+
/// }
832+
/// }
833+
///
834+
/// impl Error for SuperError {
835+
/// fn source(&self) -> Option<&(dyn Error + 'static)> {
836+
/// Some(&self.side)
837+
/// }
838+
/// }
839+
///
840+
/// #[derive(Debug)]
841+
/// struct SuperErrorSideKick;
842+
///
843+
/// impl fmt::Display for SuperErrorSideKick {
844+
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
845+
/// write!(f, "SuperErrorSideKick is here!")
846+
/// }
847+
/// }
848+
///
849+
/// impl Error for SuperErrorSideKick {}
850+
///
851+
/// fn main() {
852+
/// let error = SuperError { side: SuperErrorSideKick };
853+
/// let report = Report::new(&error).pretty();
854+
///
855+
/// println!("{}", report);
856+
/// }
857+
/// ```
858+
#[unstable(feature = "error_reporter", issue = "90172")]
859+
pub struct Report<E> {
860+
source: E,
861+
show_backtrace: bool,
862+
pretty: bool,
863+
}
864+
865+
impl<E> Report<E>
866+
where
867+
E: Error,
868+
{
869+
/// Create a new `Report` from an input error.
870+
#[unstable(feature = "error_reporter", issue = "90172")]
871+
pub fn new(source: E) -> Report<E> {
872+
Report { source, show_backtrace: false, pretty: false }
873+
}
874+
875+
/// Enable pretty-printing the report.
876+
#[unstable(feature = "error_reporter", issue = "90172")]
877+
pub fn pretty(mut self) -> Self {
878+
self.pretty = true;
879+
self
880+
}
881+
882+
/// Enable showing a backtrace for the report.
883+
#[unstable(feature = "error_reporter", issue = "90172")]
884+
pub fn show_backtrace(mut self) -> Self {
885+
self.show_backtrace = true;
886+
self
887+
}
888+
889+
/// Format the report as a single line.
890+
#[unstable(feature = "error_reporter", issue = "90172")]
891+
fn fmt_singleline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
892+
write!(f, "{}", self.source)?;
893+
894+
let sources = self.source.source().into_iter().flat_map(<dyn Error>::chain);
895+
896+
for cause in sources {
897+
write!(f, ": {}", cause)?;
898+
}
899+
900+
Ok(())
901+
}
902+
903+
/// Format the report as multiple lines, with each error cause on its own line.
904+
#[unstable(feature = "error_reporter", issue = "90172")]
905+
fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
906+
let error = &self.source;
907+
908+
write!(f, "{}", error)?;
909+
910+
if let Some(cause) = error.source() {
911+
write!(f, "\n\nCaused by:")?;
912+
913+
let multiple = cause.source().is_some();
914+
let format = if multiple {
915+
Format::Numbered { ind: 0 }
916+
} else {
917+
Format::Uniform { indentation: " " }
918+
};
919+
920+
for error in cause.chain() {
921+
writeln!(f)?;
922+
923+
let mut indented = Indented { inner: f, needs_indent: true, format };
924+
925+
write!(indented, "{}", error)?;
926+
}
927+
}
928+
929+
if self.show_backtrace {
930+
let backtrace = error.backtrace();
931+
932+
if let Some(backtrace) = backtrace {
933+
let mut backtrace = backtrace.to_string();
934+
935+
write!(f, "\n\n")?;
936+
writeln!(f, "Stack backtrace:")?;
937+
938+
backtrace.truncate(backtrace.trim_end().len());
939+
940+
write!(f, "{}", backtrace)?;
941+
}
942+
}
943+
944+
Ok(())
945+
}
946+
}
947+
948+
#[unstable(feature = "error_reporter", issue = "90172")]
949+
impl<E> From<E> for Report<E>
950+
where
951+
E: Error,
952+
{
953+
fn from(source: E) -> Self {
954+
Report::new(source)
955+
}
956+
}
957+
958+
#[unstable(feature = "error_reporter", issue = "90172")]
959+
impl<E> fmt::Display for Report<E>
960+
where
961+
E: Error,
962+
{
963+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
964+
if self.pretty { self.fmt_multiline(f) } else { self.fmt_singleline(f) }
965+
}
966+
}
967+
968+
// This type intentionally outputs the same format for `Display` and `Debug`for
969+
// situations where you unwrap a `Report` or return it from main.
970+
#[unstable(feature = "error_reporter", issue = "90172")]
971+
impl<E> fmt::Debug for Report<E>
972+
where
973+
E: Error,
974+
{
975+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
976+
fmt::Display::fmt(self, f)
977+
}
978+
}
979+
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+
}
1006+
1007+
impl<D> Write for Indented<'_, D>
1008+
where
1009+
D: Write + ?Sized,
1010+
{
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+
}
1022+
1023+
self.format.insert_indentation(ind, &mut self.inner)?;
1024+
self.needs_indent = false;
1025+
}
1026+
1027+
self.inner.write_fmt(format_args!("{}", line))?;
1028+
}
1029+
1030+
Ok(())
1031+
}
1032+
}
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

Comments
 (0)