From 5e20a29b4fdc8a2d442d1093681b396dcb4b816b Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Tue, 7 Jan 2020 11:18:04 +0000 Subject: Add structopt dependency in version 0.3.7 This patch series replaces argparse with structopt in the argument handling code. As a first step, we need structopt as a dependency. Import subrepo structopt/:structopt at efbdda4753592e27bc430fb01f7b9650b2f3174d Import subrepo bitflags/:bitflags at 30668016aca6bd3b02c766e8347e0b4080d4c296 Import subrepo clap/:clap at 784524f7eb193e35f81082cc69454c8c21b948f7 Import subrepo heck/:heck at 093d56fbf001e1506e56dbfa38631d99b1066df1 Import subrepo proc-macro-error/:proc-macro-error at 6c4cfe79a622c5de8ae68557993542be46eacae2 Import subrepo proc-macro2/:proc-macro2 at d5d48eddca4566e5438e8a2cbed4a74e049544de Import subrepo quote/:quote at 727436c6c137b20f0f34dde5d8fda2679b9747ad Import subrepo rustversion/:rustversion at 0c5663313516263059ce9059ef81fc7a1cf655ca Import subrepo syn-mid/:syn-mid at 5d3d85414a9e6674e1857ec22a87b96e04a6851a Import subrepo syn/:syn at e87c27e87f6f4ef8919d0372bdb056d53ef0d8f3 Import subrepo textwrap/:textwrap at abcd618beae3f74841032aa5b53c1086b0a57ca2 Import subrepo unicode-segmentation/:unicode-segmentation at 637c9874c4fe0c205ff27787faf150a40295c6c3 Import subrepo unicode-width/:unicode-width at 3033826f8bf05e82724140a981d5941e48fce393 Import subrepo unicode-xid/:unicode-xid at 4baae9fffb156ba229665b972a9cd5991787ceb7 --- rustversion/src/lib.rs | 254 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 rustversion/src/lib.rs (limited to 'rustversion/src/lib.rs') diff --git a/rustversion/src/lib.rs b/rustversion/src/lib.rs new file mode 100644 index 0000000..cf8ed21 --- /dev/null +++ b/rustversion/src/lib.rs @@ -0,0 +1,254 @@ +//! This crate provides macros for conditional compilation according to rustc +//! compiler version, analogous to [`#[cfg(...)]`][cfg] and +//! [`#[cfg_attr(...)]`][cfg_attr]. +//! +//! [cfg]: https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute +//! [cfg_attr]: https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute +//! +//!
+//! +//! # Selectors +//! +//! -

+//! #[rustversion::stable] +//! —
+//! True on any stable compiler. +//!

+//! +//! -

+//! #[rustversion::stable(1.34)] +//! —
+//! True on exactly the specified stable compiler. +//!

+//! +//! -

+//! #[rustversion::beta] +//! —
+//! True on any beta compiler. +//!

+//! +//! -

+//! #[rustversion::nightly] +//! —
+//! True on any nightly compiler or dev build. +//!

+//! +//! -

+//! #[rustversion::nightly(2019-01-01)] +//! —
+//! True on exactly one nightly. +//!

+//! +//! -

+//! #[rustversion::since(1.34)] +//! —
+//! True on that stable release and any later compiler, including beta and +//! nightly. +//!

+//! +//! -

+//! #[rustversion::since(2019-01-01)] +//! —
+//! True on that nightly and all newer ones. +//!

+//! +//! -

+//! #[rustversion::before(version or date)] +//! —
+//! Negative of #[rustversion::since(...)]. +//!

+//! +//! -

+//! #[rustversion::not(selector)] +//! —
+//! Negative of any selector; for example #[rustversion::not(nightly)]. +//!

+//! +//! -

+//! #[rustversion::any(selectors...)] +//! —
+//! True if any of the comma-separated selectors is true; for example +//! #[rustversion::any(stable, beta)]. +//!

+//! +//! -

+//! #[rustversion::all(selectors...)] +//! —
+//! True if all of the comma-separated selectors are true; for example +//! #[rustversion::all(since(1.31), before(1.34))]. +//!

+//! +//! -

+//! #[rustversion::attr(selector, attribute)] +//! —
+//! For conditional inclusion of attributes; analogous to +//! cfg_attr. +//!

+//! +//!
+//! +//! # Use cases +//! +//! Providing additional trait impls as types are stabilized in the standard library +//! without breaking compatibility with older compilers; in this case Pin\ +//! stabilized in [Rust 1.33][pin]: +//! +//! [pin]: https://blog.rust-lang.org/2019/02/28/Rust-1.33.0.html#pinning +//! +//! ``` +//! # trait MyTrait {} +//! # +//! #[rustversion::since(1.33)] +//! use std::pin::Pin; +//! +//! #[rustversion::since(1.33)] +//! impl MyTrait for Pin

{ +//! /* ... */ +//! } +//! ``` +//! +//! Similar but for language features; the ability to control alignment greater than +//! 1 of packed structs was stabilized in [Rust 1.33][packed]. +//! +//! [packed]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1330-2019-02-28 +//! +//! ``` +//! #[rustversion::attr(before(1.33), repr(packed))] +//! #[rustversion::attr(since(1.33), repr(packed(2)))] +//! struct Six(i16, i32); +//! +//! fn main() { +//! println!("{}", std::mem::align_of::()); +//! } +//! ``` +//! +//! Augmenting code with `const` as const impls are stabilized in the standard +//! library. This use of `const` as an attribute is recognized as a special case +//! by the rustversion::attr macro. +//! +//! ``` +//! use std::time::Duration; +//! +//! #[rustversion::attr(since(1.32), const)] +//! fn duration_as_days(dur: Duration) -> u64 { +//! dur.as_secs() / 60 / 60 / 24 +//! } +//! ``` +//! +//!
+ +extern crate proc_macro; + +mod attr; +mod bound; +mod date; +mod expr; +mod rustc; +mod time; +mod version; + +use crate::attr::Then; +use crate::expr::Expr; +use proc_macro::TokenStream; +use proc_macro2::{Ident, Span, TokenStream as TokenStream2}; +use quote::quote; +use syn::{parse_macro_input, ItemFn, Result}; + +#[proc_macro_attribute] +pub fn stable(args: TokenStream, input: TokenStream) -> TokenStream { + cfg("stable", args, input) +} + +#[proc_macro_attribute] +pub fn beta(args: TokenStream, input: TokenStream) -> TokenStream { + cfg("beta", args, input) +} + +#[proc_macro_attribute] +pub fn nightly(args: TokenStream, input: TokenStream) -> TokenStream { + cfg("nightly", args, input) +} + +#[proc_macro_attribute] +pub fn since(args: TokenStream, input: TokenStream) -> TokenStream { + cfg("since", args, input) +} + +#[proc_macro_attribute] +pub fn before(args: TokenStream, input: TokenStream) -> TokenStream { + cfg("before", args, input) +} + +#[proc_macro_attribute] +pub fn not(args: TokenStream, input: TokenStream) -> TokenStream { + cfg("not", args, input) +} + +#[proc_macro_attribute] +pub fn any(args: TokenStream, input: TokenStream) -> TokenStream { + cfg("any", args, input) +} + +#[proc_macro_attribute] +pub fn all(args: TokenStream, input: TokenStream) -> TokenStream { + cfg("all", args, input) +} + +fn cfg(top: &str, args: TokenStream, input: TokenStream) -> TokenStream { + match try_cfg(top, args, input) { + Ok(tokens) => tokens, + Err(err) => TokenStream::from(err.to_compile_error()), + } +} + +fn try_cfg(top: &str, args: TokenStream, input: TokenStream) -> Result { + let args = TokenStream2::from(args); + let top = Ident::new(top, Span::call_site()); + + let mut full_args = quote!(#top); + if !args.is_empty() { + full_args.extend(quote!((#args))); + } + + let expr: Expr = syn::parse2(full_args)?; + let version = rustc::version()?; + + if expr.eval(version) { + Ok(input) + } else { + Ok(TokenStream::new()) + } +} + +#[proc_macro_attribute] +pub fn attr(args: TokenStream, input: TokenStream) -> TokenStream { + let args = parse_macro_input!(args as attr::Args); + + match try_attr(args, input) { + Ok(tokens) => tokens, + Err(err) => TokenStream::from(err.to_compile_error()), + } +} + +fn try_attr(args: attr::Args, input: TokenStream) -> Result { + let version = rustc::version()?; + + if !args.condition.eval(version) { + return Ok(input); + } + + match args.then { + Then::Const(const_token) => { + let mut input: ItemFn = syn::parse(input)?; + input.sig.constness = Some(const_token); + Ok(TokenStream::from(quote!(#input))) + } + Then::Attribute(then) => { + let input = TokenStream2::from(input); + Ok(TokenStream::from(quote! { + #[cfg_attr(all(), #then)] + #input + })) + } + } +} -- cgit v1.2.1