Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Span::mixed_site, Span::resolved_at, and Span::located_at behind hygiene feature #228

Merged
merged 2 commits into from
May 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -57,6 +61,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;
Expand Down
18 changes: 9 additions & 9 deletions src/fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,24 +374,24 @@ impl Span {
Span { lo: 0, hi: 0 }
}

#[cfg(procmacro2_semver_exempt)]
pub fn def_site() -> Span {
#[cfg(hygiene)]
pub fn mixed_site() -> 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 def_site() -> Span {
Span::call_site()
}

#[cfg(procmacro2_semver_exempt)]
pub fn located_at(&self, other: Span) -> Span {
pub fn resolved_at(&self, other: Span) -> Span {
other
}

pub fn located_at(&self, _other: Span) -> Span {
*self
}

#[cfg(procmacro2_semver_exempt)]
pub fn source_file(&self) -> SourceFile {
SOURCE_MAP.with(|cm| {
Expand Down
18 changes: 14 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -359,17 +369,17 @@ 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))
}

/// 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))
}
Expand Down
23 changes: 21 additions & 2 deletions src/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -385,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(),
}
Expand Down