From d6d896df4c63fcb7b7c34aad5f5f049bf6cfab3b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Nov 2024 20:51:28 -0500 Subject: [PATCH] Access Backtrace exclusively through ::thiserror --- build.rs | 24 ++++++++++++++++++++++++ impl/src/expand.rs | 20 ++++++++++---------- src/lib.rs | 3 +++ 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/build.rs b/build.rs index 4b40e9d..8495ef3 100644 --- a/build.rs +++ b/build.rs @@ -5,12 +5,14 @@ use std::io::ErrorKind; use std::iter; use std::path::Path; use std::process::{self, Command, Stdio}; +use std::str; fn main() { println!("cargo:rerun-if-changed=build/probe.rs"); println!("cargo:rustc-check-cfg=cfg(error_generic_member_access)"); println!("cargo:rustc-check-cfg=cfg(thiserror_nightly_testing)"); + println!("cargo:rustc-check-cfg=cfg(thiserror_no_backtrace_type)"); let error_generic_member_access; let consider_rustc_bootstrap; @@ -54,6 +56,17 @@ fn main() { if consider_rustc_bootstrap { println!("cargo:rerun-if-env-changed=RUSTC_BOOTSTRAP"); } + + let rustc = match rustc_minor_version() { + Some(rustc) => rustc, + None => return, + }; + + // std::backtrace::Backtrace stabilized in Rust 1.65 + // https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html#stabilized-apis + if rustc < 65 { + println!("cargo:rustc-cfg=thiserror_no_backtrace_type"); + } } fn compile_probe(rustc_bootstrap: bool) -> bool { @@ -135,6 +148,17 @@ fn compile_probe(rustc_bootstrap: bool) -> bool { success } +fn rustc_minor_version() -> Option { + let rustc = cargo_env_var("RUSTC"); + let output = Command::new(rustc).arg("--version").output().ok()?; + let version = str::from_utf8(&output.stdout).ok()?; + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } + pieces.next()?.parse().ok() +} + fn cargo_env_var(key: &str) -> OsString { env::var_os(key).unwrap_or_else(|| { eprintln!("Environment variable ${key} is not set during execution of build script"); diff --git a/impl/src/expand.rs b/impl/src/expand.rs index bfa1b50..e172af9 100644 --- a/impl/src/expand.rs +++ b/impl/src/expand.rs @@ -118,12 +118,12 @@ fn impl_struct(input: Struct) -> TokenStream { } else if type_is_option(backtrace_field.ty) { Some(quote! { if let ::core::option::Option::Some(backtrace) = &self.#backtrace { - #request.provide_ref::<::std::backtrace::Backtrace>(backtrace); + #request.provide_ref::<::thiserror::__private::Backtrace>(backtrace); } }) } else { Some(quote! { - #request.provide_ref::<::std::backtrace::Backtrace>(&self.#backtrace); + #request.provide_ref::<::thiserror::__private::Backtrace>(&self.#backtrace); }) }; quote! { @@ -134,12 +134,12 @@ fn impl_struct(input: Struct) -> TokenStream { } else if type_is_option(backtrace_field.ty) { quote! { if let ::core::option::Option::Some(backtrace) = &self.#backtrace { - #request.provide_ref::<::std::backtrace::Backtrace>(backtrace); + #request.provide_ref::<::thiserror::__private::Backtrace>(backtrace); } } } else { quote! { - #request.provide_ref::<::std::backtrace::Backtrace>(&self.#backtrace); + #request.provide_ref::<::thiserror::__private::Backtrace>(&self.#backtrace); } }; quote! { @@ -309,12 +309,12 @@ fn impl_enum(input: Enum) -> TokenStream { let self_provide = if type_is_option(backtrace_field.ty) { quote! { if let ::core::option::Option::Some(backtrace) = backtrace { - #request.provide_ref::<::std::backtrace::Backtrace>(backtrace); + #request.provide_ref::<::thiserror::__private::Backtrace>(backtrace); } } } else { quote! { - #request.provide_ref::<::std::backtrace::Backtrace>(backtrace); + #request.provide_ref::<::thiserror::__private::Backtrace>(backtrace); } }; quote! { @@ -357,12 +357,12 @@ fn impl_enum(input: Enum) -> TokenStream { let body = if type_is_option(backtrace_field.ty) { quote! { if let ::core::option::Option::Some(backtrace) = backtrace { - #request.provide_ref::<::std::backtrace::Backtrace>(backtrace); + #request.provide_ref::<::thiserror::__private::Backtrace>(backtrace); } } } else { quote! { - #request.provide_ref::<::std::backtrace::Backtrace>(backtrace); + #request.provide_ref::<::thiserror::__private::Backtrace>(backtrace); } }; quote! { @@ -532,11 +532,11 @@ fn from_initializer( let backtrace_member = &backtrace_field.member; if type_is_option(backtrace_field.ty) { quote! { - #backtrace_member: ::core::option::Option::Some(::std::backtrace::Backtrace::capture()), + #backtrace_member: ::core::option::Option::Some(::thiserror::__private::Backtrace::capture()), } } else { quote! { - #backtrace_member: ::core::convert::From::from(::std::backtrace::Backtrace::capture()), + #backtrace_member: ::core::convert::From::from(::thiserror::__private::Backtrace::capture()), } } }); diff --git a/src/lib.rs b/src/lib.rs index 26dbdb1..17975e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -287,6 +287,9 @@ pub mod __private { #[cfg(error_generic_member_access)] #[doc(hidden)] pub use crate::provide::ThiserrorProvide; + #[cfg(not(thiserror_no_backtrace_type))] + #[doc(hidden)] + pub use std::backtrace::Backtrace; #[doc(hidden)] pub use std::error::Error; }