Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 34 additions & 20 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ fn main() {
println!("cargo:rustc-check-cfg=cfg(no_literal_c_string)");
println!("cargo:rustc-check-cfg=cfg(no_source_text)");
println!("cargo:rustc-check-cfg=cfg(proc_macro_span)");
println!("cargo:rustc-check-cfg=cfg(proc_macro_span_location)");
println!("cargo:rustc-check-cfg=cfg(procmacro2_backtrace)");
println!("cargo:rustc-check-cfg=cfg(procmacro2_build_probe)");
println!("cargo:rustc-check-cfg=cfg(procmacro2_nightly_testing)");
Expand Down Expand Up @@ -68,18 +69,16 @@ fn main() {
return;
}

println!("cargo:rerun-if-changed=src/probe/proc_macro_span.rs");

let proc_macro_span;
let consider_rustc_bootstrap;
if compile_probe(false) {
if compile_probe_unstable("proc_macro_span", false) {
// This is a nightly or dev compiler, so it supports unstable features
// regardless of RUSTC_BOOTSTRAP. No need to rerun build script if
// RUSTC_BOOTSTRAP is changed.
proc_macro_span = true;
consider_rustc_bootstrap = false;
} else if let Some(rustc_bootstrap) = env::var_os("RUSTC_BOOTSTRAP") {
if compile_probe(true) {
if compile_probe_unstable("proc_macro_span", true) {
// This is a stable or beta compiler for which the user has set
// RUSTC_BOOTSTRAP to turn on unstable features. Rerun build script
// if they change it.
Expand Down Expand Up @@ -116,13 +115,19 @@ fn main() {
}

if proc_macro_span {
// Enable non-dummy behavior of Span::start and Span::end methods which
// requires an unstable compiler feature. Enabled when building with
// nightly, unless `-Z allow-feature` in RUSTFLAGS disallows unstable
// features.
// Enable non-dummy behavior of Span::byte_range and Span::join methods
// which requires an unstable compiler feature. Enabled when building
// with nightly, unless `-Z allow-feature` in RUSTFLAGS disallows
// unstable features.
println!("cargo:rustc-cfg=proc_macro_span");
}

if proc_macro_span || (rustc >= 88 && compile_probe_stable("proc_macro_span_location")) {
// Enable non-dummy behavior of Span::start and Span::end methods on
// Rust 1.88+.
println!("cargo:rustc-cfg=proc_macro_span_location");
}

if semver_exempt && proc_macro_span {
// Implement the semver exempt API in terms of the nightly-only
// proc_macro API.
Expand All @@ -134,22 +139,31 @@ fn main() {
}
}

fn compile_probe(rustc_bootstrap: bool) -> bool {
if env::var_os("RUSTC_STAGE").is_some() {
// We are running inside rustc bootstrap. This is a highly non-standard
// environment with issues such as:
//
// https://github.com/rust-lang/cargo/issues/11138
// https://github.com/rust-lang/rust/issues/114839
//
// Let's just not use nightly features here.
return false;
}
fn compile_probe_unstable(feature: &str, rustc_bootstrap: bool) -> bool {
// RUSTC_STAGE indicates that this crate is being compiled as a dependency
// of a multistage rustc bootstrap. This environment uses Cargo in a highly
// non-standard way with issues such as:
//
// https://github.com/rust-lang/cargo/issues/11138
// https://github.com/rust-lang/rust/issues/114839
//
env::var_os("RUSTC_STAGE").is_none() && do_compile_probe(feature, rustc_bootstrap)
}

fn compile_probe_stable(feature: &str) -> bool {
env::var_os("RUSTC_STAGE").is_some() || do_compile_probe(feature, true)
}

fn do_compile_probe(feature: &str, rustc_bootstrap: bool) -> bool {
println!("cargo:rerun-if-changed=src/probe/{}.rs", feature);

let rustc = cargo_env_var("RUSTC");
let out_dir = cargo_env_var("OUT_DIR");
let out_subdir = Path::new(&out_dir).join("probe");
let probefile = Path::new("src").join("probe").join("proc_macro_span.rs");
let probefile = Path::new("src")
.join("probe")
.join(feature)
.with_extension("rs");

if let Err(err) = fs::create_dir(&out_subdir) {
if err.kind() != ErrorKind::AlreadyExists {
Expand Down
3 changes: 3 additions & 0 deletions src/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

#[cfg(proc_macro_span)]
pub(crate) mod proc_macro_span;

#[cfg(proc_macro_span_location)]
pub(crate) mod proc_macro_span_location;
21 changes: 21 additions & 0 deletions src/probe/proc_macro_span_location.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// The subset of Span's API stabilized in Rust 1.88.

extern crate proc_macro;

use proc_macro::Span;

pub fn start(this: &Span) -> Span {
this.start()
}

pub fn end(this: &Span) -> Span {
this.end()
}

pub fn line(this: &Span) -> usize {
this.line()
}

pub fn column(this: &Span) -> usize {
this.column()
}
20 changes: 11 additions & 9 deletions src/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use crate::fallback::{self, FromStr2 as _};
use crate::location::LineColumn;
#[cfg(proc_macro_span)]
use crate::probe::proc_macro_span;
#[cfg(all(span_locations, proc_macro_span_location))]
use crate::probe::proc_macro_span_location;
use crate::{Delimiter, Punct, Spacing, TokenTree};
use core::fmt::{self, Debug, Display};
#[cfg(span_locations)]
Expand Down Expand Up @@ -433,12 +435,12 @@ impl Span {
#[cfg(span_locations)]
pub(crate) fn start(&self) -> LineColumn {
match self {
#[cfg(proc_macro_span)]
#[cfg(proc_macro_span_location)]
Span::Compiler(s) => LineColumn {
line: proc_macro_span::line(s),
column: proc_macro_span::column(s).saturating_sub(1),
line: proc_macro_span_location::line(s),
column: proc_macro_span_location::column(s).saturating_sub(1),
},
#[cfg(not(proc_macro_span))]
#[cfg(not(proc_macro_span_location))]
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
Span::Fallback(s) => s.start(),
}
Expand All @@ -447,15 +449,15 @@ impl Span {
#[cfg(span_locations)]
pub(crate) fn end(&self) -> LineColumn {
match self {
#[cfg(proc_macro_span)]
#[cfg(proc_macro_span_location)]
Span::Compiler(s) => {
let end = proc_macro_span::end(s);
let end = proc_macro_span_location::end(s);
LineColumn {
line: proc_macro_span::line(&end),
column: proc_macro_span::column(&end).saturating_sub(1),
line: proc_macro_span_location::line(&end),
column: proc_macro_span_location::column(&end).saturating_sub(1),
}
}
#[cfg(not(proc_macro_span))]
#[cfg(not(proc_macro_span_location))]
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
Span::Fallback(s) => s.end(),
}
Expand Down