From 9e3896db2826c82666e50a07de25c606fe1fcddc Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Tue, 19 May 2020 08:56:16 -0700 Subject: [PATCH 1/2] Add `Span::mixed_site()` for Rust 1.45+ Fixes #210 This was stabilized in Rust in https://github.com/rust-lang/rust/pull/68716 --- build.rs | 4 ++++ src/fallback.rs | 5 +++++ src/lib.rs | 10 ++++++++++ src/wrapper.rs | 9 +++++++++ 4 files changed, 28 insertions(+) diff --git a/build.rs b/build.rs index deb9b927..a06f009c 100644 --- a/build.rs +++ b/build.rs @@ -57,6 +57,10 @@ fn main() { println!("cargo:rustc-cfg=span_locations"); } + if version.minor >= 45 { + 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..725e1214 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -348,6 +348,16 @@ 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. This is the same hygiene behavior as `macro_rules`. + /// + /// This function requires Rust 1.45 or later. + #[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() { From 9b4633b991609a40c104f259222ad90295656863 Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Tue, 19 May 2020 09:11:12 -0700 Subject: [PATCH 2/2] Stabilize Span::resolved_at + Span::located_at with fallback On compilers prior to 1.45 where this is not stable, these fall back to returning the span associated with resolution behavior, since the source location is only cosmetic. This is a reversal of the previous fallback implementation, which preserved source location because it does not track resolution location. The differnce is only observable with `span_locations` enabled. These methods were stabilized in Rust in https://github.com/rust-lang/rust/pull/69041 --- build.rs | 4 ++++ src/fallback.rs | 13 ++++--------- src/lib.rs | 8 ++++---- src/wrapper.rs | 14 ++++++++++++-- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/build.rs b/build.rs index a06f009c..89e2ab39 100644 --- a/build.rs +++ b/build.rs @@ -14,6 +14,10 @@ // procmacro2_semver_exempt surface area is implemented by using the // nightly-only proc_macro API. // +// "hygiene" +// Enable Span::mixed_site() and non-dummy behavior of Span::resolved_at +// and Span::located_at. Enabled on Rust 1.45+. +// // "proc_macro_span" // Enable non-dummy behavior of Span::start and Span::end methods which // requires an unstable compiler feature. Enabled when building with diff --git a/src/fallback.rs b/src/fallback.rs index 554c87ea..eac975f2 100644 --- a/src/fallback.rs +++ b/src/fallback.rs @@ -384,17 +384,12 @@ impl Span { Span::call_site() } - #[cfg(procmacro2_semver_exempt)] - pub fn resolved_at(&self, _other: Span) -> Span { - // Stable spans consist only of line/column information, so - // `resolved_at` and `located_at` only select which span the - // caller wants line/column information from. - *self + pub fn resolved_at(&self, other: Span) -> Span { + other } - #[cfg(procmacro2_semver_exempt)] - pub fn located_at(&self, other: Span) -> Span { - other + pub fn located_at(&self, _other: Span) -> Span { + *self } #[cfg(procmacro2_semver_exempt)] diff --git a/src/lib.rs b/src/lib.rs index 725e1214..98ba5950 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -369,8 +369,8 @@ impl Span { /// Creates a new span with the same line/column information as `self` but /// that resolves symbols as though it were at `other`. /// - /// This method is semver exempt and not exposed by default. - #[cfg(procmacro2_semver_exempt)] + /// On versions of Rust prior to 1.45, this returns `other` to preserve the + /// name resolution behavior while discarding location information. pub fn resolved_at(&self, other: Span) -> Span { Span::_new(self.inner.resolved_at(other.inner)) } @@ -378,8 +378,8 @@ impl Span { /// Creates a new span with the same name resolution behavior as `self` but /// with the line/column information of `other`. /// - /// This method is semver exempt and not exposed by default. - #[cfg(procmacro2_semver_exempt)] + /// On versions of Rust prior to 1.45, this returns `self` to preserve the + /// name resolution behavior while discarding location information. pub fn located_at(&self, other: Span) -> Span { Span::_new(self.inner.located_at(other.inner)) } diff --git a/src/wrapper.rs b/src/wrapper.rs index f9429b7b..32c71fad 100644 --- a/src/wrapper.rs +++ b/src/wrapper.rs @@ -394,19 +394,29 @@ impl Span { } } - #[cfg(super_unstable)] pub fn resolved_at(&self, other: Span) -> Span { match (self, other) { + #[cfg(hygiene)] (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)), + + // Name resolution affects semantics, but location is only cosmetic + #[cfg(not(hygiene))] + (Span::Compiler(_), Span::Compiler(_)) => other, + (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)), _ => mismatch(), } } - #[cfg(super_unstable)] pub fn located_at(&self, other: Span) -> Span { match (self, other) { + #[cfg(hygiene)] (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)), + + // Name resolution affects semantics, but location is only cosmetic + #[cfg(not(hygiene))] + (Span::Compiler(_), Span::Compiler(_)) => *self, + (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)), _ => mismatch(), }