Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turns out, Report *really* doesn't want to be an Error or Diagnostic... #368

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .helix/languages.toml
@@ -0,0 +1,2 @@
[language-server.rust-analyzer]
config = { cargo = { features = "all" } }
53 changes: 1 addition & 52 deletions src/eyreish/context.rs
@@ -1,4 +1,4 @@
use super::error::{ContextError, ErrorImpl};
use super::error::ContextError;
use super::{Report, WrapErr};
use core::fmt::{self, Debug, Display, Write};

Expand Down Expand Up @@ -27,15 +27,6 @@ mod ext {
Report::from_msg(msg, self)
}
}

impl Diag for Report {
fn ext_report<D>(self, msg: D) -> Report
where
D: Display + Send + Sync + 'static,
{
self.wrap_err(msg)
}
}
}

impl<T, E> WrapErr<T, E> for Result<T, E>
Expand Down Expand Up @@ -111,15 +102,6 @@ where
}
}

impl<D> StdError for ContextError<D, Report>
where
D: Display,
{
fn source(&self) -> Option<&(dyn StdError + 'static)> {
unsafe { Some(ErrorImpl::error(self.error.inner.by_ref())) }
}
}

impl<D, E> Diagnostic for ContextError<D, E>
where
D: Display,
Expand Down Expand Up @@ -154,39 +136,6 @@ where
}
}

impl<D> Diagnostic for ContextError<D, Report>
where
D: Display,
{
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).code() }
}

fn severity(&self) -> Option<crate::Severity> {
unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).severity() }
}

fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).help() }
}

fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).url() }
}

fn labels<'a>(&'a self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + 'a>> {
unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).labels() }
}

fn source_code(&self) -> Option<&dyn crate::SourceCode> {
self.error.source_code()
}

fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {
self.error.related()
}
}

struct Quoted<D>(D);

impl<D> Debug for Quoted<D>
Expand Down
140 changes: 55 additions & 85 deletions src/eyreish/error.rs
Expand Up @@ -2,14 +2,15 @@ use core::any::TypeId;
use core::fmt::{self, Debug, Display};
use core::mem::ManuallyDrop;
use core::ptr::{self, NonNull};
use std::any::type_name;
use std::error::Error as StdError;

use super::ptr::{Mut, Own, Ref};
use super::Report;
use super::ReportHandler;
use crate::chain::Chain;
use crate::eyreish::wrapper::WithSourceCode;
use crate::{Diagnostic, SourceCode};
use crate::{Diagnostic, LabeledSpan, Severity, SourceCode};
use core::ops::{Deref, DerefMut};

impl Report {
Expand All @@ -25,7 +26,8 @@ impl Report {
where
E: Diagnostic + Send + Sync + 'static,
{
Report::from_std(error)
dbg!("HEEEEEEEEEEEEEEEEEELLLLLLLLLLLLLLLOOOOOOOOOOOOOOOOOOOOOO>?");
dbg!(Report::from_std(error))
}

/// Create a new error object from a printable error message.
Expand Down Expand Up @@ -94,8 +96,6 @@ impl Report {
object_drop: object_drop::<E>,
object_ref: object_ref::<E>,
object_ref_stderr: object_ref_stderr::<E>,
object_boxed: object_boxed::<E>,
object_boxed_stderr: object_boxed_stderr::<E>,
object_downcast: object_downcast::<E>,
object_drop_rest: object_drop_front::<E>,
};
Expand All @@ -117,8 +117,6 @@ impl Report {
object_drop: object_drop::<MessageError<M>>,
object_ref: object_ref::<MessageError<M>>,
object_ref_stderr: object_ref_stderr::<MessageError<M>>,
object_boxed: object_boxed::<MessageError<M>>,
object_boxed_stderr: object_boxed_stderr::<MessageError<M>>,
object_downcast: object_downcast::<M>,
object_drop_rest: object_drop_front::<M>,
};
Expand All @@ -142,8 +140,6 @@ impl Report {
object_drop: object_drop::<ContextError<D, E>>,
object_ref: object_ref::<ContextError<D, E>>,
object_ref_stderr: object_ref_stderr::<ContextError<D, E>>,
object_boxed: object_boxed::<ContextError<D, E>>,
object_boxed_stderr: object_boxed_stderr::<ContextError<D, E>>,
object_downcast: context_downcast::<D, E>,
object_drop_rest: context_drop_rest::<D, E>,
};
Expand All @@ -164,8 +160,6 @@ impl Report {
object_drop: object_drop::<BoxedError>,
object_ref: object_ref::<BoxedError>,
object_ref_stderr: object_ref_stderr::<BoxedError>,
object_boxed: object_boxed::<BoxedError>,
object_boxed_stderr: object_boxed_stderr::<BoxedError>,
object_downcast: object_downcast::<Box<dyn Diagnostic + Send + Sync>>,
object_drop_rest: object_drop_front::<Box<dyn Diagnostic + Send + Sync>>,
};
Expand Down Expand Up @@ -223,8 +217,6 @@ impl Report {
object_drop: object_drop::<ContextError<D, Report>>,
object_ref: object_ref::<ContextError<D, Report>>,
object_ref_stderr: object_ref_stderr::<ContextError<D, Report>>,
object_boxed: object_boxed::<ContextError<D, Report>>,
object_boxed_stderr: object_boxed_stderr::<ContextError<D, Report>>,
object_downcast: context_chain_downcast::<D>,
object_drop_rest: context_chain_drop_rest::<D>,
};
Expand Down Expand Up @@ -363,7 +355,11 @@ impl Report {
unsafe {
// Use vtable to find NonNull<()> which points to a value of type E
// somewhere inside the data structure.
let addr = (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?;
dbg!(type_name::<E>());
let addr = dbg!((vtable(self.inner.ptr).object_downcast)(
self.inner.by_ref(),
target
))?;
Some(addr.cast::<E>().deref())
}
}
Expand Down Expand Up @@ -411,21 +407,10 @@ impl Report {

/// Provide source code for this error
pub fn with_source_code(self, source_code: impl SourceCode + Send + Sync + 'static) -> Report {
WithSourceCode {
Self::new(WithSourceCode {
source_code,
error: self,
}
.into()
}
}

impl<E> From<E> for Report
where
E: Diagnostic + Send + Sync + 'static,
{
#[cfg_attr(track_caller, track_caller)]
fn from(error: E) -> Self {
Report::from_std(error)
})
}
}

Expand Down Expand Up @@ -464,17 +449,52 @@ impl Drop for Report {
}
}

impl StdError for Report {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
(**self).source()
}
}

impl Diagnostic for Report {
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
(**self).code()
}

fn severity(&self) -> Option<Severity> {
(**self).severity()
}

fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
(**self).help()
}

fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
(**self).url()
}

fn source_code(&self) -> Option<&dyn SourceCode> {
(**self).source_code()
}

fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
(**self).labels()
}

fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {
(**self).related()
}

fn diagnostic_source(&self) -> Option<&dyn Diagnostic> {
(**self).diagnostic_source()
}
}

struct ErrorVTable {
object_drop: unsafe fn(Own<ErasedErrorImpl>),
object_ref:
unsafe fn(Ref<'_, ErasedErrorImpl>) -> Ref<'_, dyn Diagnostic + Send + Sync + 'static>,
object_ref_stderr:
unsafe fn(Ref<'_, ErasedErrorImpl>) -> Ref<'_, dyn StdError + Send + Sync + 'static>,
#[allow(clippy::type_complexity)]
object_boxed: unsafe fn(Own<ErasedErrorImpl>) -> Box<dyn Diagnostic + Send + Sync + 'static>,
#[allow(clippy::type_complexity)]
object_boxed_stderr:
unsafe fn(Own<ErasedErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static>,
object_downcast: unsafe fn(Ref<'_, ErasedErrorImpl>, TypeId) -> Option<Ref<'_, ()>>,
object_drop_rest: unsafe fn(Own<ErasedErrorImpl>, TypeId),
}
Expand Down Expand Up @@ -527,31 +547,15 @@ where
))
}

// Safety: requires layout of *e to match ErrorImpl<E>.
unsafe fn object_boxed<E>(e: Own<ErasedErrorImpl>) -> Box<dyn Diagnostic + Send + Sync + 'static>
where
E: Diagnostic + Send + Sync + 'static,
{
// Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below.
e.cast::<ErrorImpl<E>>().boxed()
}

// Safety: requires layout of *e to match ErrorImpl<E>.
unsafe fn object_boxed_stderr<E>(
e: Own<ErasedErrorImpl>,
) -> Box<dyn StdError + Send + Sync + 'static>
where
E: StdError + Send + Sync + 'static,
{
// Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below.
e.cast::<ErrorImpl<E>>().boxed()
}

// Safety: requires layout of *e to match ErrorImpl<E>.
unsafe fn object_downcast<E>(e: Ref<'_, ErasedErrorImpl>, target: TypeId) -> Option<Ref<'_, ()>>
where
E: 'static,
{
dbg!(
"object_downcast????????????????????????????????????????????????????????????????",
type_name::<E>()
);
if TypeId::of::<E>() == target {
// Caller is looking for an E pointer and e is ErrorImpl<E>, take a
// pointer to its E field.
Expand Down Expand Up @@ -745,40 +749,6 @@ where
}
}

impl From<Report> for Box<dyn Diagnostic + Send + Sync + 'static> {
fn from(error: Report) -> Self {
let outer = ManuallyDrop::new(error);
unsafe {
// Use vtable to attach ErrorImpl<E>'s native StdError vtable for
// the right original type E.
(vtable(outer.inner.ptr).object_boxed)(outer.inner)
}
}
}

impl From<Report> for Box<dyn StdError + Send + Sync + 'static> {
fn from(error: Report) -> Self {
let outer = ManuallyDrop::new(error);
unsafe {
// Use vtable to attach ErrorImpl<E>'s native StdError vtable for
// the right original type E.
(vtable(outer.inner.ptr).object_boxed_stderr)(outer.inner)
}
}
}

impl From<Report> for Box<dyn Diagnostic + 'static> {
fn from(error: Report) -> Self {
Box::<dyn Diagnostic + Send + Sync>::from(error)
}
}

impl From<Report> for Box<dyn StdError + 'static> {
fn from(error: Report) -> Self {
Box::<dyn StdError + Send + Sync>::from(error)
}
}

impl AsRef<dyn Diagnostic + Send + Sync> for Report {
fn as_ref(&self) -> &(dyn Diagnostic + Send + Sync + 'static) {
&**self
Expand Down
2 changes: 1 addition & 1 deletion src/eyreish/into_diagnostic.rs
Expand Up @@ -28,6 +28,6 @@ pub trait IntoDiagnostic<T, E> {

impl<T, E: std::error::Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E> {
fn into_diagnostic(self) -> Result<T, Report> {
self.map_err(|e| DiagnosticError(Box::new(e)).into())
self.map_err(|e| Report::new(DiagnosticError(Box::new(e))))
}
}
6 changes: 3 additions & 3 deletions src/eyreish/kind.rs
Expand Up @@ -80,15 +80,15 @@ pub trait TraitKind: Sized {
}
}

impl<E> TraitKind for E where E: Into<Report> {}
impl<E> TraitKind for E where E: Diagnostic + Send + Sync + 'static {}

impl Trait {
#[cfg_attr(track_caller, track_caller)]
pub fn new<E>(self, error: E) -> Report
where
E: Into<Report>,
E: Diagnostic + Send + Sync + 'static,
{
error.into()
Report::new(error)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/eyreish/macros.rs
Expand Up @@ -228,7 +228,7 @@ macro_rules! ensure {
#[macro_export]
macro_rules! miette {
($($key:ident = $value:expr,)* $fmt:literal $($arg:tt)*) => {
$crate::Report::from(
$crate::Report::new(
$crate::diagnostic!($($key = $value,)* $fmt $($arg)*)
)
};
Expand Down
2 changes: 2 additions & 0 deletions src/eyreish/ptr.rs
Expand Up @@ -58,6 +58,8 @@ where
}
}

// FIXME: Delete this derive!
#[derive(Debug)]
#[allow(explicit_outlives_requirements)]
#[repr(transparent)]
/// A raw pointer that represents a shared borrow of its pointee
Expand Down