From c2b6819f4392d3f1f3f0b1d737c9cb83d80488e7 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 29 Aug 2019 11:01:19 +0900 Subject: [PATCH] Detect if the proc_macro_def_site feature is not disallowed by -Zallow-features --- pin-project-internal/build.rs | 27 ++++++++++++++++++--- pin-project-internal/src/lib.rs | 2 +- pin-project-internal/src/pin_project/mod.rs | 6 ++--- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/pin-project-internal/build.rs b/pin-project-internal/build.rs index 0ed72856..1b547f9e 100644 --- a/pin-project-internal/build.rs +++ b/pin-project-internal/build.rs @@ -1,15 +1,36 @@ // Based on https://stackoverflow.com/a/49250753/1290530 +use std::env; + use rustc_version::{version_meta, Channel}; fn main() { // Set cfg flags depending on release channel match version_meta().unwrap().channel { // Enable our feature on nightly, or when using a - // locally build rustc - Channel::Nightly | Channel::Dev => { - println!("cargo:rustc-cfg=feature=\"RUSTC_IS_NIGHTLY\""); + // locally build rustc, unless `-Zallow-features` + // in RUSTFLAGS disallows unstable features. + Channel::Nightly | Channel::Dev if feature_allowed("proc_macro_def_site") => { + println!("cargo:rustc-cfg=proc_macro_def_site"); } _ => {} } } + +// Based on https://github.com/alexcrichton/proc-macro2/pull/176 +fn feature_allowed(feature: &str) -> bool { + if let Some(rustflags) = env::var_os("RUSTFLAGS") { + for mut flag in rustflags.to_string_lossy().split(' ') { + if flag.starts_with("-Z") { + flag = &flag["-Z".len()..]; + } + if flag.starts_with("allow-features=") { + flag = &flag["allow-features=".len()..]; + return flag.split(',').any(|allowed| allowed == feature); + } + } + } + + // No allow-features= flag, allowed by default. + true +} diff --git a/pin-project-internal/src/lib.rs b/pin-project-internal/src/lib.rs index 5c514807..48b519ae 100644 --- a/pin-project-internal/src/lib.rs +++ b/pin-project-internal/src/lib.rs @@ -8,7 +8,7 @@ #![warn(single_use_lifetimes)] #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::use_self)] -#![cfg_attr(feature = "RUSTC_IS_NIGHTLY", feature(proc_macro_def_site))] +#![cfg_attr(proc_macro_def_site, feature(proc_macro_def_site))] extern crate proc_macro; diff --git a/pin-project-internal/src/pin_project/mod.rs b/pin-project-internal/src/pin_project/mod.rs index 61fab439..1ab466a4 100644 --- a/pin-project-internal/src/pin_project/mod.rs +++ b/pin-project-internal/src/pin_project/mod.rs @@ -129,12 +129,12 @@ impl Context { } } else { let make_span = || { - #[cfg(feature = "RUSTC_IS_NIGHTLY")] + #[cfg(proc_macro_def_site)] { proc_macro::Span::def_site().into() } - #[cfg(not(feature = "RUSTC_IS_NIGHTLY"))] + #[cfg(not(proc_macro_def_site))] { Span::call_site() } @@ -229,7 +229,7 @@ impl Context { impl #impl_generics ::core::marker::Unpin for #orig_ident #ty_generics #full_where_clause {} }; - if cfg!(feature = "RUSTC_IS_NIGHTLY") { + if cfg!(proc_macro_def_site) { // On nightly, we use def-site hygiene to make it impossible // for user code to refer to any of the types we define. // This allows us to omit wrapping the generated types