feat(no_std): Implement comprehensive no_std support

This commit finishes full no_std support to miette.
This commit is contained in:
François Garillot 2025-10-18 07:44:18 -04:00
parent 243ea534e8
commit 79fbd0a07d
No known key found for this signature in database
GPG Key ID: E7645C6B883A1E9A
42 changed files with 198 additions and 104 deletions

View File

@ -32,22 +32,19 @@ syntect = { version = "5.1.0", optional = true }
[dev-dependencies] [dev-dependencies]
semver = "1.0.21" semver = "1.0.21"
[build-dependencies]
rustc_version = "0.2"
# Eyre devdeps
futures = { version = "0.3", default-features = false } futures = { version = "0.3", default-features = false }
indenter = "0.3.3" indenter = "0.3.3"
rustversion = "1.0" rustversion = "1.0"
trybuild = { version = "1.0.89", features = ["diff"] } trybuild = { version = "1.0.89", features = ["diff"] }
syn = { version = "2.0.87", features = ["full"] } syn = { version = "2.0.87", features = ["full"] }
regex = "1.10" regex = "1.10"
serde = { version = "1.0.196", features = ["derive"] } serde = { version = "1.0.196", features = ["derive"] }
serde_json = "1.0.113" serde_json = "1.0.113"
strip-ansi-escapes = "0.2.0" strip-ansi-escapes = "0.2.0"
[build-dependencies]
rustc_version = "0.2"
[features] [features]
default = ["derive", "std"] default = ["derive", "std"]
std = ["thiserror/std", "fancy-no-syscall"] std = ["thiserror/std", "fancy-no-syscall"]

19
build.rs Normal file
View File

@ -0,0 +1,19 @@
use rustc_version::{version_meta, Channel};
fn main() {
if let Channel::Nightly = version_meta().unwrap().channel {
println!("cargo:rustc-cfg=nightly")
}
// Configure track_caller based on Rust version
if let Ok(version) = rustc_version::version() {
if version >= rustc_version::Version::new(1, 46, 0) {
println!("cargo:rustc-cfg=track_caller");
}
}
// Add check-cfg for conditional configurations
println!("cargo:rustc-check-cfg=cfg(doc_cfg)");
println!("cargo:rustc-check-cfg=cfg(track_caller)");
println!("cargo:rustc-check-cfg=cfg(nightly)");
}

View File

@ -2,6 +2,8 @@
//! so the decoding source will be annotated with the decoding error, //! so the decoding source will be annotated with the decoding error,
//! providing contextual information about the error. //! providing contextual information about the error.
extern crate alloc;
use miette::{IntoDiagnostic, SourceOffset}; use miette::{IntoDiagnostic, SourceOffset};
use serde_json::{self, json}; use serde_json::{self, json};

View File

@ -71,9 +71,7 @@ impl Severity {
syn::Fields::Unnamed(_) => quote! { (..) }, syn::Fields::Unnamed(_) => quote! { (..) },
syn::Fields::Unit => quote! {}, syn::Fields::Unit => quote! {},
}; };
Some( Some(quote! { Self::#ident #fields => Option::Some(miette::Severity::#severity), })
quote! { Self::#ident #fields => Option::Some(miette::Severity::#severity), },
)
}, },
) )
} }

View File

@ -5,9 +5,6 @@ NOTE: This module is taken wholesale from <https://crates.io/crates/eyre>.
*/ */
extern crate alloc; extern crate alloc;
#[cfg(feature = "std")]
use std::error::Error as StdError;
#[cfg(not(feature = "std"))]
use crate::StdError; use crate::StdError;
use alloc::vec::{self, Vec}; use alloc::vec::{self, Vec};

View File

@ -2,10 +2,7 @@
Iterate over error `.diagnostic_source()` chains. Iterate over error `.diagnostic_source()` chains.
*/ */
extern crate alloc;
use crate::protocol::Diagnostic; use crate::protocol::Diagnostic;
use alloc::string::ToString;
/// Iterator of a chain of cause errors. /// Iterator of a chain of cause errors.
#[derive(Clone, Default)] #[derive(Clone, Default)]

View File

@ -3,12 +3,10 @@ Default trait implementations for [`Diagnostic`].
*/ */
extern crate alloc; extern crate alloc;
use core::{convert::Infallible, fmt::Display};
use alloc::boxed::Box; use alloc::boxed::Box;
use core::{convert::Infallible, fmt::Display};
use crate::{Diagnostic, LabeledSpan, Severity, SourceCode, StdError}; use crate::{Diagnostic, LabeledSpan, Severity, SourceCode};
impl StdError for Infallible {}
impl Diagnostic for Infallible { impl Diagnostic for Infallible {
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {

View File

@ -1,13 +1,13 @@
extern crate alloc; extern crate alloc;
#[cfg(feature = "std")]
use std::io;
#[cfg(feature = "std")]
use std::error::Error;
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
use crate::StdError as Error; use crate::StdError as Error;
use core::fmt::{self, Display};
use alloc::boxed::Box; use alloc::boxed::Box;
use core::fmt::{self, Display};
#[cfg(feature = "std")]
use std::error::Error;
#[cfg(feature = "std")]
use std::io;
use crate::Diagnostic; use crate::Diagnostic;
@ -83,17 +83,17 @@ impl Diagnostic for MietteError {
}; };
Some(Box::new(alloc::format!( Some(Box::new(alloc::format!(
"https://docs.rs/miette/{}/miette/enum.MietteError.html{}", "https://docs.rs/miette/{}/miette/enum.MietteError.html{}",
crate_version, variant, crate_version,
variant,
))) )))
} }
} }
#[cfg(test)] #[cfg(test)]
pub(crate) mod tests { pub(crate) mod tests {
#[cfg(feature = "std")] #[cfg(not(feature = "std"))]
use std::io::ErrorKind; use crate::StdError as Error;
#[cfg(not(feature = "std"))] use std::string::ToString;
use crate::StdError as Error;
use super::*; use super::*;
@ -126,9 +126,9 @@ pub(crate) mod tests {
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[test] #[test]
fn io_error() { fn io_error() {
let inner_error = io::Error::new(ErrorKind::Other, "halt and catch fire"); let inner_error = io::Error::other("halt and catch fire");
let outer_error = TestError(inner_error); let outer_error = TestError(inner_error);
let io_error = io::Error::new(ErrorKind::Other, outer_error); let io_error = io::Error::other(outer_error);
let miette_error = MietteError::from(io_error); let miette_error = MietteError::from(io_error);

View File

@ -2,13 +2,10 @@ extern crate alloc;
use super::error::{ContextError, ErrorImpl}; use super::error::{ContextError, ErrorImpl};
use super::{Report, WrapErr}; use super::{Report, WrapErr};
use core::fmt::{self, Debug, Display, Write};
use core::convert::Infallible; use core::convert::Infallible;
use core::fmt::{self, Debug, Display, Write};
#[cfg(feature = "std")] use crate::StdError;
use std::error::Error as StdError;
#[cfg(not(feature = "std"))]
use crate::StdError as StdError;
use alloc::boxed::Box; use alloc::boxed::Box;
use crate::{Diagnostic, LabeledSpan}; use crate::{Diagnostic, LabeledSpan};
@ -27,6 +24,7 @@ mod ext {
where where
E: Diagnostic + Send + Sync + 'static, E: Diagnostic + Send + Sync + 'static,
{ {
#[cfg_attr(track_caller, track_caller)]
fn ext_report<D>(self, msg: D) -> Report fn ext_report<D>(self, msg: D) -> Report
where where
D: Display + Send + Sync + 'static, D: Display + Send + Sync + 'static,
@ -36,6 +34,7 @@ mod ext {
} }
impl Diag for Report { impl Diag for Report {
#[cfg_attr(track_caller, track_caller)]
fn ext_report<D>(self, msg: D) -> Report fn ext_report<D>(self, msg: D) -> Report
where where
D: Display + Send + Sync + 'static, D: Display + Send + Sync + 'static,
@ -46,6 +45,7 @@ mod ext {
} }
impl<T> WrapErr<T, Infallible> for Option<T> { impl<T> WrapErr<T, Infallible> for Option<T> {
#[cfg_attr(track_caller, track_caller)]
fn wrap_err<D>(self, msg: D) -> Result<T, Report> fn wrap_err<D>(self, msg: D) -> Result<T, Report>
where where
D: Display + Send + Sync + 'static, D: Display + Send + Sync + 'static,
@ -56,6 +56,7 @@ impl<T> WrapErr<T, Infallible> for Option<T> {
} }
} }
#[cfg_attr(track_caller, track_caller)]
fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report> fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report>
where where
D: Display + Send + Sync + 'static, D: Display + Send + Sync + 'static,
@ -67,6 +68,7 @@ impl<T> WrapErr<T, Infallible> for Option<T> {
} }
} }
#[cfg_attr(track_caller, track_caller)]
fn context<D>(self, msg: D) -> Result<T, Report> fn context<D>(self, msg: D) -> Result<T, Report>
where where
D: Display + Send + Sync + 'static, D: Display + Send + Sync + 'static,
@ -74,6 +76,7 @@ impl<T> WrapErr<T, Infallible> for Option<T> {
self.wrap_err(msg) self.wrap_err(msg)
} }
#[cfg_attr(track_caller, track_caller)]
fn with_context<D, F>(self, msg: F) -> Result<T, Report> fn with_context<D, F>(self, msg: F) -> Result<T, Report>
where where
D: Display + Send + Sync + 'static, D: Display + Send + Sync + 'static,
@ -87,6 +90,7 @@ impl<T, E> WrapErr<T, E> for Result<T, E>
where where
E: ext::Diag + Send + Sync + 'static, E: ext::Diag + Send + Sync + 'static,
{ {
#[cfg_attr(track_caller, track_caller)]
fn wrap_err<D>(self, msg: D) -> Result<T, Report> fn wrap_err<D>(self, msg: D) -> Result<T, Report>
where where
D: Display + Send + Sync + 'static, D: Display + Send + Sync + 'static,
@ -97,6 +101,7 @@ where
} }
} }
#[cfg_attr(track_caller, track_caller)]
fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report> fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report>
where where
D: Display + Send + Sync + 'static, D: Display + Send + Sync + 'static,
@ -108,6 +113,7 @@ where
} }
} }
#[cfg_attr(track_caller, track_caller)]
fn context<D>(self, msg: D) -> Result<T, Report> fn context<D>(self, msg: D) -> Result<T, Report>
where where
D: Display + Send + Sync + 'static, D: Display + Send + Sync + 'static,
@ -115,6 +121,7 @@ where
self.wrap_err(msg) self.wrap_err(msg)
} }
#[cfg_attr(track_caller, track_caller)]
fn with_context<D, F>(self, msg: F) -> Result<T, Report> fn with_context<D, F>(self, msg: F) -> Result<T, Report>
where where
D: Display + Send + Sync + 'static, D: Display + Send + Sync + 'static,

View File

@ -1,14 +1,11 @@
extern crate alloc; extern crate alloc;
use crate::StdError;
use alloc::boxed::Box;
use core::any::TypeId; use core::any::TypeId;
use core::fmt::{self, Debug, Display}; use core::fmt::{self, Debug, Display};
use core::mem::ManuallyDrop; use core::mem::ManuallyDrop;
use core::ptr::{self, NonNull}; use core::ptr::{self, NonNull};
#[cfg(feature = "std")]
use std::error::Error as StdError;
#[cfg(not(feature = "std"))]
use crate::StdError as StdError;
use alloc::boxed::Box;
use super::ptr::{Mut, Own, Ref}; use super::ptr::{Mut, Own, Ref};
use super::Report; use super::Report;
@ -93,7 +90,6 @@ impl Report {
Report::from_boxed(error) Report::from_boxed(error)
} }
#[cfg_attr(track_caller, track_caller)]
#[cold] #[cold]
pub(crate) fn from_std<E>(error: E) -> Self pub(crate) fn from_std<E>(error: E) -> Self
where where
@ -160,7 +156,7 @@ impl Report {
}; };
// Safety: passing vtable that operates on the right type. // Safety: passing vtable that operates on the right type.
let handler = Some(super::capture_handler(&error)); let handler = Some(super::capture_handler_with_location(&error));
unsafe { Report::construct(error, vtable, handler) } unsafe { Report::construct(error, vtable, handler) }
} }
@ -445,7 +441,6 @@ impl<E> From<E> for Report
where where
E: Diagnostic + Send + Sync + 'static, E: Diagnostic + Send + Sync + 'static,
{ {
#[cfg_attr(track_caller, track_caller)]
#[cold] #[cold]
fn from(error: E) -> Self { fn from(error: E) -> Self {
Report::from_std(error) Report::from_std(error)

View File

@ -1,10 +1,6 @@
extern crate alloc; extern crate alloc;
#[cfg(feature = "std")]
use std::error::Error;
#[cfg(not(feature = "std"))]
use crate::StdError as Error; use crate::StdError as Error;
use core::fmt::Display;
use alloc::boxed::Box; use alloc::boxed::Box;
use crate::{Diagnostic, Report}; use crate::{Diagnostic, Report};
@ -42,11 +38,13 @@ inaccessible. If you have a type implementing [`Diagnostic`] consider simply ret
pub trait IntoDiagnostic<T, E> { pub trait IntoDiagnostic<T, E> {
/// Converts [`Result`] types that return regular [`std::error::Error`]s /// Converts [`Result`] types that return regular [`std::error::Error`]s
/// into a [`Result`] that returns a [`Diagnostic`]. /// into a [`Result`] that returns a [`Diagnostic`].
#[cfg_attr(track_caller, track_caller)]
fn into_diagnostic(self) -> Result<T, Report>; fn into_diagnostic(self) -> Result<T, Report>;
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<T, E: std::error::Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E> { impl<T, E: std::error::Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E> {
#[cfg_attr(track_caller, track_caller)]
fn into_diagnostic(self) -> Result<T, Report> { fn into_diagnostic(self) -> Result<T, Report> {
self.map_err(|e| DiagnosticError(Box::new(e)).into()) self.map_err(|e| DiagnosticError(Box::new(e)).into())
} }
@ -54,6 +52,7 @@ impl<T, E: std::error::Error + Send + Sync + 'static> IntoDiagnostic<T, E> for R
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
impl<T, E: Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E> { impl<T, E: Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E> {
#[cfg_attr(track_caller, track_caller)]
fn into_diagnostic(self) -> Result<T, Report> { fn into_diagnostic(self) -> Result<T, Report> {
self.map_err(|e| DiagnosticError(Box::new(e)).into()) self.map_err(|e| DiagnosticError(Box::new(e)).into())
} }
@ -62,7 +61,9 @@ impl<T, E: Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E>
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::io::{self, ErrorKind}; use std::io::{self};
#[cfg(feature = "std")]
use std::string::ToString;
use super::*; use super::*;
@ -72,7 +73,7 @@ mod tests {
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[test] #[test]
fn diagnostic_error() { fn diagnostic_error() {
let inner_error = io::Error::new(ErrorKind::Other, "halt and catch fire"); let inner_error = io::Error::other("halt and catch fire");
let outer_error: Result<(), _> = Err(TestError(inner_error)); let outer_error: Result<(), _> = Err(TestError(inner_error));
let diagnostic_error = outer_error.into_diagnostic().unwrap_err(); let diagnostic_error = outer_error.into_diagnostic().unwrap_err();

View File

@ -56,6 +56,9 @@ use crate::Diagnostic;
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
use alloc::boxed::Box; use alloc::boxed::Box;
#[cfg(feature = "std")]
use std::boxed::Box;
pub struct Adhoc; pub struct Adhoc;
pub trait AdhocKind: Sized { pub trait AdhocKind: Sized {

View File

@ -6,14 +6,14 @@
)] )]
extern crate alloc; extern crate alloc;
use core::fmt::Display;
use alloc::boxed::Box; use alloc::boxed::Box;
use core::fmt::Display;
#[cfg(not(feature = "std"))]
use crate::StdError;
use spin::Once;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::error::Error as StdError; use std::error::Error as StdError;
#[cfg(not(feature = "std"))]
use crate::StdError as StdError;
use spin::Once;
#[allow(unreachable_pub)] #[allow(unreachable_pub)]
pub use into_diagnostic::*; pub use into_diagnostic::*;
@ -95,9 +95,20 @@ pub fn set_hook(hook: ErrorHook) -> Result<(), InstallError> {
Ok(()) Ok(())
} }
pub(crate) fn capture_handler(error: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> {
static DEFAULT: Once<ErrorHook> = Once::new();
let hook = HOOK.get().unwrap_or_else(|| {
DEFAULT.call_once(|| default_hook());
DEFAULT.get().unwrap()
});
hook(error)
}
#[cfg_attr(track_caller, track_caller)] #[cfg_attr(track_caller, track_caller)]
#[cfg_attr(not(track_caller), allow(unused_mut))] pub(crate) fn capture_handler_with_location(
fn capture_handler(error: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> { error: &(dyn Diagnostic + 'static),
) -> Box<dyn ReportHandler> {
static DEFAULT: Once<ErrorHook> = Once::new(); static DEFAULT: Once<ErrorHook> = Once::new();
let hook = HOOK.get().unwrap_or_else(|| { let hook = HOOK.get().unwrap_or_else(|| {
DEFAULT.call_once(|| default_hook()); DEFAULT.call_once(|| default_hook());

View File

@ -1,8 +1,8 @@
extern crate alloc; extern crate alloc;
use alloc::boxed::Box;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::ptr::NonNull; use core::ptr::NonNull;
use alloc::boxed::Box;
#[repr(transparent)] #[repr(transparent)]
/// A raw pointer that owns its pointee /// A raw pointer that owns its pointee

View File

@ -2,13 +2,8 @@ extern crate alloc;
use core::fmt::{self, Debug, Display}; use core::fmt::{self, Debug, Display};
#[cfg(feature = "std")] use crate::StdError;
use std::error::Error as StdError;
#[cfg(not(feature = "std"))]
use crate::StdError as StdError;
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use crate::{Diagnostic, LabeledSpan, Report, SourceCode}; use crate::{Diagnostic, LabeledSpan, Report, SourceCode};
@ -216,6 +211,11 @@ impl<C> StdError for WithSourceCode<Report, C> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::{
boxed::Box,
string::{String, ToString},
};
use thiserror::Error; use thiserror::Error;
use crate::{Diagnostic, LabeledSpan, Report, SourceCode, SourceSpan}; use crate::{Diagnostic, LabeledSpan, Report, SourceCode, SourceSpan};

View File

@ -1,3 +1,7 @@
extern crate alloc;
use alloc::boxed::Box;
use alloc::string::String;
use crate::highlighters::Highlighter; use crate::highlighters::Highlighter;
use crate::highlighters::MietteHighlighter; use crate::highlighters::MietteHighlighter;
use crate::protocol::Diagnostic; use crate::protocol::Diagnostic;
@ -491,7 +495,10 @@ mod syscall {
#[inline] #[inline]
pub(super) fn supports_color() -> bool { pub(super) fn supports_color() -> bool {
cfg_if! { cfg_if! {
if #[cfg(feature = "fancy-no-syscall")] { if #[cfg(feature = "fancy-no-backtrace")] {
supports_color::on(supports_color::Stream::Stderr).is_some()
} else if #[cfg(feature = "fancy-no-syscall")] {
// In no-std environment without color support, default to no color support
false false
} else { } else {
supports_color::on(supports_color::Stream::Stderr).is_some() supports_color::on(supports_color::Stream::Stderr).is_some()
@ -502,8 +509,11 @@ mod syscall {
#[inline] #[inline]
pub(super) fn supports_color_has_16m() -> Option<bool> { pub(super) fn supports_color_has_16m() -> Option<bool> {
cfg_if! { cfg_if! {
if #[cfg(feature = "fancy-no-syscall")] { if #[cfg(feature = "fancy-no-backtrace")] {
None supports_color::on(supports_color::Stream::Stderr).map(|color| color.has_16m)
} else if #[cfg(feature = "fancy-no-syscall")] {
// In no-std environment without color support, default to no RGB color support
Some(false)
} else { } else {
supports_color::on(supports_color::Stream::Stderr).map(|color| color.has_16m) supports_color::on(supports_color::Stream::Stderr).map(|color| color.has_16m)
} }

View File

@ -1,7 +1,7 @@
extern crate alloc; extern crate alloc;
use core::fmt;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::fmt;
use crate::{protocol::Diagnostic, ReportHandler}; use crate::{protocol::Diagnostic, ReportHandler};

View File

@ -1,4 +1,10 @@
use std::fmt::{self, Write}; extern crate alloc;
use alloc::boxed::Box;
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::fmt::{self, Write};
use owo_colors::{OwoColorize, Style, StyledList}; use owo_colors::{OwoColorize, Style, StyledList};
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr}; use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};

View File

@ -1,7 +1,7 @@
extern crate alloc; extern crate alloc;
use core::fmt::{self, Write};
use alloc::string::ToString; use alloc::string::ToString;
use core::fmt::{self, Write};
use crate::{ use crate::{
diagnostic_chain::DiagnosticChain, protocol::Diagnostic, ReportHandler, Severity, SourceCode, diagnostic_chain::DiagnosticChain, protocol::Diagnostic, ReportHandler, Severity, SourceCode,

View File

@ -7,9 +7,9 @@ use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
use crate::diagnostic_chain::DiagnosticChain; use crate::diagnostic_chain::DiagnosticChain;
use crate::protocol::{Diagnostic, Severity}; use crate::protocol::{Diagnostic, Severity};
use crate::{LabeledSpan, MietteError, ReportHandler, SourceCode, SourceSpan, SpanContents}; use crate::{LabeledSpan, MietteError, ReportHandler, SourceCode, SourceSpan, SpanContents};
use alloc::boxed::Box;
use alloc::string::String; use alloc::string::String;
use alloc::vec::Vec; use alloc::vec::Vec;
use alloc::boxed::Box;
/** /**
[`ReportHandler`] that renders plain text and avoids extraneous graphics. [`ReportHandler`] that renders plain text and avoids extraneous graphics.

View File

@ -1,5 +1,7 @@
use std::io::IsTerminal; extern crate alloc;
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
use owo_colors::Style; use owo_colors::Style;
/** /**

View File

@ -1,3 +1,8 @@
extern crate alloc;
use alloc::boxed::Box;
use alloc::vec;
use alloc::vec::Vec;
use owo_colors::Style; use owo_colors::Style;
use crate::SpanContents; use crate::SpanContents;

View File

@ -13,6 +13,11 @@
use std::{ops::Deref, sync::Arc}; use std::{ops::Deref, sync::Arc};
extern crate alloc;
use alloc::boxed::Box;
use alloc::sync::Arc;
use alloc::vec::Vec;
use crate::SpanContents; use crate::SpanContents;
use owo_colors::Styled; use owo_colors::Styled;

View File

@ -1,5 +1,10 @@
use std::path::Path; use std::path::Path;
extern crate alloc;
use alloc::boxed::Box;
use alloc::vec;
use alloc::vec::Vec;
// all syntect imports are explicitly qualified, but their paths are shortened for convenience // all syntect imports are explicitly qualified, but their paths are shortened for convenience
#[allow(clippy::module_inception)] #[allow(clippy::module_inception)]
mod syntect { mod syntect {

View File

@ -1,8 +1,8 @@
#![no_std] #![no_std]
#![deny(missing_docs, missing_debug_implementations, nonstandard_style)] #![deny(missing_docs, missing_debug_implementations, nonstandard_style)]
#![warn(unreachable_pub, rust_2018_idioms)] #![warn(unreachable_pub, rust_2018_idioms)]
#![allow(unexpected_cfgs)] #![allow(unexpected_cfgs)]
//! You run miette? You run her code like the software? Oh. Oh! Error code for //! You run miette? You run her code like the software? Oh. Oh! Error code for
//! coder! Error code for One Thousand Lines! //! coder! Error code for One Thousand Lines!
//! //!
@ -98,6 +98,7 @@
//! ## Example //! ## Example
//! //!
//! ```rust //! ```rust
//! # extern crate alloc;
//! /* //! /*
//! You can derive a `Diagnostic` from any `std::error::Error` type. //! You can derive a `Diagnostic` from any `std::error::Error` type.
//! //!
@ -195,6 +196,7 @@
//! the trait directly, just like with `std::error::Error`. //! the trait directly, just like with `std::error::Error`.
//! //!
//! ```rust //! ```rust
//! # extern crate alloc;
//! // lib/error.rs //! // lib/error.rs
//! use miette::{Diagnostic, SourceSpan}; //! use miette::{Diagnostic, SourceSpan};
//! use thiserror::Error; //! use thiserror::Error;
@ -362,6 +364,7 @@
//! attribute: //! attribute:
//! //!
//! ```rust //! ```rust
//! # extern crate alloc;
//! use miette::Diagnostic; //! use miette::Diagnostic;
//! use thiserror::Error; //! use thiserror::Error;
//! //!
@ -382,6 +385,7 @@
//! (very high quality and detailed!) documentation on this diagnostic: //! (very high quality and detailed!) documentation on this diagnostic:
//! //!
//! ```rust //! ```rust
//! # extern crate alloc;
//! use miette::Diagnostic; //! use miette::Diagnostic;
//! use thiserror::Error; //! use thiserror::Error;
//! //!
@ -412,6 +416,7 @@
//! `derive(Diagnostic)` macro: //! `derive(Diagnostic)` macro:
//! //!
//! ```rust //! ```rust
//! # extern crate alloc;
//! use miette::{Diagnostic, SourceSpan}; //! use miette::{Diagnostic, SourceSpan};
//! use thiserror::Error; //! use thiserror::Error;
//! //!
@ -450,6 +455,7 @@
//! enum variants: //! enum variants:
//! //!
//! ```rust //! ```rust
//! # extern crate alloc;
//! use miette::Diagnostic; //! use miette::Diagnostic;
//! use thiserror::Error; //! use thiserror::Error;
//! //!
@ -463,6 +469,7 @@
//! your diagnostic: //! your diagnostic:
//! //!
//! ```rust //! ```rust
//! # extern crate alloc;
//! use miette::Diagnostic; //! use miette::Diagnostic;
//! use thiserror::Error; //! use thiserror::Error;
//! //!
@ -501,6 +508,7 @@
//! `Diagnostic` type: //! `Diagnostic` type:
//! //!
//! ```rust //! ```rust
//! # extern crate alloc;
//! use miette::Diagnostic; //! use miette::Diagnostic;
//! use thiserror::Error; //! use thiserror::Error;
//! //!
@ -519,6 +527,7 @@
//! method for that: //! method for that:
//! //!
//! ```rust,no_run //! ```rust,no_run
//! # extern crate alloc;
//! use miette::{Diagnostic, SourceSpan}; //! use miette::{Diagnostic, SourceSpan};
//! use thiserror::Error; //! use thiserror::Error;
//! //!
@ -551,6 +560,7 @@
//! emitted at the same time: //! emitted at the same time:
//! //!
//! ```rust,no_run //! ```rust,no_run
//! # extern crate alloc;
//! use miette::{Diagnostic, Report, SourceSpan}; //! use miette::{Diagnostic, Report, SourceSpan};
//! use thiserror::Error; //! use thiserror::Error;
//! //!
@ -612,6 +622,7 @@
//! will likely want to use _both_: //! will likely want to use _both_:
//! //!
//! ```rust //! ```rust
//! # extern crate alloc;
//! use miette::Diagnostic; //! use miette::Diagnostic;
//! use thiserror::Error; //! use thiserror::Error;
//! //!
@ -817,6 +828,11 @@
//! and some from [`thiserror`](https://github.com/dtolnay/thiserror), also //! and some from [`thiserror`](https://github.com/dtolnay/thiserror), also
//! under the Apache License. Some code is taken from //! under the Apache License. Some code is taken from
//! [`ariadne`](https://github.com/zesterer/ariadne), which is MIT licensed. //! [`ariadne`](https://github.com/zesterer/ariadne), which is MIT licensed.
// For doctests that use Diagnostic derive macro
#[cfg(test)]
extern crate alloc;
#[cfg(feature = "std")] #[cfg(feature = "std")]
extern crate std; extern crate std;

View File

@ -51,7 +51,6 @@ impl ToLabeledSpan<LabeledSpan> for ToLabelSpanWrapper {
span span
} }
} }
#[cfg(not(feature = "std"))]
impl<T> ToLabeledSpan<T> for ToLabelSpanWrapper impl<T> ToLabeledSpan<T> for ToLabelSpanWrapper
where where
T: Into<SourceSpan>, T: Into<SourceSpan>,

View File

@ -1,14 +1,13 @@
extern crate alloc; extern crate alloc;
#[cfg(not(feature = "std"))]
use crate::StdError as Error;
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::fmt::{Debug, Display}; use core::fmt::{Debug, Display};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::error::Error; use std::error::Error;
#[cfg(not(feature = "std"))]
use crate::StdError as Error;
use alloc::string::String;
use alloc::vec::{self, Vec};
use alloc::format;
use alloc::boxed::Box;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View File

@ -12,9 +12,9 @@ pub struct NamedSource<S: SourceCode + 'static> {
extern crate alloc; extern crate alloc;
use alloc::boxed::Box;
use alloc::string::String; use alloc::string::String;
use alloc::string::ToString; use alloc::string::ToString;
use alloc::boxed::Box;
impl<S: SourceCode> core::fmt::Debug for NamedSource<S> { impl<S: SourceCode> core::fmt::Debug for NamedSource<S> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {

View File

@ -1,4 +1,11 @@
use std::{error::Error, fmt::Display}; use std::boxed::Box;
use std::{
eprintln,
error::Error,
fmt::Display,
format,
string::{String, ToString},
};
use backtrace::Backtrace; use backtrace::Backtrace;
@ -104,7 +111,7 @@ impl Panic {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::error::Error; use std::{borrow::ToOwned, error::Error};
use super::*; use super::*;

View File

@ -5,13 +5,13 @@ full reporting and such features.
*/ */
extern crate alloc; extern crate alloc;
use core::fmt::{self, Display};
#[cfg(feature = "std")]
use std::fs;
use core::panic::Location;
use core::ops;
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::string::String; use alloc::string::String;
use core::fmt::{self, Display};
use core::ops;
use core::panic::Location;
#[cfg(feature = "std")]
use std::fs;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -152,9 +152,6 @@ impl From<String> for Box<dyn Diagnostic + Send + Sync> {
fn from(s: String) -> Self { fn from(s: String) -> Self {
struct StringError(String); struct StringError(String);
#[cfg(feature = "std")]
impl std::error::Error for StringError {}
#[cfg(not(feature = "std"))]
impl crate::StdError for StringError {} impl crate::StdError for StringError {}
impl Diagnostic for StringError {} impl Diagnostic for StringError {}

View File

@ -3,14 +3,14 @@ Default trait implementations for [`SourceCode`].
*/ */
extern crate alloc; extern crate alloc;
use core::fmt::Debug;
use alloc::borrow::Cow; use alloc::borrow::Cow;
use alloc::borrow::ToOwned; use alloc::borrow::ToOwned;
use alloc::collections::VecDeque;
use alloc::sync::Arc;
use alloc::string::String;
use alloc::vec::Vec;
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::collections::VecDeque;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::fmt::Debug;
use crate::{MietteError, MietteSpanContents, SourceCode, SourceSpan, SpanContents}; use crate::{MietteError, MietteSpanContents, SourceCode, SourceSpan, SpanContents};

View File

@ -1,5 +1,7 @@
#![cfg(feature = "fancy-no-backtrace")] #![cfg(feature = "fancy-no-backtrace")]
extern crate alloc;
use miette::{Diagnostic, MietteHandler, MietteHandlerOpts, ReportHandler, RgbColors}; use miette::{Diagnostic, MietteHandler, MietteHandlerOpts, ReportHandler, RgbColors};
use regex::Regex; use regex::Regex;
use std::ffi::OsString; use std::ffi::OsString;
@ -83,7 +85,9 @@ fn check_colors<F: Fn(MietteHandlerOpts) -> MietteHandlerOpts>(
// //
// Since environment variables are shared for the entire process, we need // Since environment variables are shared for the entire process, we need
// to ensure that only one test that modifies these env vars runs at a time. // to ensure that only one test that modifies these env vars runs at a time.
let lock = COLOR_ENV_VARS.lock().unwrap(); let lock = COLOR_ENV_VARS
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner());
let guards = ( let guards = (
EnvVarGuard::new("NO_COLOR"), EnvVarGuard::new("NO_COLOR"),

View File

@ -10,5 +10,5 @@ pub fn bail_fmt() -> Result<()> {
} }
pub fn bail_error() -> Result<()> { pub fn bail_error() -> Result<()> {
bail!(io::Error::new(io::ErrorKind::Other, "oh no!")); bail!(io::Error::other("oh no!"));
} }

View File

@ -1,3 +1,5 @@
extern crate alloc;
use miette::{Diagnostic, Report, Severity, SourceSpan}; use miette::{Diagnostic, Report, Severity, SourceSpan};
use thiserror::Error; use thiserror::Error;

View File

@ -1,5 +1,7 @@
#![cfg(feature = "fancy-no-backtrace")] #![cfg(feature = "fancy-no-backtrace")]
extern crate alloc;
use miette::{ use miette::{
Diagnostic, GraphicalReportHandler, GraphicalTheme, MietteError, NamedSource, Diagnostic, GraphicalReportHandler, GraphicalTheme, MietteError, NamedSource,
NarratableReportHandler, Report, SourceSpan, NarratableReportHandler, Report, SourceSpan,

View File

@ -1,5 +1,7 @@
#![cfg(feature = "fancy-no-backtrace")] #![cfg(feature = "fancy-no-backtrace")]
extern crate alloc;
use miette::{Diagnostic, MietteError, NamedSource, NarratableReportHandler, Report, SourceSpan}; use miette::{Diagnostic, MietteError, NamedSource, NarratableReportHandler, Report, SourceSpan};
use miette::{GraphicalReportHandler, GraphicalTheme}; use miette::{GraphicalReportHandler, GraphicalTheme};

View File

@ -42,13 +42,13 @@ fn test_boxed_str_stderr() {
#[test] #[test]
fn test_boxed_thiserror() { fn test_boxed_thiserror() {
let error = MyError { let error = MyError {
source: io::Error::new(io::ErrorKind::Other, "oh no!"), source: io::Error::other("oh no!"),
}; };
let report: Report = miette!(error); let report: Report = miette!(error);
assert_eq!("oh no!", report.source().unwrap().to_string()); assert_eq!("oh no!", report.source().unwrap().to_string());
let error = MyError { let error = MyError {
source: io::Error::new(io::ErrorKind::Other, "oh no!!!!"), source: io::Error::other("oh no!!!!"),
}; };
let error: Box<dyn Diagnostic + Send + Sync + 'static> = Box::new(error); let error: Box<dyn Diagnostic + Send + Sync + 'static> = Box::new(error);
let report = Report::new_boxed(error); let report = Report::new_boxed(error);
@ -203,7 +203,7 @@ fn test_boxed_custom_diagnostic() {
let related = CustomDiagnostic::new(); let related = CustomDiagnostic::new();
let main_diagnostic = CustomDiagnostic::new() let main_diagnostic = CustomDiagnostic::new()
.with_source(io::Error::new(io::ErrorKind::Other, "oh no!")) .with_source(io::Error::other("oh no!"))
.with_related(related); .with_related(related);
let report = Report::new_boxed(Box::new(main_diagnostic)); let report = Report::new_boxed(Box::new(main_diagnostic));
@ -211,7 +211,7 @@ fn test_boxed_custom_diagnostic() {
let related = CustomDiagnostic::new(); let related = CustomDiagnostic::new();
let main_diagnostic = CustomDiagnostic::new() let main_diagnostic = CustomDiagnostic::new()
.with_source(io::Error::new(io::ErrorKind::Other, "oh no!")) .with_source(io::Error::other("oh no!"))
.with_related(related); .with_related(related);
let main_diagnostic = Box::new(main_diagnostic) as Box<dyn Diagnostic + Send + Sync + 'static>; let main_diagnostic = Box::new(main_diagnostic) as Box<dyn Diagnostic + Send + Sync + 'static>;
let report = miette!(main_diagnostic); let report = miette!(main_diagnostic);
@ -228,7 +228,7 @@ fn test_boxed_custom_diagnostic() {
#[test] #[test]
fn test_boxed_sources() { fn test_boxed_sources() {
let error = MyError { let error = MyError {
source: io::Error::new(io::ErrorKind::Other, "oh no!"), source: io::Error::other("oh no!"),
}; };
let error = Box::<dyn Diagnostic + Send + Sync>::from(error); let error = Box::<dyn Diagnostic + Send + Sync>::from(error);
let error: Report = miette!(error).wrap_err("it failed"); let error: Report = miette!(error).wrap_err("it failed");

View File

@ -1,4 +1,6 @@
// Testing of the `diagnostic` attr used by derive(Diagnostic) // Testing of the `diagnostic` attr used by derive(Diagnostic)
extern crate alloc;
use miette::{Diagnostic, LabeledSpan, NamedSource, SourceSpan}; use miette::{Diagnostic, LabeledSpan, NamedSource, SourceSpan};
use thiserror::Error; use thiserror::Error;

View File

@ -1,3 +1,5 @@
extern crate alloc;
use std::{ use std::{
collections::{LinkedList, VecDeque}, collections::{LinkedList, VecDeque},
ops::Range, ops::Range,

View File

@ -1,3 +1,5 @@
extern crate alloc;
use miette::Diagnostic; use miette::Diagnostic;
#[derive(Debug, miette::Diagnostic, thiserror::Error)] #[derive(Debug, miette::Diagnostic, thiserror::Error)]

View File

@ -1,4 +1,6 @@
mod json_report_handler { mod json_report_handler {
extern crate alloc;
use miette::{Diagnostic, MietteError, NamedSource, Report, SourceSpan}; use miette::{Diagnostic, MietteError, NamedSource, Report, SourceSpan};
use miette::JSONReportHandler; use miette::JSONReportHandler;

View File

@ -50,7 +50,7 @@ fn test_fmt_source() {
#[test] #[test]
#[ignore = "Again with the io::Error source issue?"] #[ignore = "Again with the io::Error source issue?"]
fn test_io_source() { fn test_io_source() {
let io = io::Error::new(io::ErrorKind::Other, "oh no!"); let io = io::Error::other("oh no!");
let error: Report = miette!(TestError::Io(io)); let error: Report = miette!(TestError::Io(io));
assert_eq!("oh no!", error.source().unwrap().to_string()); assert_eq!("oh no!", error.source().unwrap().to_string());
} }