fix: address review feedback for no_std support

- Use core::error::Error directly (MSRV 1.82 supports it)
- Remove build.rs (track_caller is always available with MSRV 1.82)
- Simplify feature detection in handler.rs syscall module
- Add clippy lints to catch std/core/alloc misuse
- Remove custom StdError trait, re-export core::error::Error
- Add __alloc module for derive macro compatibility
- Clean up verbose comments
- Remove extern crate alloc from tests (not needed with std)
- Fix derive macros to use miette::__alloc paths
This commit is contained in:
François Garillot 2026-01-14 15:38:54 -05:00
parent 09e1090b2e
commit c07cab4b60
No known key found for this signature in database
GPG Key ID: E7645C6B883A1E9A
31 changed files with 158 additions and 225 deletions

View File

@ -13,11 +13,11 @@ rust-version = "1.82.0"
exclude = ["images/", "tests/", "miette-derive/"]
[dependencies]
thiserror = "2.0.11"
miette-derive = { path = "miette-derive", version = "=7.6.0", optional = true }
unicode-width = { version = "0.2.0", default-features = false }
cfg-if = "1.0.0"
spin = { version = "0.9", default-features = false, features = ["mutex", "spin_mutex", "lazy"] }
# spin is needed for no_std environments (provides Once without std)
spin = { version = "0.9", default-features = false, features = ["once"] }
owo-colors = { version = "4.0.0", optional = true }
textwrap = { version = "0.16.0", default-features = false, features = ["unicode-linebreak", "unicode-width"], optional = true }
@ -31,6 +31,7 @@ serde = { version = "1.0.196", features = ["derive"], optional = true }
syntect = { version = "5.1.0", optional = true }
[dev-dependencies]
thiserror = "2.0.11"
semver = "1.0.21"
futures = { version = "0.3", default-features = false }
indenter = "0.3.3"
@ -45,7 +46,7 @@ strip-ansi-escapes = "0.2.0"
[features]
default = ["derive", "std"]
std = ["thiserror/std", "fancy-no-syscall"]
std = []
derive = ["dep:miette-derive"]
no-format-args-capture = []
fancy-base = [
@ -57,13 +58,14 @@ fancy-no-syscall = [
]
fancy-no-backtrace = [
"fancy-base",
"std",
"dep:terminal_size",
"dep:supports-hyperlinks",
"dep:supports-color",
"dep:supports-unicode",
]
fancy = ["fancy-no-backtrace", "dep:backtrace", "dep:backtrace-ext"]
syntect-highlighter = ["fancy-no-backtrace", "dep:syntect", "std"]
syntect-highlighter = ["fancy-no-backtrace", "dep:syntect"]
[workspace]
members = ["miette-derive"]

View File

@ -1,6 +0,0 @@
fn main() {
// track_caller is always available with our MSRV (Rust ≥ 1.82)
// Add check-cfg for conditional configurations
println!("cargo:rustc-check-cfg=cfg(doc_cfg)");
}

View File

@ -56,13 +56,13 @@ impl Code {
let code = &code.as_ref()?.0;
Some(match fields {
syn::Fields::Named(_) => {
quote! { Self::#ident { .. } => core::option::Option::Some(alloc::boxed::Box::new(#code)), }
quote! { Self::#ident { .. } => core::option::Option::Some(miette::__alloc::Box::new(#code)), }
}
syn::Fields::Unnamed(_) => {
quote! { Self::#ident(..) => core::option::Option::Some(alloc::boxed::Box::new(#code)), }
quote! { Self::#ident(..) => core::option::Option::Some(miette::__alloc::Box::new(#code)), }
}
syn::Fields::Unit => {
quote! { Self::#ident => core::option::Option::Some(alloc::boxed::Box::new(#code)), }
quote! { Self::#ident => core::option::Option::Some(miette::__alloc::Box::new(#code)), }
}
})
},
@ -72,8 +72,8 @@ impl Code {
pub(crate) fn gen_struct(&self) -> Option<TokenStream> {
let code = &self.0;
Some(quote! {
fn code(&self) -> core::option::Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
core::option::Option::Some(alloc::boxed::Box::new(#code))
fn code(&self) -> core::option::Option<miette::__alloc::Box<dyn core::fmt::Display + '_>> {
core::option::Option::Some(miette::__alloc::Box::new(#code))
}
})
}

View File

@ -59,7 +59,7 @@ impl DiagnosticSource {
};
quote! {
Self::#ident #display_pat => {
core::option::Option::Some(alloc::borrow::Borrow::borrow(#rel))
core::option::Option::Some(miette::__alloc::borrow::Borrow::borrow(#rel))
}
}
})
@ -71,7 +71,7 @@ impl DiagnosticSource {
let rel = &self.0;
Some(quote! {
fn diagnostic_source<'a>(&'a self) -> core::option::Option<&'a dyn miette::Diagnostic> {
core::option::Option::Some(alloc::borrow::Borrow::borrow(&self.#rel))
core::option::Option::Some(miette::__alloc::borrow::Borrow::borrow(&self.#rel))
}
})
}

View File

@ -58,22 +58,22 @@ impl WhichFn {
pub fn signature(&self) -> TokenStream {
match self {
Self::Code => quote! {
fn code(& self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>>
fn code(& self) -> Option<miette::__alloc::Box<dyn core::fmt::Display + '_>>
},
Self::Help => quote! {
fn help(& self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>>
fn help(& self) -> Option<miette::__alloc::Box<dyn core::fmt::Display + '_>>
},
Self::Url => quote! {
fn url(& self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>>
fn url(& self) -> Option<miette::__alloc::Box<dyn core::fmt::Display + '_>>
},
Self::Severity => quote! {
fn severity(&self) -> Option<miette::Severity>
},
Self::Related => quote! {
fn related(&self) -> Option<alloc::boxed::Box<dyn Iterator<Item = &dyn miette::Diagnostic> + '_>>
fn related(&self) -> Option<miette::__alloc::Box<dyn Iterator<Item = &dyn miette::Diagnostic> + '_>>
},
Self::Labels => quote! {
fn labels(&self) -> Option<alloc::boxed::Box<dyn Iterator<Item = miette::LabeledSpan> + '_>>
fn labels(&self) -> Option<miette::__alloc::Box<dyn Iterator<Item = miette::LabeledSpan> + '_>>
},
Self::SourceCode => quote! {
fn source_code(&self) -> Option<&dyn miette::SourceCode>

View File

@ -94,7 +94,7 @@ impl Help {
Help::Display(display) => {
let (fmt, args) = display.expand_shorthand_cloned(&display_members);
Some(quote! {
Self::#ident #display_pat => Option::Some(alloc::boxed::Box::new(format!(#fmt #args))),
Self::#ident #display_pat => Option::Some(miette::__alloc::Box::new(format!(#fmt #args))),
})
}
Help::Field(member, ty) => {
@ -108,7 +108,7 @@ impl Help {
Some(quote! {
Self::#ident #display_pat => {
use miette::macro_helpers::ToOption;
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&#help).as_ref().map(|#var| -> alloc::boxed::Box<dyn core::fmt::Display + '_> { alloc::boxed::Box::new(format!("{}", #var)) })
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&#help).as_ref().map(|#var| -> miette::__alloc::Box<dyn core::fmt::Display + '_> { miette::__alloc::Box::new(format!("{}", #var)) })
},
})
}
@ -123,21 +123,21 @@ impl Help {
Help::Display(display) => {
let (fmt, args) = display.expand_shorthand_cloned(&display_members);
Some(quote! {
fn help(&self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
fn help(&self) -> Option<miette::__alloc::Box<dyn core::fmt::Display + '_>> {
#[allow(unused_variables, deprecated)]
let Self #display_pat = self;
Option::Some(alloc::boxed::Box::new(format!(#fmt #args)))
Option::Some(miette::__alloc::Box::new(format!(#fmt #args)))
}
})
}
Help::Field(member, ty) => {
let var = quote! { __miette_internal_var };
Some(quote! {
fn help(&self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
fn help(&self) -> Option<miette::__alloc::Box<dyn core::fmt::Display + '_>> {
#[allow(unused_variables, deprecated)]
let Self #display_pat = self;
use miette::macro_helpers::ToOption;
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&self.#member).as_ref().map(|#var| -> alloc::boxed::Box<dyn core::fmt::Display + '_> { alloc::boxed::Box::new(format!("{}", #var)) })
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&self.#member).as_ref().map(|#var| -> miette::__alloc::Box<dyn core::fmt::Display + '_> { miette::__alloc::Box::new(format!("{}", #var)) })
}
})
}

View File

@ -226,7 +226,7 @@ impl Labels {
Some(quote! {
#[allow(unused_variables)]
fn labels(&self) -> Option<alloc::boxed::Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
fn labels(&self) -> Option<miette::__alloc::Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
use miette::macro_helpers::ToOption;
let Self #display_pat = self;
@ -236,7 +236,7 @@ impl Labels {
.into_iter()
#(#collections_chain)*;
Option::Some(alloc::boxed::Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
Option::Some(miette::__alloc::Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
}
})
}
@ -322,7 +322,7 @@ impl Labels {
]
.into_iter()
#(#collections_chain)*;
Option::Some(alloc::boxed::Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
Option::Some(miette::__alloc::Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
}
}),
}

View File

@ -55,7 +55,7 @@ impl Related {
};
quote! {
Self::#ident #display_pat => {
Option::Some(alloc::boxed::Box::new(
Option::Some(miette::__alloc::Box::new(
#rel.iter().map(|x| -> &(dyn miette::Diagnostic) { &*x })
))
}
@ -68,9 +68,9 @@ impl Related {
pub(crate) fn gen_struct(&self) -> Option<TokenStream> {
let rel = &self.0;
Some(quote! {
fn related<'a>(&'a self) -> Option<alloc::boxed::Box<dyn Iterator<Item = &'a dyn miette::Diagnostic> + 'a>> {
use alloc::borrow::Borrow;
Option::Some(alloc::boxed::Box::new(
fn related<'a>(&'a self) -> Option<miette::__alloc::Box<dyn Iterator<Item = &'a dyn miette::Diagnostic> + 'a>> {
use miette::__alloc::borrow::Borrow;
Option::Some(miette::__alloc::Box::new(
self.#rel.iter().map(|x| -> &(dyn miette::Diagnostic) { &*x.borrow() })
))
}

View File

@ -96,7 +96,7 @@ impl Url {
}
};
Some(quote! {
Self::#ident #pat => Option::Some(alloc::boxed::Box::new(format!(#fmt #args))),
Self::#ident #pat => Option::Some(miette::__alloc::Box::new(format!(#fmt #args))),
})
},
)
@ -129,10 +129,10 @@ impl Url {
}
};
Some(quote! {
fn url(&self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
fn url(&self) -> Option<miette::__alloc::Box<dyn core::fmt::Display + '_>> {
#[allow(unused_variables, deprecated)]
let Self #pat = self;
Option::Some(alloc::boxed::Box::new(format!(#fmt #args)))
Option::Some(miette::__alloc::Box::new(format!(#fmt #args)))
}
})
}

View File

@ -8,8 +8,8 @@ use core::{convert::Infallible, fmt::Display};
use crate::{Diagnostic, LabeledSpan, Severity, SourceCode};
#[cfg(not(feature = "std"))]
impl crate::StdError for Infallible {}
// Note: Infallible implements core::error::Error since Rust 1.81,
// so we don't need to provide our own StdError impl.
impl Diagnostic for Infallible {
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {

View File

@ -1,12 +1,9 @@
extern crate alloc;
#[cfg(not(feature = "std"))]
use crate::StdError as Error;
use alloc::boxed::Box;
use core::error::Error;
use core::fmt::{self, Display};
#[cfg(feature = "std")]
use std::error::Error;
#[cfg(feature = "std")]
use std::io;
use crate::Diagnostic;
@ -93,10 +90,7 @@ impl Diagnostic for MietteError {
pub(crate) mod tests {
#[cfg(not(feature = "std"))]
use crate::StdError as Error;
#[cfg(not(feature = "std"))]
use alloc::string::ToString;
#[cfg(feature = "std")]
use std::string::ToString;
use super::*;

View File

@ -1,7 +1,7 @@
extern crate alloc;
use crate::StdError as Error;
use alloc::boxed::Box;
use core::error::Error;
use crate::{Diagnostic, Report};
@ -42,15 +42,6 @@ pub trait IntoDiagnostic<T, E> {
fn into_diagnostic(self) -> Result<T, Report>;
}
#[cfg(feature = "std")]
impl<T, E: std::error::Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E> {
#[track_caller]
fn into_diagnostic(self) -> Result<T, Report> {
self.map_err(|e| DiagnosticError(Box::new(e)).into())
}
}
#[cfg(not(feature = "std"))]
impl<T, E: Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E> {
#[track_caller]
fn into_diagnostic(self) -> Result<T, Report> {
@ -60,11 +51,13 @@ impl<T, E: Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E>
#[cfg(test)]
mod tests {
extern crate alloc;
use alloc::string::ToString;
use super::IntoDiagnostic;
#[cfg(feature = "std")]
use std::io::{self};
#[cfg(feature = "std")]
use std::string::ToString;
use std::io;
#[cfg(feature = "std")]
use crate::error::tests::TestError;

View File

@ -45,20 +45,14 @@
// let error = $msg;
// (&error).miette_kind().new(error)
#[cfg(not(feature = "std"))]
extern crate alloc;
use super::Report;
use alloc::boxed::Box;
use core::fmt::{Debug, Display};
use super::Report;
use crate::Diagnostic;
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
#[cfg(feature = "std")]
use std::boxed::Box;
pub struct Adhoc;
pub trait AdhocKind: Sized {

View File

@ -9,11 +9,9 @@ extern crate alloc;
use alloc::boxed::Box;
use core::fmt::Display;
#[cfg(not(feature = "std"))]
use crate::StdError;
use spin::Once;
use core::error::Error as StdError;
#[cfg(feature = "std")]
use std::error::Error as StdError;
use std::sync::OnceLock;
#[allow(unreachable_pub)]
pub use into_diagnostic::*;
@ -67,7 +65,11 @@ unsafe impl Send for Report {}
pub type ErrorHook =
Box<dyn Fn(&(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> + Sync + Send + 'static>;
static HOOK: Once<ErrorHook> = Once::new();
#[cfg(feature = "std")]
static HOOK: OnceLock<ErrorHook> = OnceLock::new();
#[cfg(not(feature = "std"))]
static HOOK: spin::Once<ErrorHook> = spin::Once::new();
fn default_hook() -> ErrorHook {
Box::new(get_default_printer)
@ -87,39 +89,51 @@ impl core::fmt::Display for InstallError {
impl StdError for InstallError {}
impl Diagnostic for InstallError {}
/**
Set the error hook.
*/
/// Set the error hook.
#[cfg(feature = "std")]
pub fn set_hook(hook: ErrorHook) -> Result<(), InstallError> {
HOOK.set(hook).map_err(|_| InstallError)
}
/// Set the error hook.
#[cfg(not(feature = "std"))]
pub fn set_hook(hook: ErrorHook) -> Result<(), InstallError> {
HOOK.call_once(|| hook);
Ok(())
}
#[cfg(feature = "std")]
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()
});
let hook = HOOK.get_or_init(default_hook);
hook(error)
}
#[cfg(not(feature = "std"))]
pub(crate) fn capture_handler(error: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> {
let hook = HOOK.call_once(default_hook);
hook(error)
}
#[track_caller]
#[cfg(feature = "std")]
pub(crate) fn capture_handler_with_location(
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()
});
let hook = HOOK.get_or_init(default_hook);
let mut handler = hook(error);
handler.track_caller(core::panic::Location::caller());
handler
}
{
let mut handler = hook(error);
handler.track_caller(core::panic::Location::caller());
handler
}
#[track_caller]
#[cfg(not(feature = "std"))]
pub(crate) fn capture_handler_with_location(
error: &(dyn Diagnostic + 'static),
) -> Box<dyn ReportHandler> {
let hook = HOOK.call_once(default_hook);
let mut handler = hook(error);
handler.track_caller(core::panic::Location::caller());
handler
}
fn get_default_printer(_err: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler + 'static> {

View File

@ -211,14 +211,14 @@ impl<C> StdError for WithSourceCode<Report, C> {
#[cfg(all(test, feature = "std"))]
mod tests {
extern crate alloc;
use alloc::boxed::Box;
#[cfg(feature = "fancy")]
use std::format;
use std::{
boxed::Box,
string::{String, ToString},
};
use alloc::format;
use alloc::string::{String, ToString};
#[cfg(feature = "fancy")]
use std::{vec, vec::Vec};
use alloc::{vec, vec::Vec};
use thiserror::Error;
use crate::{Diagnostic, LabeledSpan, Report, SourceCode, SourceSpan};
@ -232,7 +232,7 @@ mod tests {
impl Diagnostic for Inner {
fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
Some(Box::new(std::iter::once(LabeledSpan::underline(self.at))))
Some(Box::new(core::iter::once(LabeledSpan::underline(self.at))))
}
fn source_code(&self) -> Option<&dyn SourceCode> {

View File

@ -352,25 +352,18 @@ impl MietteHandlerOpts {
} else if let Some(force_graphical) = self.force_graphical {
force_graphical
} else {
#[cfg(feature = "fancy-no-syscall")]
#[cfg(all(feature = "fancy-no-syscall", not(feature = "fancy-no-backtrace")))]
{
// In no-std environment, assume graphics are available
true
}
#[cfg(all(not(feature = "fancy-no-syscall"), feature = "std"))]
#[cfg(feature = "fancy-no-backtrace")]
{
// In std environment, check NO_GRAPHICS env var
if let Ok(env) = std::env::var("NO_GRAPHICS") {
env == "0"
} else {
true
}
}
#[cfg(all(not(feature = "fancy-no-syscall"), not(feature = "std")))]
{
// In no-std environment without fancy-no-syscall, default to true
true
}
}
}
@ -485,77 +478,63 @@ impl From<HighlighterOption> for MietteHighlighter {
}
mod syscall {
use cfg_if::cfg_if;
#[inline]
pub(super) fn terminal_width() -> Option<usize> {
cfg_if! {
if #[cfg(any(feature = "fancy-no-syscall", miri))] {
None
} else if #[cfg(feature = "fancy-no-backtrace")] {
terminal_size::terminal_size().map(|size| size.0 .0 as usize)
} else {
None
}
#[cfg(all(feature = "fancy-no-backtrace", not(miri)))]
{
terminal_size::terminal_size().map(|size| size.0 .0 as usize)
}
#[cfg(any(not(feature = "fancy-no-backtrace"), miri))]
{
None
}
}
#[inline]
pub(super) fn supports_hyperlinks() -> bool {
cfg_if! {
if #[cfg(feature = "fancy-no-syscall")] {
false
} else if #[cfg(feature = "fancy-no-backtrace")] {
supports_hyperlinks::on(supports_hyperlinks::Stream::Stderr)
} else {
false
}
#[cfg(feature = "fancy-no-backtrace")]
{
supports_hyperlinks::on(supports_hyperlinks::Stream::Stderr)
}
#[cfg(not(feature = "fancy-no-backtrace"))]
{
false
}
}
#[inline]
pub(super) fn supports_color() -> bool {
cfg_if! {
if #[cfg(all(feature = "fancy", not(feature = "fancy-no-syscall")))] {
// Standard fancy mode with full std support
supports_color::on(supports_color::Stream::Stderr).is_some()
} else if #[cfg(all(feature = "fancy", feature = "fancy-no-backtrace"))] {
// Fancy mode without backtrace but with color support
supports_color::on(supports_color::Stream::Stderr).is_some()
} else if #[cfg(not(feature = "std"))] {
// No-std environment - no color support by default
false
} else {
// All other cases - no color support
false
}
#[cfg(feature = "fancy-no-backtrace")]
{
supports_color::on(supports_color::Stream::Stderr).is_some()
}
#[cfg(not(feature = "fancy-no-backtrace"))]
{
false
}
}
#[inline]
pub(super) fn supports_color_has_16m() -> Option<bool> {
cfg_if! {
if #[cfg(feature = "fancy-no-backtrace")] {
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 {
Some(true) // Fallback to assuming RGB support
}
#[cfg(feature = "fancy-no-backtrace")]
{
supports_color::on(supports_color::Stream::Stderr).map(|color| color.has_16m)
}
#[cfg(not(feature = "fancy-no-backtrace"))]
{
None
}
}
#[inline]
pub(super) fn supports_unicode() -> bool {
cfg_if! {
if #[cfg(feature = "fancy-no-syscall")] {
false
} else if #[cfg(feature = "fancy-no-backtrace")] {
supports_unicode::on(supports_unicode::Stream::Stderr)
} else {
false
}
#[cfg(feature = "fancy-no-backtrace")]
{
supports_unicode::on(supports_unicode::Stream::Stderr)
}
#[cfg(not(feature = "fancy-no-backtrace"))]
{
false
}
}
}

View File

@ -71,13 +71,9 @@ impl GraphicalTheme {
impl Default for GraphicalTheme {
fn default() -> Self {
#[cfg(feature = "fancy-no-syscall")]
{
// In no-std environments, default to no-color mode
Self::unicode_nocolor()
}
#[cfg(all(not(feature = "fancy-no-syscall"), feature = "std"))]
#[cfg(feature = "fancy-no-backtrace")]
{
use std::io::IsTerminal;
match std::env::var("NO_COLOR") {
_ if !std::io::stdout().is_terminal() || !std::io::stderr().is_terminal() => {
Self::none()
@ -86,10 +82,9 @@ impl Default for GraphicalTheme {
_ => Self::unicode(),
}
}
#[cfg(all(not(feature = "fancy-no-syscall"), not(feature = "std")))]
#[cfg(not(feature = "fancy-no-backtrace"))]
{
// In no-std environment, default to unicode theme
Self::unicode()
Self::unicode_nocolor()
}
}
}

View File

@ -84,23 +84,17 @@ impl MietteHighlighter {
impl Default for MietteHighlighter {
fn default() -> Self {
#[cfg(all(feature = "syntect-highlighter", not(feature = "fancy-no-syscall")))]
#[cfg(feature = "syntect-highlighter")]
{
use std::io::IsTerminal;
match std::env::var("NO_COLOR") {
_ if !std::io::stdout().is_terminal() || !std::io::stderr().is_terminal() => {
//TODO: should use ANSI styling instead of 24-bit truecolor here
Self(Arc::new(SyntectHighlighter::default()))
}
Ok(string) if string != "0" => MietteHighlighter::nocolor(),
_ => Self(Arc::new(SyntectHighlighter::default())),
}
}
#[cfg(all(feature = "syntect-highlighter", feature = "fancy-no-syscall"))]
{
// In no-std environment, use syntect but without terminal detection
Self(Arc::new(SyntectHighlighter::default()))
}
#[cfg(not(feature = "syntect-highlighter"))]
{
MietteHighlighter::nocolor()

View File

@ -103,7 +103,7 @@ impl SyntectHighlighter {
}
// finally, attempt to guess syntax based on first line
self.syntax_set.find_syntax_by_first_line(
std::str::from_utf8(contents.data())
core::str::from_utf8(contents.data())
.ok()?
.split('\n')
.next()?,

View File

@ -1,6 +1,11 @@
#![no_std]
#![deny(missing_docs, missing_debug_implementations, nonstandard_style)]
#![warn(unreachable_pub, rust_2018_idioms)]
#![warn(
clippy::alloc_instead_of_core,
clippy::std_instead_of_core,
clippy::std_instead_of_alloc
)]
#![allow(unexpected_cfgs)]
//! You run miette? You run her code like the software? Oh. Oh! Error code for
@ -845,18 +850,13 @@
#[cfg(feature = "std")]
extern crate std;
#[cfg(feature = "std")]
pub use std::error::Error as StdError;
pub use core::error::Error as StdError;
#[cfg(not(feature = "std"))]
/// Compatibility trait for error handling in no_std environments.
/// This trait provides a subset of `std::error::Error` functionality
/// suitable for no_std environments.
pub trait StdError: core::fmt::Debug + core::fmt::Display {
/// Returns the lower-level source of this error, if any.
fn source(&self) -> Option<&(dyn StdError + 'static)> {
None
}
#[doc(hidden)]
pub mod __alloc {
extern crate alloc;
pub use alloc::borrow;
pub use alloc::boxed::Box;
}
#[cfg(feature = "derive")]

View File

@ -1,13 +1,10 @@
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::error::Error;
use core::fmt::{Debug, Display};
#[cfg(feature = "std")]
use std::error::Error;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@ -267,6 +264,7 @@ impl MietteDiagnostic {
#[cfg(feature = "serde")]
#[test]
fn test_serialize_miette_diagnostic() {
use alloc::format;
use serde_json::json;
use crate::diagnostic;
@ -317,6 +315,7 @@ fn test_serialize_miette_diagnostic() {
#[cfg(feature = "serde")]
#[test]
fn test_deserialize_miette_diagnostic() {
use alloc::format;
use serde_json::json;
use crate::diagnostic;

View File

@ -1,6 +1,11 @@
#[cfg(feature = "std")]
// `fancy` feature requires std, so std imports are fine here.
#![allow(
clippy::std_instead_of_core,
clippy::std_instead_of_alloc,
clippy::alloc_instead_of_core
)]
use std::boxed::Box;
#[cfg(feature = "std")]
use std::{
eprintln,
error::Error,
@ -9,14 +14,11 @@ use std::{
string::{String, ToString},
};
#[cfg(feature = "std")]
use backtrace::Backtrace;
#[cfg(feature = "std")]
use crate::{Context, Diagnostic, Result};
/// Makes miette show pretty error messages when your program crashes.
#[cfg(feature = "std")]
pub fn set_panic_hook() {
std::panic::set_hook(Box::new(move |info| {
let mut message = "Something went wrong".to_string();
@ -38,20 +40,9 @@ pub fn set_panic_hook() {
}));
}
/// Makes miette show pretty error messages when your program crashes.
///
/// On computers without the standard library, this function does nothing
/// because crash hooks need the standard library to work.
#[cfg(not(feature = "std"))]
pub fn set_panic_hook() {
// Does nothing on computers without the standard library
}
#[derive(Debug)]
#[cfg(feature = "std")]
struct Panic(String);
#[cfg(feature = "std")]
impl Display for Panic {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let msg = &self.0;
@ -60,10 +51,8 @@ impl Display for Panic {
}
}
#[cfg(feature = "std")]
impl Error for Panic {}
#[cfg(feature = "std")]
impl Diagnostic for Panic {
fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
Some(Box::new(
@ -72,7 +61,6 @@ impl Diagnostic for Panic {
}
}
#[cfg(feature = "std")]
impl Panic {
fn backtrace() -> String {
use std::fmt::Write;
@ -129,7 +117,6 @@ impl Panic {
}
#[cfg(test)]
#[cfg(feature = "std")]
mod tests {
use std::{borrow::ToOwned, error::Error};

View File

@ -177,8 +177,8 @@ impl From<String> for Box<dyn Diagnostic + Send + Sync> {
use crate::DiagnosticError;
#[cfg(feature = "std")]
impl From<Box<dyn std::error::Error + Send + Sync>> for Box<dyn Diagnostic + Send + Sync> {
fn from(s: Box<dyn std::error::Error + Send + Sync>) -> Self {
impl From<Box<dyn core::error::Error + Send + Sync>> for Box<dyn Diagnostic + Send + Sync> {
fn from(s: Box<dyn core::error::Error + Send + Sync>) -> Self {
Box::new(DiagnosticError(s))
}
}
@ -374,6 +374,7 @@ impl LabeledSpan {
#[cfg(feature = "serde")]
#[test]
fn test_serialize_labeled_span() {
use alloc::string::ToString;
use serde_json::json;
assert_eq!(
@ -397,6 +398,7 @@ fn test_serialize_labeled_span() {
#[cfg(feature = "serde")]
#[test]
fn test_deserialize_labeled_span() {
use alloc::string::ToString;
use serde_json::json;
let span: LabeledSpan = serde_json::from_value(json!({

View File

@ -1,7 +1,5 @@
#![cfg(feature = "fancy-no-backtrace")]
extern crate alloc;
use miette::{Diagnostic, MietteHandler, MietteHandlerOpts, ReportHandler, RgbColors};
use regex::Regex;
use std::ffi::OsString;

View File

@ -1,5 +1,4 @@
#[allow(unused_assignments)] // some fields unused when feature="fancy"
extern crate alloc;
#![allow(unused_assignments)] // some fields unused when feature="fancy"
use miette::{Diagnostic, Report, Severity, SourceSpan};
use thiserror::Error;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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