Skip to content

Commit 0f80653

Browse files
authored
Rollup merge of #71400 - dtolnay:isavailable, r=petrochenkov
proc_macro::is_available() This PR adds `proc_macro::is_available() -> bool` to determine whether proc_macro has been made accessible to the currently running program. The proc_macro crate is only intended for use inside the implementation of procedural macros. All the functions in the crate panic if invoked from outside of a procedural macro, such as from a build script or unit test or ordinary Rust binary. Unfortunately those panics made it impossible for libraries that are designed to support both macro and non-macro use cases (e.g. Syn) to be used from binaries that are compiled with panic=abort. In panic=unwind mode we're able to attempt a proc macro call inside catch_unwind and use libproc_macro's result if it succeeds, otherwise fall back to a non-macro alternative implementation. But in panic=abort there was no way to determine which implementation needs to be used. r? @eddyb attn: @petrochenkov @adetaylor ref: dtolnay/cxx#130
2 parents 16be619 + 3bd742f commit 0f80653

File tree

4 files changed

+56
-0
lines changed

4 files changed

+56
-0
lines changed

src/libproc_macro/bridge/client.rs

+7
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,13 @@ impl BridgeState<'_> {
290290
}
291291

292292
impl Bridge<'_> {
293+
pub(crate) fn is_available() -> bool {
294+
BridgeState::with(|state| match state {
295+
BridgeState::Connected(_) | BridgeState::InUse => true,
296+
BridgeState::NotConnected => false,
297+
})
298+
}
299+
293300
fn enter<R>(self, f: impl FnOnce() -> R) -> R {
294301
// Hide the default panic output within `proc_macro` expansions.
295302
// NB. the server can't do this because it may use a different libstd.

src/libproc_macro/lib.rs

+18
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,24 @@ use std::path::PathBuf;
4545
use std::str::FromStr;
4646
use std::{error, fmt, iter, mem};
4747

48+
/// Determines whether proc_macro has been made accessible to the currently
49+
/// running program.
50+
///
51+
/// The proc_macro crate is only intended for use inside the implementation of
52+
/// procedural macros. All the functions in this crate panic if invoked from
53+
/// outside of a procedural macro, such as from a build script or unit test or
54+
/// ordinary Rust binary.
55+
///
56+
/// With consideration for Rust libraries that are designed to support both
57+
/// macro and non-macro use cases, `proc_macro::is_available()` provides a
58+
/// non-panicking way to detect whether the infrastructure required to use the
59+
/// API of proc_macro is presently available. Returns true if invoked from
60+
/// inside of a procedural macro, false if invoked from any other binary.
61+
#[unstable(feature = "proc_macro_is_available", issue = "71436")]
62+
pub fn is_available() -> bool {
63+
bridge::Bridge::is_available()
64+
}
65+
4866
/// The main type provided by this crate, representing an abstract stream of
4967
/// tokens, or, more specifically, a sequence of token trees.
5068
/// The type provide interfaces for iterating over those token trees and, conversely,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// force-host
2+
// no-prefer-dynamic
3+
4+
#![crate_type = "proc-macro"]
5+
#![feature(proc_macro_is_available)]
6+
7+
extern crate proc_macro;
8+
9+
use proc_macro::{Literal, TokenStream, TokenTree};
10+
11+
#[proc_macro]
12+
pub fn from_inside_proc_macro(_input: TokenStream) -> TokenStream {
13+
proc_macro::is_available().to_string().parse().unwrap()
14+
}
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// run-pass
2+
3+
#![feature(proc_macro_hygiene, proc_macro_is_available)]
4+
5+
extern crate proc_macro;
6+
7+
// aux-build:is-available.rs
8+
extern crate is_available;
9+
10+
fn main() {
11+
let a = proc_macro::is_available();
12+
let b = is_available::from_inside_proc_macro!();
13+
let c = proc_macro::is_available();
14+
assert!(!a);
15+
assert!(b);
16+
assert!(!c);
17+
}

0 commit comments

Comments
 (0)