aboutsummaryrefslogtreecommitdiff
path: root/rustversion/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rustversion/src/lib.rs')
-rw-r--r--rustversion/src/lib.rs254
1 files changed, 0 insertions, 254 deletions
diff --git a/rustversion/src/lib.rs b/rustversion/src/lib.rs
deleted file mode 100644
index cf8ed21..0000000
--- a/rustversion/src/lib.rs
+++ /dev/null
@@ -1,254 +0,0 @@
-//! 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
-//!
-//! <br>
-//!
-//! # Selectors
-//!
-//! - <p style="margin-left:50px;text-indent:-50px">
-//! <b><code>#[rustversion::stable]</code></b>
-//! —<br>
-//! True on any stable compiler.
-//! </p>
-//!
-//! - <p style="margin-left:50px;text-indent:-50px">
-//! <b><code>#[rustversion::stable(1.34)]</code></b>
-//! —<br>
-//! True on exactly the specified stable compiler.
-//! </p>
-//!
-//! - <p style="margin-left:50px;text-indent:-50px">
-//! <b><code>#[rustversion::beta]</code></b>
-//! —<br>
-//! True on any beta compiler.
-//! </p>
-//!
-//! - <p style="margin-left:50px;text-indent:-50px">
-//! <b><code>#[rustversion::nightly]</code></b>
-//! —<br>
-//! True on any nightly compiler or dev build.
-//! </p>
-//!
-//! - <p style="margin-left:50px;text-indent:-50px">
-//! <b><code>#[rustversion::nightly(2019-01-01)]</code></b>
-//! —<br>
-//! True on exactly one nightly.
-//! </p>
-//!
-//! - <p style="margin-left:50px;text-indent:-50px">
-//! <b><code>#[rustversion::since(1.34)]</code></b>
-//! —<br>
-//! True on that stable release and any later compiler, including beta and
-//! nightly.
-//! </p>
-//!
-//! - <p style="margin-left:50px;text-indent:-50px">
-//! <b><code>#[rustversion::since(2019-01-01)]</code></b>
-//! —<br>
-//! True on that nightly and all newer ones.
-//! </p>
-//!
-//! - <p style="margin-left:50px;text-indent:-50px">
-//! <b><code>#[rustversion::before(</code></b><i>version or date</i><b><code>)]</code></b>
-//! —<br>
-//! Negative of <i>#[rustversion::since(...)]</i>.
-//! </p>
-//!
-//! - <p style="margin-left:50px;text-indent:-50px">
-//! <b><code>#[rustversion::not(</code></b><i>selector</i><b><code>)]</code></b>
-//! —<br>
-//! Negative of any selector; for example <i>#[rustversion::not(nightly)]</i>.
-//! </p>
-//!
-//! - <p style="margin-left:50px;text-indent:-50px">
-//! <b><code>#[rustversion::any(</code></b><i>selectors...</i><b><code>)]</code></b>
-//! —<br>
-//! True if any of the comma-separated selectors is true; for example
-//! <i>#[rustversion::any(stable, beta)]</i>.
-//! </p>
-//!
-//! - <p style="margin-left:50px;text-indent:-50px">
-//! <b><code>#[rustversion::all(</code></b><i>selectors...</i><b><code>)]</code></b>
-//! —<br>
-//! True if all of the comma-separated selectors are true; for example
-//! <i>#[rustversion::all(since(1.31), before(1.34))]</i>.
-//! </p>
-//!
-//! - <p style="margin-left:50px;text-indent:-50px">
-//! <b><code>#[rustversion::attr(</code></b><i>selector</i><b><code>, </code></b><i>attribute</i><b><code>)]</code></b>
-//! —<br>
-//! For conditional inclusion of attributes; analogous to
-//! <code>cfg_attr</code>.
-//! </p>
-//!
-//! <br>
-//!
-//! # Use cases
-//!
-//! Providing additional trait impls as types are stabilized in the standard library
-//! without breaking compatibility with older compilers; in this case Pin\<P\>
-//! 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<P: MyTrait> MyTrait for Pin<P> {
-//! /* ... */
-//! }
-//! ```
-//!
-//! 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::<Six>());
-//! }
-//! ```
-//!
-//! 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
-//! }
-//! ```
-//!
-//! <br>
-
-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<TokenStream> {
- 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<TokenStream> {
- 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
- }))
- }
- }
-}