Infer nightly feature on nightly toolchain
Before this commit, enabling procmacro2_semver_exempt would disable
wrap_proc_macro, meaning that real spans would not be preserved by proc
macros. One would also need to enable the "nightly" feature in order to
preserve spans when using procmacro2_semver_exempt.
This commit automatically enables wrap_proc_macro when building with
procmacro2_semver_exempt on a nightly compiler.
diff --git a/.travis.yml b/.travis.yml
index 610f64f..424f5d5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,19 +4,26 @@
matrix:
include:
- rust: 1.15.0 # oldest supported version
- script: cargo build
+ script:
+ - cargo build
+ - cargo build --no-default-features
+ - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build
+ - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build --no-default-features
- rust: 1.19.0 # first release with the --tests flag
- script: cargo test --tests
+ script:
+ - cargo test --tests
+ - cargo test --no-default-features --tests
+ - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --tests
+ - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features --tests
- rust: 1.26.0 # first release on which our doc tests pass
- rust: stable
- rust: beta
- rust: nightly
script:
- cargo test
- - cargo test --features nightly
- cargo test --no-default-features
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
- - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --features nightly
+ - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features
- cargo update -Z minimal-versions && cargo build
- rust: nightly
name: WebAssembly
@@ -28,7 +35,9 @@
script:
- cargo test
+ - cargo test --no-default-features
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
+ - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features
notifications:
email:
diff --git a/Cargo.toml b/Cargo.toml
index a08b98d..dba5c3e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -26,16 +26,12 @@
quote = "0.6"
[features]
-# When enabled: act as a shim around the nightly compiler's proc_macro crate.
-# This requires a nightly compiler.
-#
-# When disabled: emulate the same API as the nightly compiler's proc_macro crate
-# but in a way that works on all stable compilers 1.15+.
-nightly = ["proc-macro"]
-
proc-macro = []
default = ["proc-macro"]
+# This feature no longer means anything.
+nightly = []
+
[badges]
travis-ci = { repository = "alexcrichton/proc-macro2" }
diff --git a/build.rs b/build.rs
index cd6df23..a175711 100644
--- a/build.rs
+++ b/build.rs
@@ -1,3 +1,37 @@
+// rustc-cfg emitted by the build script:
+//
+// "u128"
+// Include u128 and i128 constructors for proc_macro2::Literal. Enabled on
+// any compiler 1.26+.
+//
+// "use_proc_macro"
+// Link to extern crate proc_macro. Available on any compiler and any target
+// except wasm32. Requires "proc-macro" Cargo cfg to be enabled (default is
+// enabled). On wasm32 we never link to proc_macro even if "proc-macro" cfg
+// is enabled.
+//
+// "wrap_proc_macro"
+// Wrap types from libproc_macro rather than polyfilling the whole API.
+// Enabled on rustc 1.29+ as long as procmacro2_semver_exempt is not set,
+// because we can't emulate the unstable API without emulating everything
+// else. Also enabled unconditionally on nightly, in which case the
+// procmacro2_semver_exempt surface area is implemented by using the
+// nightly-only proc_macro API.
+//
+// "slow_extend"
+// Fallback when `impl Extend for TokenStream` is not available. These impls
+// were added one version later than the rest of the proc_macro token API.
+// Enabled on rustc 1.29 only.
+//
+// "nightly"
+// Enable the Span::unstable method. This is to support proc_macro_span and
+// proc_macro_diagnostic use on the nightly channel without requiring the
+// semver exemption opt-in. Enabled when building with nightly.
+//
+// "super_unstable"
+// Implement the semver exempt API in terms of the nightly-only proc_macro
+// API. Enabled when using procmacro2_semver_exempt on a nightly compiler.
+
use std::env;
use std::process::Command;
use std::str;
@@ -7,12 +41,12 @@
let target = env::var("TARGET").unwrap();
- let minor = match rustc_minor_version() {
- Some(n) => n,
+ let version = match rustc_version() {
+ Some(version) => version,
None => return,
};
- if minor >= 26 {
+ if version.minor >= 26 {
println!("cargo:rustc-cfg=u128");
}
@@ -21,20 +55,28 @@
}
println!("cargo:rustc-cfg=use_proc_macro");
- // Rust 1.29 stabilized the necessary APIs in the `proc_macro` crate
- if (minor >= 29 && !cfg!(procmacro2_semver_exempt)) || cfg!(feature = "nightly") {
- println!("cargo:rustc-cfg=wrap_proc_macro");
-
- if cfg!(procmacro2_semver_exempt) {
- println!("cargo:rustc-cfg=super_unstable");
- // https://github.com/alexcrichton/proc-macro2/issues/147
- println!("cargo:rustc-cfg=procmacro2_semver_exempt");
- }
+ let semver_exempt = cfg!(procmacro2_semver_exempt);
+ if semver_exempt {
+ // https://github.com/alexcrichton/proc-macro2/issues/147
+ println!("cargo:rustc-cfg=procmacro2_semver_exempt");
}
- if minor == 29 {
+ // Rust 1.29 stabilized the necessary APIs in the `proc_macro` crate
+ if version.nightly || version.minor >= 29 && !semver_exempt {
+ println!("cargo:rustc-cfg=wrap_proc_macro");
+ }
+
+ if version.minor == 29 {
println!("cargo:rustc-cfg=slow_extend");
}
+
+ if version.nightly {
+ println!("cargo:rustc-cfg=nightly");
+ }
+
+ if semver_exempt && version.nightly {
+ println!("cargo:rustc-cfg=super_unstable");
+ }
}
fn enable_use_proc_macro(target: &str) -> bool {
@@ -47,7 +89,12 @@
cfg!(feature = "proc-macro")
}
-fn rustc_minor_version() -> Option<u32> {
+struct RustcVersion {
+ minor: u32,
+ nightly: bool,
+}
+
+fn rustc_version() -> Option<RustcVersion> {
macro_rules! otry {
($e:expr) => {
match $e {
@@ -56,12 +103,20 @@
}
};
}
+
let rustc = otry!(env::var_os("RUSTC"));
let output = otry!(Command::new(rustc).arg("--version").output().ok());
let version = otry!(str::from_utf8(&output.stdout).ok());
+ let nightly = version.contains("nightly");
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
- otry!(pieces.next()).parse().ok()
+ let minor = otry!(pieces.next());
+ let minor = otry!(minor.parse().ok());
+
+ Some(RustcVersion {
+ minor: minor,
+ nightly: nightly,
+ })
}
diff --git a/src/lib.rs b/src/lib.rs
index db51272..347b937 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -333,9 +333,11 @@
Span::_new(self.inner.located_at(other.inner))
}
- /// This method is only available when the `"nightly"` feature is enabled.
- #[doc(hidden)]
- #[cfg(any(feature = "nightly", super_unstable))]
+ /// Convert `proc_macro2::Span` to `proc_macro::Span`.
+ ///
+ /// This method is available when building with a nightly compiler, or when
+ /// building with rustc 1.29+ *without* semver exempt features.
+ #[cfg(wrap_proc_macro)]
pub fn unstable(self) -> proc_macro::Span {
self.inner.unstable()
}
diff --git a/tests/test.rs b/tests/test.rs
index 9d37cf3..6da1283 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -193,7 +193,7 @@
}
#[cfg(procmacro2_semver_exempt)]
-#[cfg(not(feature = "nightly"))]
+#[cfg(not(nightly))]
#[test]
fn default_span() {
let start = Span::call_site().start();
@@ -329,7 +329,6 @@
}
#[test]
-#[cfg(not(feature = "nightly"))]
fn test_debug_tokenstream() {
let tts = TokenStream::from_str("[a + 1]").unwrap();