diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index acb52480..aca27cd3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,6 +40,7 @@ jobs: - run: cargo test --no-default-features - run: cargo test --no-default-features -- --ignored # run the ignored test to make sure the `proc-macro` feature is disabled - run: cargo test --features span-locations + - run: cargo test --features hygiene - run: RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test - run: RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features - run: RUSTFLAGS='-Z allow-features=' cargo test diff --git a/Cargo.toml b/Cargo.toml index 2c1ee240..779dc496 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,8 @@ default = ["proc-macro"] # of a token. span-locations = [] +hygiene = [] + # This feature no longer means anything. nightly = [] diff --git a/build.rs b/build.rs index deb9b927..5b0ce674 100644 --- a/build.rs +++ b/build.rs @@ -57,6 +57,10 @@ fn main() { println!("cargo:rustc-cfg=span_locations"); } + if semver_exempt || cfg!(feature = "hygiene") { + println!("cargo:rustc-cfg=hygiene"); + } + let target = env::var("TARGET").unwrap(); if !enable_use_proc_macro(&target) { return; diff --git a/src/fallback.rs b/src/fallback.rs index fffea68f..554c87ea 100644 --- a/src/fallback.rs +++ b/src/fallback.rs @@ -374,6 +374,11 @@ impl Span { Span { lo: 0, hi: 0 } } + #[cfg(hygiene)] + pub fn mixed_site() -> Span { + Span::call_site() + } + #[cfg(procmacro2_semver_exempt)] pub fn def_site() -> Span { Span::call_site() diff --git a/src/lib.rs b/src/lib.rs index 23b2c266..4deb30bb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -348,6 +348,18 @@ impl Span { Span::_new(imp::Span::call_site()) } + /// The span located at the invocation of the procedural macro, but with + /// local variables, labels, and `$crate` resolved at the definition site + /// of the macro. + /// + /// `macro_rules` behaves like this in terms of hygiene. + /// + /// This method requires the `"hygiene"` feature to be enabled. + #[cfg(hygiene)] + pub fn mixed_site() -> Span { + Span::_new(imp::Span::mixed_site()) + } + /// A span that resolves at the macro definition site. /// /// This method is semver exempt and not exposed by default. diff --git a/src/wrapper.rs b/src/wrapper.rs index 1887d8e2..f9429b7b 100644 --- a/src/wrapper.rs +++ b/src/wrapper.rs @@ -376,6 +376,15 @@ impl Span { } } + #[cfg(hygiene)] + pub fn mixed_site() -> Span { + if inside_proc_macro() { + Span::Compiler(proc_macro::Span::mixed_site()) + } else { + Span::Fallback(fallback::Span::mixed_site()) + } + } + #[cfg(super_unstable)] pub fn def_site() -> Span { if inside_proc_macro() {