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..c88150df 100644 --- a/src/detection.rs +++ b/src/detection.rs @@ -49,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"); + } } }