Attempt to fix tidy errors
This commit is contained in:
parent
c6de41331c
commit
c0f14cb930
2 changed files with 345 additions and 79 deletions
|
@ -25,7 +25,7 @@ use crate::backtrace::Backtrace;
|
||||||
use crate::borrow::Cow;
|
use crate::borrow::Cow;
|
||||||
use crate::cell;
|
use crate::cell;
|
||||||
use crate::char;
|
use crate::char;
|
||||||
use crate::fmt::{self, Debug, Display, Write};
|
use crate::fmt::{self, Debug, Display};
|
||||||
use crate::mem::transmute;
|
use crate::mem::transmute;
|
||||||
use crate::num;
|
use crate::num;
|
||||||
use crate::str;
|
use crate::str;
|
||||||
|
@ -816,6 +816,7 @@ impl dyn Error + Send + Sync {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(error_reporter)]
|
/// #![feature(error_reporter)]
|
||||||
|
/// #![feature(negative_impls)]
|
||||||
///
|
///
|
||||||
/// use std::error::{Error, Report};
|
/// use std::error::{Error, Report};
|
||||||
/// use std::fmt;
|
/// use std::fmt;
|
||||||
|
@ -848,6 +849,10 @@ impl dyn Error + Send + Sync {
|
||||||
///
|
///
|
||||||
/// impl Error for SuperErrorSideKick {}
|
/// impl Error for SuperErrorSideKick {}
|
||||||
///
|
///
|
||||||
|
/// // Note that the error doesn't need to be `Send` or `Sync`.
|
||||||
|
/// impl !Send for SuperError {}
|
||||||
|
/// impl !Sync for SuperError {}
|
||||||
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let error = SuperError { side: SuperErrorSideKick };
|
/// let error = SuperError { side: SuperErrorSideKick };
|
||||||
/// let report = Report::new(&error).pretty(true);
|
/// let report = Report::new(&error).pretty(true);
|
||||||
|
@ -855,10 +860,37 @@ impl dyn Error + Send + Sync {
|
||||||
/// println!("{}", report);
|
/// println!("{}", report);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// `Report` only requires that the wrapped error implements `Error`. It doesn't require that the
|
||||||
|
/// wrapped error be `Send`, `Sync`, or `'static`.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #![feature(error_reporter)]
|
||||||
|
/// # use std::fmt;
|
||||||
|
/// # use std::error::{Error, Report};
|
||||||
|
/// #[derive(Debug)]
|
||||||
|
/// struct SuperError<'a> {
|
||||||
|
/// side: &'a str,
|
||||||
|
/// }
|
||||||
|
/// impl<'a> fmt::Display for SuperError<'a> {
|
||||||
|
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
/// write!(f, "SuperError is here: {}", self.side)
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// impl<'a> Error for SuperError<'a> {}
|
||||||
|
/// fn main() {
|
||||||
|
/// let msg = String::from("Huzzah!");
|
||||||
|
/// let report = Report::new(SuperError { side: &msg });
|
||||||
|
/// println!("{}", report);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[unstable(feature = "error_reporter", issue = "90172")]
|
#[unstable(feature = "error_reporter", issue = "90172")]
|
||||||
pub struct Report<E> {
|
pub struct Report<E> {
|
||||||
|
/// The error being reported.
|
||||||
error: E,
|
error: E,
|
||||||
|
/// Whether a backtrace should be included as part of the report.
|
||||||
show_backtrace: bool,
|
show_backtrace: bool,
|
||||||
|
/// Whether the report should be pretty-printed.
|
||||||
pretty: bool,
|
pretty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -911,18 +943,15 @@ where
|
||||||
write!(f, "\n\nCaused by:")?;
|
write!(f, "\n\nCaused by:")?;
|
||||||
|
|
||||||
let multiple = cause.source().is_some();
|
let multiple = cause.source().is_some();
|
||||||
let format = if multiple {
|
|
||||||
Format::Numbered { ind: 0 }
|
|
||||||
} else {
|
|
||||||
Format::Uniform { indentation: " " }
|
|
||||||
};
|
|
||||||
|
|
||||||
for error in cause.chain() {
|
for (ind, error) in cause.chain().enumerate() {
|
||||||
writeln!(f)?;
|
writeln!(f)?;
|
||||||
|
|
||||||
let mut indented = Indented { inner: f, needs_indent: true, format };
|
if multiple {
|
||||||
|
write!(f, "{: >4}: {}", ind, Indented { source: error })?;
|
||||||
write!(indented, "{}", error)?;
|
} else {
|
||||||
|
write!(f, " {}", error)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -930,14 +959,10 @@ where
|
||||||
let backtrace = error.backtrace();
|
let backtrace = error.backtrace();
|
||||||
|
|
||||||
if let Some(backtrace) = backtrace {
|
if let Some(backtrace) = backtrace {
|
||||||
let mut backtrace = backtrace.to_string();
|
let backtrace = backtrace.to_string();
|
||||||
|
|
||||||
write!(f, "\n\n")?;
|
f.write_str("\n\nStack backtrace:\n")?;
|
||||||
writeln!(f, "Stack backtrace:")?;
|
f.write_str(backtrace.trim_end())?;
|
||||||
|
|
||||||
backtrace.truncate(backtrace.trim_end().len());
|
|
||||||
|
|
||||||
write!(f, "{}", backtrace)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,76 +1002,26 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encapsulates how error sources are indented and formatted.
|
/// Wrapper type for indenting the inner source.
|
||||||
struct Indented<'a, D: ?Sized> {
|
struct Indented<D> {
|
||||||
inner: &'a mut D,
|
source: D,
|
||||||
needs_indent: bool,
|
|
||||||
format: Format,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The possible variants that error sources can be formatted as.
|
impl<D> fmt::Display for Indented<D>
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
enum Format {
|
|
||||||
/// Insert uniform indentation before every line.
|
|
||||||
///
|
|
||||||
/// This format takes a static string as input and inserts it after every newline.
|
|
||||||
Uniform {
|
|
||||||
/// The string to insert as indentation.
|
|
||||||
indentation: &'static str,
|
|
||||||
},
|
|
||||||
/// Inserts a number before the first line.
|
|
||||||
///
|
|
||||||
/// This format hard codes the indentation level to match the indentation from
|
|
||||||
/// `std::backtrace::Backtrace`.
|
|
||||||
Numbered {
|
|
||||||
/// The index to insert before the first line of output.
|
|
||||||
ind: usize,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<D> Write for Indented<'_, D>
|
|
||||||
where
|
where
|
||||||
D: Write + ?Sized,
|
D: fmt::Display,
|
||||||
{
|
{
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
for (ind, line) in s.split('\n').enumerate() {
|
let source = self.source.to_string();
|
||||||
|
|
||||||
|
for (ind, line) in source.trim().split('\n').filter(|l| !l.is_empty()).enumerate() {
|
||||||
if ind > 0 {
|
if ind > 0 {
|
||||||
self.inner.write_char('\n')?;
|
write!(f, "\n {}", line)?;
|
||||||
self.needs_indent = true;
|
} else {
|
||||||
|
write!(f, "{}", line)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.needs_indent {
|
|
||||||
if line.is_empty() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.format.insert_indentation(ind, &mut self.inner)?;
|
|
||||||
self.needs_indent = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.inner.write_fmt(format_args!("{}", line))?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Format {
|
|
||||||
/// Write the specified formatting to the write buffer.
|
|
||||||
fn insert_indentation(&mut self, line: usize, f: &mut dyn Write) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Format::Uniform { indentation } => {
|
|
||||||
write!(f, "{}", indentation)
|
|
||||||
}
|
|
||||||
Format::Numbered { ind } => {
|
|
||||||
if line == 0 {
|
|
||||||
write!(f, "{: >4}: ", ind)?;
|
|
||||||
*ind += 1;
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
write!(f, " ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -35,3 +35,294 @@ fn downcasting() {
|
||||||
Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A),
|
Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::backtrace;
|
||||||
|
use crate::env;
|
||||||
|
use crate::error::Report;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct SuperError {
|
||||||
|
side: SuperErrorSideKick,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SuperError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "SuperError is here!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for SuperError {
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
Some(&self.side)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct SuperErrorSideKick;
|
||||||
|
|
||||||
|
impl fmt::Display for SuperErrorSideKick {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "SuperErrorSideKick is here!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for SuperErrorSideKick {}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn single_line_formatting() {
|
||||||
|
let error = SuperError { side: SuperErrorSideKick };
|
||||||
|
let report = Report::new(&error);
|
||||||
|
let actual = report.to_string();
|
||||||
|
let expected = String::from("SuperError is here!: SuperErrorSideKick is here!");
|
||||||
|
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_line_formatting() {
|
||||||
|
let error = SuperError { side: SuperErrorSideKick };
|
||||||
|
let report = Report::new(&error).pretty(true);
|
||||||
|
let actual = report.to_string();
|
||||||
|
let expected =
|
||||||
|
String::from("SuperError is here!\n\nCaused by:\n SuperErrorSideKick is here!");
|
||||||
|
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn error_with_no_sources_formats_single_line_correctly() {
|
||||||
|
let report = Report::new(SuperErrorSideKick);
|
||||||
|
let actual = report.to_string();
|
||||||
|
let expected = String::from("SuperErrorSideKick is here!");
|
||||||
|
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn error_with_no_sources_formats_multi_line_correctly() {
|
||||||
|
let report = Report::new(SuperErrorSideKick).pretty(true);
|
||||||
|
let actual = report.to_string();
|
||||||
|
let expected = String::from("SuperErrorSideKick is here!");
|
||||||
|
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn error_with_backtrace_outputs_correctly() {
|
||||||
|
use backtrace::Backtrace;
|
||||||
|
|
||||||
|
env::remove_var("RUST_BACKTRACE");
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct ErrorWithBacktrace<'a> {
|
||||||
|
msg: &'a str,
|
||||||
|
trace: Backtrace,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> fmt::Display for ErrorWithBacktrace<'a> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Error with backtrace: {}", self.msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Error for ErrorWithBacktrace<'a> {
|
||||||
|
fn backtrace(&self) -> Option<&Backtrace> {
|
||||||
|
Some(&self.trace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let msg = String::from("The source of the error");
|
||||||
|
let report = Report::new(ErrorWithBacktrace { msg: &msg, trace: Backtrace::capture() })
|
||||||
|
.pretty(true)
|
||||||
|
.show_backtrace(true);
|
||||||
|
|
||||||
|
let expected = String::from(
|
||||||
|
"Error with backtrace: The source of the error\n\nStack backtrace:\ndisabled backtrace",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(expected, report.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct GenericError<D> {
|
||||||
|
message: D,
|
||||||
|
source: Option<Box<dyn Error + 'static>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> GenericError<D> {
|
||||||
|
fn new(message: D) -> GenericError<D> {
|
||||||
|
Self { message, source: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_source<E>(message: D, source: E) -> GenericError<D>
|
||||||
|
where
|
||||||
|
E: Error + 'static,
|
||||||
|
{
|
||||||
|
let source: Box<dyn Error + 'static> = Box::new(source);
|
||||||
|
let source = Some(source);
|
||||||
|
GenericError { message, source }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> fmt::Display for GenericError<D>
|
||||||
|
where
|
||||||
|
D: fmt::Display,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Display::fmt(&self.message, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> Error for GenericError<D>
|
||||||
|
where
|
||||||
|
D: fmt::Debug + fmt::Display,
|
||||||
|
{
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
self.source.as_deref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn error_formats_single_line_with_rude_display_impl() {
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct MyMessage;
|
||||||
|
|
||||||
|
impl fmt::Display for MyMessage {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str("line 1\nline 2")?;
|
||||||
|
f.write_str("\nline 3\nline 4\n")?;
|
||||||
|
f.write_str("line 5\nline 6")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let error = GenericError::new(MyMessage);
|
||||||
|
let error = GenericError::new_with_source(MyMessage, error);
|
||||||
|
let error = GenericError::new_with_source(MyMessage, error);
|
||||||
|
let error = GenericError::new_with_source(MyMessage, error);
|
||||||
|
let report = Report::new(error);
|
||||||
|
let expected = r#"line 1
|
||||||
|
line 2
|
||||||
|
line 3
|
||||||
|
line 4
|
||||||
|
line 5
|
||||||
|
line 6: line 1
|
||||||
|
line 2
|
||||||
|
line 3
|
||||||
|
line 4
|
||||||
|
line 5
|
||||||
|
line 6: line 1
|
||||||
|
line 2
|
||||||
|
line 3
|
||||||
|
line 4
|
||||||
|
line 5
|
||||||
|
line 6: line 1
|
||||||
|
line 2
|
||||||
|
line 3
|
||||||
|
line 4
|
||||||
|
line 5
|
||||||
|
line 6"#;
|
||||||
|
|
||||||
|
let actual = report.to_string();
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn error_formats_multi_line_with_rude_display_impl() {
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct MyMessage;
|
||||||
|
|
||||||
|
impl fmt::Display for MyMessage {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str("line 1\nline 2")?;
|
||||||
|
f.write_str("\nline 3\nline 4\n")?;
|
||||||
|
f.write_str("line 5\nline 6")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let error = GenericError::new(MyMessage);
|
||||||
|
let error = GenericError::new_with_source(MyMessage, error);
|
||||||
|
let error = GenericError::new_with_source(MyMessage, error);
|
||||||
|
let error = GenericError::new_with_source(MyMessage, error);
|
||||||
|
let report = Report::new(error).pretty(true);
|
||||||
|
let expected = r#"line 1
|
||||||
|
line 2
|
||||||
|
line 3
|
||||||
|
line 4
|
||||||
|
line 5
|
||||||
|
line 6
|
||||||
|
|
||||||
|
Caused by:
|
||||||
|
0: line 1
|
||||||
|
line 2
|
||||||
|
line 3
|
||||||
|
line 4
|
||||||
|
line 5
|
||||||
|
line 6
|
||||||
|
1: line 1
|
||||||
|
line 2
|
||||||
|
line 3
|
||||||
|
line 4
|
||||||
|
line 5
|
||||||
|
line 6
|
||||||
|
2: line 1
|
||||||
|
line 2
|
||||||
|
line 3
|
||||||
|
line 4
|
||||||
|
line 5
|
||||||
|
line 6"#;
|
||||||
|
|
||||||
|
let actual = report.to_string();
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn errors_that_start_with_newline_formats_correctly() {
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct MyMessage;
|
||||||
|
|
||||||
|
impl fmt::Display for MyMessage {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str("\nThe message\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let error = GenericError::new(MyMessage);
|
||||||
|
let error = GenericError::new_with_source(MyMessage, error);
|
||||||
|
let error = GenericError::new_with_source(MyMessage, error);
|
||||||
|
let report = Report::new(error).pretty(true);
|
||||||
|
let expected = r#"
|
||||||
|
The message
|
||||||
|
|
||||||
|
|
||||||
|
Caused by:
|
||||||
|
0: The message
|
||||||
|
1: The message"#;
|
||||||
|
|
||||||
|
let actual = report.to_string();
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn errors_with_string_interpolation_formats_correctly() {
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct MyMessage(usize);
|
||||||
|
|
||||||
|
impl fmt::Display for MyMessage {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Got an error code: ({}). ", self.0)?;
|
||||||
|
write!(f, "What would you like to do in response?")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let error = GenericError::new(MyMessage(10));
|
||||||
|
let error = GenericError::new_with_source(MyMessage(20), error);
|
||||||
|
let report = Report::new(error).pretty(true);
|
||||||
|
let expected = r#"Got an error code: (20). What would you like to do in response?
|
||||||
|
|
||||||
|
Caused by:
|
||||||
|
Got an error code: (10). What would you like to do in response?"#;
|
||||||
|
let actual = report.to_string();
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue