mirror of
https://github.com/eyre-rs/eyre.git
synced 2025-09-28 05:21:34 +00:00
Detect nightly and only expose backtrace if available
This commit is contained in:
parent
3cd72734d5
commit
270ea5e7d5
39
build.rs
Normal file
39
build.rs
Normal file
@ -0,0 +1,39 @@
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
use std::str;
|
||||
|
||||
fn main() {
|
||||
let compiler = match rustc_version() {
|
||||
Some(compiler) => compiler,
|
||||
None => return,
|
||||
};
|
||||
|
||||
if compiler.nightly {
|
||||
println!("cargo:rustc-cfg=backtrace");
|
||||
}
|
||||
}
|
||||
|
||||
struct Compiler {
|
||||
nightly: bool,
|
||||
}
|
||||
|
||||
fn rustc_version() -> Option<Compiler> {
|
||||
let rustc = match env::var_os("RUSTC") {
|
||||
Some(rustc) => rustc,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let output = match Command::new(rustc).arg("--version").output() {
|
||||
Ok(output) => output,
|
||||
Err(_) => return None,
|
||||
};
|
||||
|
||||
let version = match str::from_utf8(&output.stdout) {
|
||||
Ok(version) => version,
|
||||
Err(_) => return None,
|
||||
};
|
||||
|
||||
Some(Compiler {
|
||||
nightly: version.contains("nightly") || version.contains("dev"),
|
||||
})
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
use std::backtrace::Backtrace;
|
||||
use crate::Error;
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt::{self, Debug, Display};
|
||||
|
||||
use crate::Error;
|
||||
#[cfg(backtrace)]
|
||||
use std::backtrace::Backtrace;
|
||||
|
||||
/// Provides the `context` method for `Result`.
|
||||
pub trait Context<T, E> {
|
||||
@ -89,6 +90,7 @@ where
|
||||
E: StdError + 'static,
|
||||
C: Display,
|
||||
{
|
||||
#[cfg(backtrace)]
|
||||
fn backtrace(&self) -> Option<&Backtrace> {
|
||||
self.error.backtrace()
|
||||
}
|
||||
@ -102,6 +104,7 @@ impl<C> StdError for ContextError<Error, C>
|
||||
where
|
||||
C: Display,
|
||||
{
|
||||
#[cfg(backtrace)]
|
||||
fn backtrace(&self) -> Option<&Backtrace> {
|
||||
Some(self.error.backtrace())
|
||||
}
|
||||
|
38
src/error.rs
38
src/error.rs
@ -1,12 +1,14 @@
|
||||
use crate::context::ContextError;
|
||||
use std::any::TypeId;
|
||||
use std::backtrace::{Backtrace, BacktraceStatus};
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt::{self, Debug, Display};
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::ptr;
|
||||
|
||||
#[cfg(backtrace)]
|
||||
use std::backtrace::{Backtrace, BacktraceStatus};
|
||||
|
||||
/// The `Error` type, a wrapper around a dynamic error type.
|
||||
///
|
||||
/// `Error` functions a lot like `Box<dyn std::error::Error>`, with these
|
||||
@ -48,6 +50,7 @@ impl Error {
|
||||
where
|
||||
E: StdError + Send + Sync + 'static,
|
||||
{
|
||||
#[cfg(backtrace)]
|
||||
let backtrace = match error.backtrace() {
|
||||
Some(_) => None,
|
||||
None => Some(Backtrace::capture()),
|
||||
@ -59,6 +62,7 @@ impl Error {
|
||||
let inner = Box::new(ErrorImpl {
|
||||
vtable,
|
||||
type_id,
|
||||
#[cfg(backtrace)]
|
||||
backtrace,
|
||||
error,
|
||||
});
|
||||
@ -90,6 +94,12 @@ impl Error {
|
||||
}
|
||||
|
||||
/// Get the backtrace for this Error.
|
||||
///
|
||||
/// Backtraces are only available on the nightly channel. Tracking issue:
|
||||
/// [rust-lang/rust#53487][tracking].
|
||||
///
|
||||
/// [tracking]: https://github.com/rust-lang/rust/issues/53487
|
||||
#[cfg(backtrace)]
|
||||
pub fn backtrace(&self) -> &Backtrace {
|
||||
// NB: this unwrap can only fail if the underlying error's backtrace
|
||||
// method is nondeterministic, which would only happen in maliciously
|
||||
@ -197,18 +207,21 @@ impl Debug for Error {
|
||||
}
|
||||
}
|
||||
|
||||
let backtrace = self.backtrace();
|
||||
match backtrace.status() {
|
||||
BacktraceStatus::Captured => {
|
||||
writeln!(f, "\n{}", backtrace)?;
|
||||
#[cfg(backtrace)]
|
||||
{
|
||||
let backtrace = self.backtrace();
|
||||
match backtrace.status() {
|
||||
BacktraceStatus::Captured => {
|
||||
writeln!(f, "\n{}", backtrace)?;
|
||||
}
|
||||
BacktraceStatus::Disabled => {
|
||||
writeln!(
|
||||
f,
|
||||
"\nbacktrace disabled; run with RUST_LIB_BACKTRACE=1 environment variable to display a backtrace"
|
||||
)?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
BacktraceStatus::Disabled => {
|
||||
writeln!(
|
||||
f,
|
||||
"\nbacktrace disabled; run with RUST_LIB_BACKTRACE=1 environment variable to display a backtrace"
|
||||
)?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -235,6 +248,7 @@ impl Drop for Error {
|
||||
struct ErrorImpl<E> {
|
||||
vtable: *const (),
|
||||
type_id: TypeId,
|
||||
#[cfg(backtrace)]
|
||||
backtrace: Option<Backtrace>,
|
||||
error: E,
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![feature(backtrace)]
|
||||
#![cfg_attr(backtrace, feature(backtrace))]
|
||||
|
||||
mod context;
|
||||
mod error;
|
||||
|
Loading…
x
Reference in New Issue
Block a user