mirror of https://github.com/zkat/miette.git
fix(report): conversion into `Box<dyn Diagnostic>` (#370)
Fixes: https://github.com/zkat/miette/issues/369 Diagnostic impls are no longer reset to default when converting a `Report` into a `Box<dyn Diagnostic>`. Also prevented `Report` vtables and handlers from being kept around on the heap after conversion.
This commit is contained in:
parent
edfdcb525e
commit
bdd1d74614
|
|
@ -542,7 +542,8 @@ where
|
|||
E: Diagnostic + Send + Sync + 'static,
|
||||
{
|
||||
// Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below.
|
||||
e.cast::<ErrorImpl<E>>().boxed()
|
||||
let unerased = e.cast::<ErrorImpl<E>>().boxed();
|
||||
Box::new(unerased._object)
|
||||
}
|
||||
|
||||
// Safety: requires layout of *e to match ErrorImpl<E>.
|
||||
|
|
@ -553,7 +554,8 @@ where
|
|||
E: StdError + Send + Sync + 'static,
|
||||
{
|
||||
// Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below.
|
||||
e.cast::<ErrorImpl<E>>().boxed()
|
||||
let unerased = e.cast::<ErrorImpl<E>>().boxed();
|
||||
Box::new(unerased._object)
|
||||
}
|
||||
|
||||
// Safety: requires layout of *e to match ErrorImpl<E>.
|
||||
|
|
@ -726,17 +728,6 @@ impl ErasedErrorImpl {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E> StdError for ErrorImpl<E>
|
||||
where
|
||||
E: StdError,
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
unsafe { ErrorImpl::diagnostic(self.erase()).source() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Diagnostic for ErrorImpl<E> where E: Diagnostic {}
|
||||
|
||||
impl<E> Debug for ErrorImpl<E>
|
||||
where
|
||||
E: Debug,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use miette::{miette, Diagnostic, LabeledSpan, Report, SourceSpan};
|
||||
use std::error::Error as StdError;
|
||||
use std::io;
|
||||
use std::ops::Deref;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
|
|
@ -159,7 +160,7 @@ impl Diagnostic for CustomDiagnostic {
|
|||
|
||||
#[test]
|
||||
fn test_boxed_custom_diagnostic() {
|
||||
fn assert_report(report: &Report) {
|
||||
fn assert_report<T: ?Sized + Diagnostic>(report: &impl Deref<Target = T>) {
|
||||
assert_eq!(
|
||||
report.source().map(|source| source.to_string()),
|
||||
Some("oh no!".to_owned()),
|
||||
|
|
@ -215,10 +216,16 @@ fn test_boxed_custom_diagnostic() {
|
|||
let main_diagnostic = Box::new(main_diagnostic) as Box<dyn Diagnostic + Send + Sync + 'static>;
|
||||
let report = miette!(main_diagnostic);
|
||||
assert_report(&report);
|
||||
|
||||
// Now make sure that conversion to a trait-object is lossless!
|
||||
let report_ref: &dyn Diagnostic = report.as_ref();
|
||||
assert_report(&report_ref);
|
||||
|
||||
let report_box: Box<dyn Diagnostic> = report.into();
|
||||
assert_report(&report_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "I don't know why this isn't working but it needs fixing."]
|
||||
fn test_boxed_sources() {
|
||||
let error = MyError {
|
||||
source: io::Error::new(io::ErrorKind::Other, "oh no!"),
|
||||
|
|
|
|||
Loading…
Reference in New Issue