From f0b0040bf846f937eb0563d8d58db0f96d210373 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 11 Oct 2021 18:02:21 +0200 Subject: [PATCH 1/2] Use proc_macro::is_available() on rust 1.57+ This avoids the need for catching a panic, which is incompatible with projects using panic=abort or cg_clif. --- build.rs | 10 ++++++++++ src/detection.rs | 14 +++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/build.rs b/build.rs index f32d5c8f..2fb73262 100644 --- a/build.rs +++ b/build.rs @@ -33,6 +33,12 @@ // location of a token. Enabled by procmacro2_semver_exempt or the // "span-locations" Cargo cfg. This is behind a cfg because tracking // location inside spans is a performance hit. +// +// "is_available" +// Use `proc_macro::is_available()` to detect if the proc macro API is +// available or needs to be polyfilled instead of trying to use the proc +// macro API and catching a panic if it isn't available. +// Enabled on Rust 1.57+ use std::env; use std::iter; @@ -82,6 +88,10 @@ fn main() { println!("cargo:rustc-cfg=literal_from_str"); } + if version.minor >= 57 { + println!("cargo:rustc-cfg=is_available"); + } + let target = env::var("TARGET").unwrap(); if !enable_use_proc_macro(&target) { return; diff --git a/src/detection.rs b/src/detection.rs index a90e07e9..7ceb5e32 100644 --- a/src/detection.rs +++ b/src/detection.rs @@ -12,8 +12,16 @@ pub(crate) fn inside_proc_macro() -> bool { _ => {} } - INIT.call_once(initialize); - inside_proc_macro() + #[cfg(feature = "is_available")] + { + proc_macro::is_available() + } + + #[cfg(not(feature = "is_available"))] + { + INIT.call_once(initialize); + inside_proc_macro() + } } pub(crate) fn force_fallback() { @@ -21,7 +29,7 @@ pub(crate) fn force_fallback() { } pub(crate) fn unforce_fallback() { - initialize(); + WORKS.store(0, Ordering::SeqCst); } // Swap in a null panic hook to avoid printing "thread panicked" to stderr, From 07ee9bba1503d59077fb4a32c244ae3f2ae6e9c4 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 12 Oct 2021 13:36:01 +0200 Subject: [PATCH 2/2] Fix review comment --- src/detection.rs | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/detection.rs b/src/detection.rs index 7ceb5e32..c88150df 100644 --- a/src/detection.rs +++ b/src/detection.rs @@ -12,16 +12,8 @@ pub(crate) fn inside_proc_macro() -> bool { _ => {} } - #[cfg(feature = "is_available")] - { - proc_macro::is_available() - } - - #[cfg(not(feature = "is_available"))] - { - INIT.call_once(initialize); - inside_proc_macro() - } + INIT.call_once(initialize); + inside_proc_macro() } pub(crate) fn force_fallback() { @@ -29,7 +21,7 @@ pub(crate) fn force_fallback() { } pub(crate) fn unforce_fallback() { - WORKS.store(0, Ordering::SeqCst); + initialize(); } // Swap in a null panic hook to avoid printing "thread panicked" to stderr, @@ -57,19 +49,27 @@ pub(crate) fn unforce_fallback() { // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from // the main thread before launching any other threads. fn initialize() { - type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static; + #[cfg(feature = "is_available")] + { + WORKS.store(proc_macro::is_available() as usize + 1, Ordering::SeqCst); + } + + #[cfg(not(feature = "is_available"))] + { + type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static; - let null_hook: Box = Box::new(|_panic_info| { /* ignore */ }); - let sanity_check = &*null_hook as *const PanicHook; - let original_hook = panic::take_hook(); - panic::set_hook(null_hook); + let null_hook: Box = Box::new(|_panic_info| { /* ignore */ }); + let sanity_check = &*null_hook as *const PanicHook; + let original_hook = panic::take_hook(); + panic::set_hook(null_hook); - let works = panic::catch_unwind(proc_macro::Span::call_site).is_ok(); - WORKS.store(works as usize + 1, Ordering::SeqCst); + let works = panic::catch_unwind(proc_macro::Span::call_site).is_ok(); + WORKS.store(works as usize + 1, Ordering::SeqCst); - let hopefully_null_hook = panic::take_hook(); - panic::set_hook(original_hook); - if sanity_check != &*hopefully_null_hook { - panic!("observed race condition in proc_macro2::inside_proc_macro"); + let hopefully_null_hook = panic::take_hook(); + panic::set_hook(original_hook); + if sanity_check != &*hopefully_null_hook { + panic!("observed race condition in proc_macro2::inside_proc_macro"); + } } }