From c07cab4b60143d8e038c68aa0c9801ec71aad21d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Wed, 14 Jan 2026 15:38:54 -0500 Subject: [PATCH] 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 --- Cargo.toml | 10 +-- build.rs | 6 -- miette-derive/src/code.rs | 10 +-- miette-derive/src/diagnostic_source.rs | 4 +- miette-derive/src/forward.rs | 10 +-- miette-derive/src/help.rs | 12 ++-- miette-derive/src/label.rs | 6 +- miette-derive/src/related.rs | 8 +-- miette-derive/src/url.rs | 6 +- src/diagnostic_impls.rs | 4 +- src/error.rs | 8 +-- src/eyreish/into_diagnostic.rs | 19 ++---- src/eyreish/kind.rs | 10 +-- src/eyreish/mod.rs | 60 +++++++++------- src/eyreish/wrapper.rs | 14 ++-- src/handler.rs | 95 ++++++++++---------------- src/handlers/theme.rs | 13 ++-- src/highlighters/mod.rs | 8 +-- src/highlighters/syntect.rs | 2 +- src/lib.rs | 22 +++--- src/miette_diagnostic.rs | 7 +- src/panic.rs | 27 ++------ src/protocol.rs | 6 +- tests/color_format.rs | 2 - tests/derive.rs | 3 +- tests/graphical.rs | 2 - tests/narrated.rs | 2 - tests/test_derive_attr.rs | 1 - tests/test_derive_collection.rs | 2 - tests/test_diagnostic_source_macro.rs | 2 - tests/test_json.rs | 2 - 31 files changed, 158 insertions(+), 225 deletions(-) delete mode 100644 build.rs diff --git a/Cargo.toml b/Cargo.toml index e830164..5b2dece 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] diff --git a/build.rs b/build.rs deleted file mode 100644 index fb54b74..0000000 --- a/build.rs +++ /dev/null @@ -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)"); -} diff --git a/miette-derive/src/code.rs b/miette-derive/src/code.rs index 83cb053..04b655e 100644 --- a/miette-derive/src/code.rs +++ b/miette-derive/src/code.rs @@ -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 { let code = &self.0; Some(quote! { - fn code(&self) -> core::option::Option> { - core::option::Option::Some(alloc::boxed::Box::new(#code)) + fn code(&self) -> core::option::Option> { + core::option::Option::Some(miette::__alloc::Box::new(#code)) } }) } diff --git a/miette-derive/src/diagnostic_source.rs b/miette-derive/src/diagnostic_source.rs index 35b5e35..fff97b1 100644 --- a/miette-derive/src/diagnostic_source.rs +++ b/miette-derive/src/diagnostic_source.rs @@ -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)) } }) } diff --git a/miette-derive/src/forward.rs b/miette-derive/src/forward.rs index cdc658f..278d6ca 100644 --- a/miette-derive/src/forward.rs +++ b/miette-derive/src/forward.rs @@ -58,22 +58,22 @@ impl WhichFn { pub fn signature(&self) -> TokenStream { match self { Self::Code => quote! { - fn code(& self) -> Option> + fn code(& self) -> Option> }, Self::Help => quote! { - fn help(& self) -> Option> + fn help(& self) -> Option> }, Self::Url => quote! { - fn url(& self) -> Option> + fn url(& self) -> Option> }, Self::Severity => quote! { fn severity(&self) -> Option }, Self::Related => quote! { - fn related(&self) -> Option + '_>> + fn related(&self) -> Option + '_>> }, Self::Labels => quote! { - fn labels(&self) -> Option + '_>> + fn labels(&self) -> Option + '_>> }, Self::SourceCode => quote! { fn source_code(&self) -> Option<&dyn miette::SourceCode> diff --git a/miette-derive/src/help.rs b/miette-derive/src/help.rs index 0169027..685537c 100644 --- a/miette-derive/src/help.rs +++ b/miette-derive/src/help.rs @@ -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 { alloc::boxed::Box::new(format!("{}", #var)) }) + miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&#help).as_ref().map(|#var| -> miette::__alloc::Box { 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> { + fn help(&self) -> Option> { #[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> { + fn help(&self) -> Option> { #[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 { alloc::boxed::Box::new(format!("{}", #var)) }) + miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&self.#member).as_ref().map(|#var| -> miette::__alloc::Box { miette::__alloc::Box::new(format!("{}", #var)) }) } }) } diff --git a/miette-derive/src/label.rs b/miette-derive/src/label.rs index 28db920..ff3738a 100644 --- a/miette-derive/src/label.rs +++ b/miette-derive/src/label.rs @@ -226,7 +226,7 @@ impl Labels { Some(quote! { #[allow(unused_variables)] - fn labels(&self) -> Option + '_>> { + fn labels(&self) -> Option + '_>> { 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))) } }), } diff --git a/miette-derive/src/related.rs b/miette-derive/src/related.rs index 8158ea6..6c0a276 100644 --- a/miette-derive/src/related.rs +++ b/miette-derive/src/related.rs @@ -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 { let rel = &self.0; Some(quote! { - fn related<'a>(&'a self) -> Option + 'a>> { - use alloc::borrow::Borrow; - Option::Some(alloc::boxed::Box::new( + fn related<'a>(&'a self) -> Option + 'a>> { + use miette::__alloc::borrow::Borrow; + Option::Some(miette::__alloc::Box::new( self.#rel.iter().map(|x| -> &(dyn miette::Diagnostic) { &*x.borrow() }) )) } diff --git a/miette-derive/src/url.rs b/miette-derive/src/url.rs index 2583a1c..156315b 100644 --- a/miette-derive/src/url.rs +++ b/miette-derive/src/url.rs @@ -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> { + fn url(&self) -> Option> { #[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))) } }) } diff --git a/src/diagnostic_impls.rs b/src/diagnostic_impls.rs index 5a9a65d..fc635d4 100644 --- a/src/diagnostic_impls.rs +++ b/src/diagnostic_impls.rs @@ -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> { diff --git a/src/error.rs b/src/error.rs index f54f4d8..1f34865 100644 --- a/src/error.rs +++ b/src/error.rs @@ -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::*; diff --git a/src/eyreish/into_diagnostic.rs b/src/eyreish/into_diagnostic.rs index c9264ec..758b0e1 100644 --- a/src/eyreish/into_diagnostic.rs +++ b/src/eyreish/into_diagnostic.rs @@ -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 { fn into_diagnostic(self) -> Result; } -#[cfg(feature = "std")] -impl IntoDiagnostic for Result { - #[track_caller] - fn into_diagnostic(self) -> Result { - self.map_err(|e| DiagnosticError(Box::new(e)).into()) - } -} - -#[cfg(not(feature = "std"))] impl IntoDiagnostic for Result { #[track_caller] fn into_diagnostic(self) -> Result { @@ -60,11 +51,13 @@ impl IntoDiagnostic for Result #[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; diff --git a/src/eyreish/kind.rs b/src/eyreish/kind.rs index d3d1df1..7f78df8 100644 --- a/src/eyreish/kind.rs +++ b/src/eyreish/kind.rs @@ -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 { diff --git a/src/eyreish/mod.rs b/src/eyreish/mod.rs index 586fc61..3667b73 100644 --- a/src/eyreish/mod.rs +++ b/src/eyreish/mod.rs @@ -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 Box + Sync + Send + 'static>; -static HOOK: Once = Once::new(); +#[cfg(feature = "std")] +static HOOK: OnceLock = OnceLock::new(); + +#[cfg(not(feature = "std"))] +static HOOK: spin::Once = 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 { - static DEFAULT: Once = 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 { + 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 { - static DEFAULT: Once = 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 { + 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 { diff --git a/src/eyreish/wrapper.rs b/src/eyreish/wrapper.rs index 0b0ac73..fd8af1b 100644 --- a/src/eyreish/wrapper.rs +++ b/src/eyreish/wrapper.rs @@ -211,14 +211,14 @@ impl StdError for WithSourceCode { #[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 + '_>> { - 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> { diff --git a/src/handler.rs b/src/handler.rs index 32a2e5e..5ceaa78 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -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 for MietteHighlighter { } mod syscall { - use cfg_if::cfg_if; - #[inline] pub(super) fn terminal_width() -> Option { - 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 { - 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 } } } diff --git a/src/handlers/theme.rs b/src/handlers/theme.rs index f51b42f..4f61c3b 100644 --- a/src/handlers/theme.rs +++ b/src/handlers/theme.rs @@ -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() } } } diff --git a/src/highlighters/mod.rs b/src/highlighters/mod.rs index 398ad36..437aac9 100644 --- a/src/highlighters/mod.rs +++ b/src/highlighters/mod.rs @@ -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() diff --git a/src/highlighters/syntect.rs b/src/highlighters/syntect.rs index d5df64e..6d31eff 100644 --- a/src/highlighters/syntect.rs +++ b/src/highlighters/syntect.rs @@ -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()?, diff --git a/src/lib.rs b/src/lib.rs index 79ed0fc..dfed8c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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")] diff --git a/src/miette_diagnostic.rs b/src/miette_diagnostic.rs index dc0fa28..d56391a 100644 --- a/src/miette_diagnostic.rs +++ b/src/miette_diagnostic.rs @@ -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; diff --git a/src/panic.rs b/src/panic.rs index eb57601..3437ef8 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -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> { 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}; diff --git a/src/protocol.rs b/src/protocol.rs index ef6f7e0..f34aa7d 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -177,8 +177,8 @@ impl From for Box { use crate::DiagnosticError; #[cfg(feature = "std")] -impl From> for Box { - fn from(s: Box) -> Self { +impl From> for Box { + fn from(s: Box) -> 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!({ diff --git a/tests/color_format.rs b/tests/color_format.rs index f0f1ad5..682f54d 100644 --- a/tests/color_format.rs +++ b/tests/color_format.rs @@ -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; diff --git a/tests/derive.rs b/tests/derive.rs index 087d184..88b46eb 100644 --- a/tests/derive.rs +++ b/tests/derive.rs @@ -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; diff --git a/tests/graphical.rs b/tests/graphical.rs index e2548e1..93c9bce 100644 --- a/tests/graphical.rs +++ b/tests/graphical.rs @@ -1,7 +1,5 @@ #![cfg(feature = "fancy-no-backtrace")] -extern crate alloc; - use miette::{ Diagnostic, GraphicalReportHandler, GraphicalTheme, MietteError, NamedSource, NarratableReportHandler, Report, SourceSpan, diff --git a/tests/narrated.rs b/tests/narrated.rs index ced0b23..52acd13 100644 --- a/tests/narrated.rs +++ b/tests/narrated.rs @@ -1,7 +1,5 @@ #![cfg(feature = "fancy-no-backtrace")] -extern crate alloc; - use miette::{Diagnostic, MietteError, NamedSource, NarratableReportHandler, Report, SourceSpan}; use miette::{GraphicalReportHandler, GraphicalTheme}; diff --git a/tests/test_derive_attr.rs b/tests/test_derive_attr.rs index 8c13670..f2b9ddf 100644 --- a/tests/test_derive_attr.rs +++ b/tests/test_derive_attr.rs @@ -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; diff --git a/tests/test_derive_collection.rs b/tests/test_derive_collection.rs index baf037c..952b505 100644 --- a/tests/test_derive_collection.rs +++ b/tests/test_derive_collection.rs @@ -1,5 +1,3 @@ -extern crate alloc; - use std::{ collections::{LinkedList, VecDeque}, ops::Range, diff --git a/tests/test_diagnostic_source_macro.rs b/tests/test_diagnostic_source_macro.rs index 33aebb6..1349303 100644 --- a/tests/test_diagnostic_source_macro.rs +++ b/tests/test_diagnostic_source_macro.rs @@ -1,5 +1,3 @@ -extern crate alloc; - use miette::Diagnostic; #[derive(Debug, miette::Diagnostic, thiserror::Error)] diff --git a/tests/test_json.rs b/tests/test_json.rs index b055fc7..664318a 100644 --- a/tests/test_json.rs +++ b/tests/test_json.rs @@ -1,6 +1,4 @@ mod json_report_handler { - extern crate alloc; - use miette::{Diagnostic, MietteError, NamedSource, Report, SourceSpan}; use miette::JSONReportHandler;