Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
35
third-party/vendor/rustversion/src/attr.rs
vendored
Normal file
35
third-party/vendor/rustversion/src/attr.rs
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
use crate::error::{Error, Result};
|
||||
use crate::expr::{self, Expr};
|
||||
use crate::{iter, token};
|
||||
use proc_macro::{Span, TokenStream};
|
||||
|
||||
pub struct Args {
|
||||
pub condition: Expr,
|
||||
pub then: Then,
|
||||
}
|
||||
|
||||
pub enum Then {
|
||||
Const(Span),
|
||||
Attribute(TokenStream),
|
||||
}
|
||||
|
||||
pub fn parse(input: TokenStream) -> Result<Args> {
|
||||
let ref mut input = iter::new(input);
|
||||
let condition = expr::parse(input)?;
|
||||
|
||||
token::parse_punct(input, ',')?;
|
||||
if input.peek().is_none() {
|
||||
return Err(Error::new(Span::call_site(), "expected one or more attrs"));
|
||||
}
|
||||
|
||||
let const_span = token::parse_optional_keyword(input, "const");
|
||||
let then = if let Some(const_span) = const_span {
|
||||
token::parse_optional_punct(input, ',');
|
||||
token::parse_end(input)?;
|
||||
Then::Const(const_span)
|
||||
} else {
|
||||
Then::Attribute(input.collect())
|
||||
};
|
||||
|
||||
Ok(Args { condition, then })
|
||||
}
|
||||
63
third-party/vendor/rustversion/src/bound.rs
vendored
Normal file
63
third-party/vendor/rustversion/src/bound.rs
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use crate::date::{self, Date};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::iter::Iter;
|
||||
use crate::release::{self, Release};
|
||||
use crate::time;
|
||||
use crate::version::{Channel::*, Version};
|
||||
use proc_macro::{Group, TokenTree};
|
||||
use std::cmp::Ordering;
|
||||
|
||||
pub enum Bound {
|
||||
Nightly(Date),
|
||||
Stable(Release),
|
||||
}
|
||||
|
||||
pub fn parse(paren: Group, iter: Iter) -> Result<Bound> {
|
||||
if let Some(TokenTree::Literal(literal)) = iter.peek() {
|
||||
let repr = literal.to_string();
|
||||
if repr.starts_with(|ch: char| ch.is_ascii_digit()) {
|
||||
if repr.contains('.') {
|
||||
return release::parse(paren, iter).map(Bound::Stable);
|
||||
} else {
|
||||
return date::parse(paren, iter).map(Bound::Nightly);
|
||||
}
|
||||
}
|
||||
}
|
||||
let msg = format!(
|
||||
"expected rustc release number like 1.31, or nightly date like {}",
|
||||
time::today(),
|
||||
);
|
||||
Err(Error::group(paren, msg))
|
||||
}
|
||||
|
||||
impl PartialEq<Bound> for Version {
|
||||
fn eq(&self, rhs: &Bound) -> bool {
|
||||
match rhs {
|
||||
Bound::Nightly(date) => match self.channel {
|
||||
Stable | Beta | Dev => false,
|
||||
Nightly(nightly) => nightly == *date,
|
||||
},
|
||||
Bound::Stable(release) => {
|
||||
self.minor == release.minor
|
||||
&& release.patch.map_or(true, |patch| self.patch == patch)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd<Bound> for Version {
|
||||
fn partial_cmp(&self, rhs: &Bound) -> Option<Ordering> {
|
||||
match rhs {
|
||||
Bound::Nightly(date) => match self.channel {
|
||||
Stable | Beta => Some(Ordering::Less),
|
||||
Nightly(nightly) => Some(nightly.cmp(date)),
|
||||
Dev => Some(Ordering::Greater),
|
||||
},
|
||||
Bound::Stable(release) => {
|
||||
let version = (self.minor, self.patch);
|
||||
let bound = (release.minor, release.patch.unwrap_or(0));
|
||||
Some(version.cmp(&bound))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
third-party/vendor/rustversion/src/constfn.rs
vendored
Normal file
58
third-party/vendor/rustversion/src/constfn.rs
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
use crate::error::{Error, Result};
|
||||
use proc_macro::{Ident, Span, TokenStream, TokenTree};
|
||||
use std::iter;
|
||||
|
||||
#[derive(PartialOrd, PartialEq)]
|
||||
enum Qualifiers {
|
||||
None,
|
||||
Async,
|
||||
Unsafe,
|
||||
Extern,
|
||||
Abi,
|
||||
}
|
||||
|
||||
impl Qualifiers {
|
||||
fn from_ident(ident: &Ident) -> Self {
|
||||
match ident.to_string().as_str() {
|
||||
"async" => Qualifiers::Async,
|
||||
"unsafe" => Qualifiers::Unsafe,
|
||||
"extern" => Qualifiers::Extern,
|
||||
_ => Qualifiers::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn insert_const(input: TokenStream, const_span: Span) -> Result<TokenStream> {
|
||||
let ref mut input = crate::iter::new(input);
|
||||
let mut out = TokenStream::new();
|
||||
let mut qualifiers = Qualifiers::None;
|
||||
let mut pending = Vec::new();
|
||||
|
||||
while let Some(token) = input.next() {
|
||||
match token {
|
||||
TokenTree::Ident(ref ident) if ident.to_string() == "fn" => {
|
||||
let const_ident = Ident::new("const", const_span);
|
||||
out.extend(iter::once(TokenTree::Ident(const_ident)));
|
||||
out.extend(pending);
|
||||
out.extend(iter::once(token));
|
||||
out.extend(input);
|
||||
return Ok(out);
|
||||
}
|
||||
TokenTree::Ident(ref ident) if Qualifiers::from_ident(ident) > qualifiers => {
|
||||
qualifiers = Qualifiers::from_ident(ident);
|
||||
pending.push(token);
|
||||
}
|
||||
TokenTree::Literal(_) if qualifiers == Qualifiers::Extern => {
|
||||
qualifiers = Qualifiers::Abi;
|
||||
pending.push(token);
|
||||
}
|
||||
_ => {
|
||||
qualifiers = Qualifiers::None;
|
||||
out.extend(pending.drain(..));
|
||||
out.extend(iter::once(token));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::new(const_span, "only allowed on a fn item"))
|
||||
}
|
||||
50
third-party/vendor/rustversion/src/date.rs
vendored
Normal file
50
third-party/vendor/rustversion/src/date.rs
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
use crate::error::{Error, Result};
|
||||
use crate::iter::Iter;
|
||||
use crate::{time, token};
|
||||
use proc_macro::Group;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Date {
|
||||
pub year: u16,
|
||||
pub month: u8,
|
||||
pub day: u8,
|
||||
}
|
||||
|
||||
impl Display for Date {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
formatter,
|
||||
"{:04}-{:02}-{:02}",
|
||||
self.year, self.month, self.day,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(paren: Group, iter: Iter) -> Result<Date> {
|
||||
try_parse(iter).map_err(|_| {
|
||||
let msg = format!("expected nightly date, like {}", time::today());
|
||||
Error::group(paren, msg)
|
||||
})
|
||||
}
|
||||
|
||||
fn try_parse(iter: Iter) -> Result<Date, ()> {
|
||||
let year = token::parse_literal(iter).map_err(drop)?;
|
||||
token::parse_punct(iter, '-').map_err(drop)?;
|
||||
let month = token::parse_literal(iter).map_err(drop)?;
|
||||
token::parse_punct(iter, '-').map_err(drop)?;
|
||||
let day = token::parse_literal(iter).map_err(drop)?;
|
||||
|
||||
let year = year.to_string().parse::<u64>().map_err(drop)?;
|
||||
let month = month.to_string().parse::<u64>().map_err(drop)?;
|
||||
let day = day.to_string().parse::<u64>().map_err(drop)?;
|
||||
if year >= 3000 || month > 12 || day > 31 {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
Ok(Date {
|
||||
year: year as u16,
|
||||
month: month as u8,
|
||||
day: day as u8,
|
||||
})
|
||||
}
|
||||
56
third-party/vendor/rustversion/src/error.rs
vendored
Normal file
56
third-party/vendor/rustversion/src/error.rs
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
|
||||
use std::fmt::Display;
|
||||
use std::iter::FromIterator;
|
||||
|
||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||
|
||||
pub struct Error {
|
||||
begin: Span,
|
||||
end: Span,
|
||||
msg: String,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn new(span: Span, msg: impl Display) -> Self {
|
||||
Self::new2(span, span, msg)
|
||||
}
|
||||
|
||||
pub fn new2(begin: Span, end: Span, msg: impl Display) -> Self {
|
||||
Error {
|
||||
begin,
|
||||
end,
|
||||
msg: msg.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn group(group: Group, msg: impl Display) -> Self {
|
||||
let mut iter = group.stream().into_iter();
|
||||
let delimiter = group.span();
|
||||
let begin = iter.next().map_or(delimiter, |t| t.span());
|
||||
let end = iter.last().map_or(begin, |t| t.span());
|
||||
Self::new2(begin, end, msg)
|
||||
}
|
||||
|
||||
pub fn into_compile_error(self) -> TokenStream {
|
||||
// compile_error! { $msg }
|
||||
TokenStream::from_iter(vec![
|
||||
TokenTree::Ident(Ident::new("compile_error", self.begin)),
|
||||
TokenTree::Punct({
|
||||
let mut punct = Punct::new('!', Spacing::Alone);
|
||||
punct.set_span(self.begin);
|
||||
punct
|
||||
}),
|
||||
TokenTree::Group({
|
||||
let mut group = Group::new(Delimiter::Brace, {
|
||||
TokenStream::from_iter(vec![TokenTree::Literal({
|
||||
let mut string = Literal::string(&self.msg);
|
||||
string.set_span(self.end);
|
||||
string
|
||||
})])
|
||||
});
|
||||
group.set_span(self.end);
|
||||
group
|
||||
}),
|
||||
])
|
||||
}
|
||||
}
|
||||
72
third-party/vendor/rustversion/src/expand.rs
vendored
Normal file
72
third-party/vendor/rustversion/src/expand.rs
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
use crate::attr::{self, Then};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::{constfn, expr, iter, token};
|
||||
use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
|
||||
use std::iter::FromIterator;
|
||||
|
||||
pub fn cfg(introducer: &str, args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
try_cfg(introducer, args, input).unwrap_or_else(Error::into_compile_error)
|
||||
}
|
||||
|
||||
fn try_cfg(introducer: &str, args: TokenStream, input: TokenStream) -> Result<TokenStream> {
|
||||
let introducer = Ident::new(introducer, Span::call_site());
|
||||
|
||||
let mut full_args = TokenStream::from(TokenTree::Ident(introducer));
|
||||
if !args.is_empty() {
|
||||
full_args.extend(std::iter::once(TokenTree::Group(Group::new(
|
||||
Delimiter::Parenthesis,
|
||||
args,
|
||||
))));
|
||||
}
|
||||
|
||||
let ref mut full_args = iter::new(full_args);
|
||||
let expr = expr::parse(full_args)?;
|
||||
token::parse_end(full_args)?;
|
||||
|
||||
if expr.eval(crate::RUSTVERSION) {
|
||||
Ok(input)
|
||||
} else {
|
||||
Ok(TokenStream::new())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_attr(args: attr::Args, input: TokenStream) -> Result<TokenStream> {
|
||||
if !args.condition.eval(crate::RUSTVERSION) {
|
||||
return Ok(input);
|
||||
}
|
||||
|
||||
match args.then {
|
||||
Then::Const(const_token) => constfn::insert_const(input, const_token),
|
||||
Then::Attribute(then) => {
|
||||
// #[cfg_attr(all(), #then)]
|
||||
Ok(TokenStream::from_iter(
|
||||
vec![
|
||||
TokenTree::Punct(Punct::new('#', Spacing::Alone)),
|
||||
TokenTree::Group(Group::new(
|
||||
Delimiter::Bracket,
|
||||
TokenStream::from_iter(vec![
|
||||
TokenTree::Ident(Ident::new("cfg_attr", Span::call_site())),
|
||||
TokenTree::Group(Group::new(
|
||||
Delimiter::Parenthesis,
|
||||
TokenStream::from_iter(
|
||||
vec![
|
||||
TokenTree::Ident(Ident::new("all", Span::call_site())),
|
||||
TokenTree::Group(Group::new(
|
||||
Delimiter::Parenthesis,
|
||||
TokenStream::new(),
|
||||
)),
|
||||
TokenTree::Punct(Punct::new(',', Spacing::Alone)),
|
||||
]
|
||||
.into_iter()
|
||||
.chain(then),
|
||||
),
|
||||
)),
|
||||
]),
|
||||
)),
|
||||
]
|
||||
.into_iter()
|
||||
.chain(input),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
163
third-party/vendor/rustversion/src/expr.rs
vendored
Normal file
163
third-party/vendor/rustversion/src/expr.rs
vendored
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
use crate::bound::{self, Bound};
|
||||
use crate::date::{self, Date};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::iter::{self, Iter};
|
||||
use crate::release::{self, Release};
|
||||
use crate::token;
|
||||
use crate::version::{Channel, Version};
|
||||
use proc_macro::{Ident, Span, TokenTree};
|
||||
|
||||
pub enum Expr {
|
||||
Stable,
|
||||
Beta,
|
||||
Nightly,
|
||||
Date(Date),
|
||||
Since(Bound),
|
||||
Before(Bound),
|
||||
Release(Release),
|
||||
Not(Box<Expr>),
|
||||
Any(Vec<Expr>),
|
||||
All(Vec<Expr>),
|
||||
}
|
||||
|
||||
impl Expr {
|
||||
pub fn eval(&self, rustc: Version) -> bool {
|
||||
use self::Expr::*;
|
||||
|
||||
match self {
|
||||
Stable => rustc.channel == Channel::Stable,
|
||||
Beta => rustc.channel == Channel::Beta,
|
||||
Nightly => match rustc.channel {
|
||||
Channel::Nightly(_) | Channel::Dev => true,
|
||||
Channel::Stable | Channel::Beta => false,
|
||||
},
|
||||
Date(date) => match rustc.channel {
|
||||
Channel::Nightly(rustc) => rustc == *date,
|
||||
Channel::Stable | Channel::Beta | Channel::Dev => false,
|
||||
},
|
||||
Since(bound) => rustc >= *bound,
|
||||
Before(bound) => rustc < *bound,
|
||||
Release(release) => {
|
||||
rustc.channel == Channel::Stable
|
||||
&& rustc.minor == release.minor
|
||||
&& release.patch.map_or(true, |patch| rustc.patch == patch)
|
||||
}
|
||||
Not(expr) => !expr.eval(rustc),
|
||||
Any(exprs) => exprs.iter().any(|e| e.eval(rustc)),
|
||||
All(exprs) => exprs.iter().all(|e| e.eval(rustc)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(iter: Iter) -> Result<Expr> {
|
||||
match &iter.next() {
|
||||
Some(TokenTree::Ident(i)) if i.to_string() == "stable" => parse_stable(iter),
|
||||
Some(TokenTree::Ident(i)) if i.to_string() == "beta" => Ok(Expr::Beta),
|
||||
Some(TokenTree::Ident(i)) if i.to_string() == "nightly" => parse_nightly(iter),
|
||||
Some(TokenTree::Ident(i)) if i.to_string() == "since" => parse_since(i, iter),
|
||||
Some(TokenTree::Ident(i)) if i.to_string() == "before" => parse_before(i, iter),
|
||||
Some(TokenTree::Ident(i)) if i.to_string() == "not" => parse_not(i, iter),
|
||||
Some(TokenTree::Ident(i)) if i.to_string() == "any" => parse_any(i, iter),
|
||||
Some(TokenTree::Ident(i)) if i.to_string() == "all" => parse_all(i, iter),
|
||||
unexpected => {
|
||||
let span = unexpected
|
||||
.as_ref()
|
||||
.map_or_else(Span::call_site, TokenTree::span);
|
||||
Err(Error::new(span, "expected one of `stable`, `beta`, `nightly`, `since`, `before`, `not`, `any`, `all`"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_nightly(iter: Iter) -> Result<Expr> {
|
||||
let paren = match token::parse_optional_paren(iter) {
|
||||
Some(group) => group,
|
||||
None => return Ok(Expr::Nightly),
|
||||
};
|
||||
|
||||
let ref mut inner = iter::new(paren.stream());
|
||||
let date = date::parse(paren, inner)?;
|
||||
token::parse_optional_punct(inner, ',');
|
||||
token::parse_end(inner)?;
|
||||
|
||||
Ok(Expr::Date(date))
|
||||
}
|
||||
|
||||
fn parse_stable(iter: Iter) -> Result<Expr> {
|
||||
let paren = match token::parse_optional_paren(iter) {
|
||||
Some(group) => group,
|
||||
None => return Ok(Expr::Stable),
|
||||
};
|
||||
|
||||
let ref mut inner = iter::new(paren.stream());
|
||||
let release = release::parse(paren, inner)?;
|
||||
token::parse_optional_punct(inner, ',');
|
||||
token::parse_end(inner)?;
|
||||
|
||||
Ok(Expr::Release(release))
|
||||
}
|
||||
|
||||
fn parse_since(introducer: &Ident, iter: Iter) -> Result<Expr> {
|
||||
let paren = token::parse_paren(introducer, iter)?;
|
||||
|
||||
let ref mut inner = iter::new(paren.stream());
|
||||
let bound = bound::parse(paren, inner)?;
|
||||
token::parse_optional_punct(inner, ',');
|
||||
token::parse_end(inner)?;
|
||||
|
||||
Ok(Expr::Since(bound))
|
||||
}
|
||||
|
||||
fn parse_before(introducer: &Ident, iter: Iter) -> Result<Expr> {
|
||||
let paren = token::parse_paren(introducer, iter)?;
|
||||
|
||||
let ref mut inner = iter::new(paren.stream());
|
||||
let bound = bound::parse(paren, inner)?;
|
||||
token::parse_optional_punct(inner, ',');
|
||||
token::parse_end(inner)?;
|
||||
|
||||
Ok(Expr::Before(bound))
|
||||
}
|
||||
|
||||
fn parse_not(introducer: &Ident, iter: Iter) -> Result<Expr> {
|
||||
let paren = token::parse_paren(introducer, iter)?;
|
||||
|
||||
let ref mut inner = iter::new(paren.stream());
|
||||
let expr = self::parse(inner)?;
|
||||
token::parse_optional_punct(inner, ',');
|
||||
token::parse_end(inner)?;
|
||||
|
||||
Ok(Expr::Not(Box::new(expr)))
|
||||
}
|
||||
|
||||
fn parse_any(introducer: &Ident, iter: Iter) -> Result<Expr> {
|
||||
let paren = token::parse_paren(introducer, iter)?;
|
||||
|
||||
let ref mut inner = iter::new(paren.stream());
|
||||
let exprs = parse_comma_separated(inner)?;
|
||||
|
||||
Ok(Expr::Any(exprs.into_iter().collect()))
|
||||
}
|
||||
|
||||
fn parse_all(introducer: &Ident, iter: Iter) -> Result<Expr> {
|
||||
let paren = token::parse_paren(introducer, iter)?;
|
||||
|
||||
let ref mut inner = iter::new(paren.stream());
|
||||
let exprs = parse_comma_separated(inner)?;
|
||||
|
||||
Ok(Expr::All(exprs.into_iter().collect()))
|
||||
}
|
||||
|
||||
fn parse_comma_separated(iter: Iter) -> Result<Vec<Expr>> {
|
||||
let mut exprs = Vec::new();
|
||||
|
||||
while iter.peek().is_some() {
|
||||
let expr = self::parse(iter)?;
|
||||
exprs.push(expr);
|
||||
if iter.peek().is_none() {
|
||||
break;
|
||||
}
|
||||
token::parse_punct(iter, ',')?;
|
||||
}
|
||||
|
||||
Ok(exprs)
|
||||
}
|
||||
42
third-party/vendor/rustversion/src/iter.rs
vendored
Normal file
42
third-party/vendor/rustversion/src/iter.rs
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
use proc_macro::{token_stream, Delimiter, TokenStream, TokenTree};
|
||||
|
||||
pub type Iter<'a> = &'a mut IterImpl;
|
||||
|
||||
pub struct IterImpl {
|
||||
stack: Vec<token_stream::IntoIter>,
|
||||
peeked: Option<TokenTree>,
|
||||
}
|
||||
|
||||
pub fn new(tokens: TokenStream) -> IterImpl {
|
||||
IterImpl {
|
||||
stack: vec![tokens.into_iter()],
|
||||
peeked: None,
|
||||
}
|
||||
}
|
||||
|
||||
impl IterImpl {
|
||||
pub fn peek(&mut self) -> Option<&TokenTree> {
|
||||
self.peeked = self.next();
|
||||
self.peeked.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for IterImpl {
|
||||
type Item = TokenTree;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(tt) = self.peeked.take() {
|
||||
return Some(tt);
|
||||
}
|
||||
loop {
|
||||
let top = self.stack.last_mut()?;
|
||||
match top.next() {
|
||||
None => drop(self.stack.pop()),
|
||||
Some(TokenTree::Group(ref group)) if group.delimiter() == Delimiter::None => {
|
||||
self.stack.push(group.stream().into_iter());
|
||||
}
|
||||
Some(tt) => return Some(tt),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
248
third-party/vendor/rustversion/src/lib.rs
vendored
Normal file
248
third-party/vendor/rustversion/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
//! [![github]](https://github.com/dtolnay/rustversion) [![crates-io]](https://crates.io/crates/rustversion) [![docs-rs]](https://docs.rs/rustversion)
|
||||
//!
|
||||
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
|
||||
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
|
||||
//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! 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>
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/rustversion/1.0.14")]
|
||||
#![allow(
|
||||
clippy::cast_lossless,
|
||||
clippy::cast_possible_truncation,
|
||||
clippy::derive_partial_eq_without_eq,
|
||||
clippy::doc_markdown,
|
||||
clippy::enum_glob_use,
|
||||
clippy::from_iter_instead_of_collect,
|
||||
// https://github.com/rust-lang/rust-clippy/issues/8539
|
||||
clippy::iter_with_drain,
|
||||
clippy::module_name_repetitions,
|
||||
clippy::must_use_candidate,
|
||||
clippy::needless_doctest_main,
|
||||
clippy::needless_pass_by_value,
|
||||
clippy::redundant_else,
|
||||
clippy::toplevel_ref_arg,
|
||||
clippy::unreadable_literal
|
||||
)]
|
||||
|
||||
extern crate proc_macro;
|
||||
|
||||
mod attr;
|
||||
mod bound;
|
||||
mod constfn;
|
||||
mod date;
|
||||
mod error;
|
||||
mod expand;
|
||||
mod expr;
|
||||
mod iter;
|
||||
mod release;
|
||||
mod time;
|
||||
mod token;
|
||||
mod version;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::version::Version;
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
const RUSTVERSION: Version = include!(concat!(env!("OUT_DIR"), "/version.expr"));
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn stable(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
expand::cfg("stable", args, input)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn beta(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
expand::cfg("beta", args, input)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn nightly(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
expand::cfg("nightly", args, input)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn since(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
expand::cfg("since", args, input)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn before(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
expand::cfg("before", args, input)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn not(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
expand::cfg("not", args, input)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn any(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
expand::cfg("any", args, input)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn all(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
expand::cfg("all", args, input)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn attr(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
attr::parse(args)
|
||||
.and_then(|args| expand::try_attr(args, input))
|
||||
.unwrap_or_else(Error::into_compile_error)
|
||||
}
|
||||
|
||||
#[cfg(not(cfg_macro_not_allowed))]
|
||||
#[proc_macro]
|
||||
pub fn cfg(input: TokenStream) -> TokenStream {
|
||||
use proc_macro::{Ident, Span, TokenTree};
|
||||
(|| {
|
||||
let ref mut args = iter::new(input);
|
||||
let expr = expr::parse(args)?;
|
||||
token::parse_end(args)?;
|
||||
let boolean = expr.eval(RUSTVERSION);
|
||||
let ident = Ident::new(&boolean.to_string(), Span::call_site());
|
||||
Ok(TokenStream::from(TokenTree::Ident(ident)))
|
||||
})()
|
||||
.unwrap_or_else(Error::into_compile_error)
|
||||
}
|
||||
34
third-party/vendor/rustversion/src/release.rs
vendored
Normal file
34
third-party/vendor/rustversion/src/release.rs
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
use crate::error::{Error, Result};
|
||||
use crate::iter::Iter;
|
||||
use crate::token;
|
||||
use proc_macro::Group;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Release {
|
||||
pub minor: u16,
|
||||
pub patch: Option<u16>,
|
||||
}
|
||||
|
||||
pub fn parse(paren: Group, iter: Iter) -> Result<Release> {
|
||||
try_parse(iter).map_err(|_| Error::group(paren, "expected rustc release number, like 1.31"))
|
||||
}
|
||||
|
||||
fn try_parse(iter: Iter) -> Result<Release, ()> {
|
||||
let major_minor = token::parse_literal(iter).map_err(drop)?;
|
||||
let string = major_minor.to_string();
|
||||
|
||||
if !string.starts_with("1.") {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let minor: u16 = string[2..].parse().map_err(drop)?;
|
||||
|
||||
let patch = if token::parse_optional_punct(iter, '.').is_some() {
|
||||
let int = token::parse_literal(iter).map_err(drop)?;
|
||||
Some(int.to_string().parse().map_err(drop)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Release { minor, patch })
|
||||
}
|
||||
51
third-party/vendor/rustversion/src/time.rs
vendored
Normal file
51
third-party/vendor/rustversion/src/time.rs
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
use crate::date::Date;
|
||||
use std::env;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
// Timestamp of 2016-03-01 00:00:00 in UTC.
|
||||
const BASE: u64 = 1456790400;
|
||||
const BASE_YEAR: u16 = 2016;
|
||||
const BASE_MONTH: u8 = 3;
|
||||
|
||||
// Days between leap days.
|
||||
const CYCLE: u64 = 365 * 4 + 1;
|
||||
|
||||
const DAYS_BY_MONTH: [u8; 12] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||||
|
||||
pub fn today() -> Date {
|
||||
let default = Date {
|
||||
year: 2020,
|
||||
month: 2,
|
||||
day: 25,
|
||||
};
|
||||
try_today().unwrap_or(default)
|
||||
}
|
||||
|
||||
fn try_today() -> Option<Date> {
|
||||
if let Some(pkg_name) = env::var_os("CARGO_PKG_NAME") {
|
||||
if pkg_name.to_str() == Some("rustversion-tests") {
|
||||
return None; // Stable date for ui testing.
|
||||
}
|
||||
}
|
||||
|
||||
let now = SystemTime::now();
|
||||
let since_epoch = now.duration_since(UNIX_EPOCH).ok()?;
|
||||
let secs = since_epoch.as_secs();
|
||||
|
||||
let approx_days = secs.checked_sub(BASE)? / 60 / 60 / 24;
|
||||
let cycle = approx_days / CYCLE;
|
||||
let mut rem = approx_days % CYCLE;
|
||||
|
||||
let mut year = BASE_YEAR + cycle as u16 * 4;
|
||||
let mut month = BASE_MONTH;
|
||||
loop {
|
||||
let days_in_month = DAYS_BY_MONTH[month as usize - 1];
|
||||
if rem < days_in_month as u64 {
|
||||
let day = rem as u8 + 1;
|
||||
return Some(Date { year, month, day });
|
||||
}
|
||||
rem -= days_in_month as u64;
|
||||
year += (month == 12) as u16;
|
||||
month = month % 12 + 1;
|
||||
}
|
||||
}
|
||||
78
third-party/vendor/rustversion/src/token.rs
vendored
Normal file
78
third-party/vendor/rustversion/src/token.rs
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
use crate::error::{Error, Result};
|
||||
use crate::iter::Iter;
|
||||
use proc_macro::{Delimiter, Group, Ident, Literal, Span, TokenTree};
|
||||
|
||||
pub fn parse_punct(iter: Iter, ch: char) -> Result<()> {
|
||||
match iter.next() {
|
||||
Some(TokenTree::Punct(ref punct)) if punct.as_char() == ch => Ok(()),
|
||||
unexpected => {
|
||||
let span = unexpected
|
||||
.as_ref()
|
||||
.map_or_else(Span::call_site, TokenTree::span);
|
||||
Err(Error::new(span, format!("expected `{}`", ch)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_optional_punct(iter: Iter, ch: char) -> Option<()> {
|
||||
match iter.peek() {
|
||||
Some(TokenTree::Punct(punct)) if punct.as_char() == ch => iter.next().map(drop),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_optional_keyword(iter: Iter, keyword: &str) -> Option<Span> {
|
||||
match iter.peek() {
|
||||
Some(TokenTree::Ident(ident)) if ident.to_string() == keyword => {
|
||||
Some(iter.next().unwrap().span())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_literal(iter: Iter) -> Result<Literal> {
|
||||
match iter.next() {
|
||||
Some(TokenTree::Literal(literal)) => Ok(literal),
|
||||
unexpected => {
|
||||
let span = unexpected
|
||||
.as_ref()
|
||||
.map_or_else(Span::call_site, TokenTree::span);
|
||||
Err(Error::new(span, "expected literal"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_paren(introducer: &Ident, iter: Iter) -> Result<Group> {
|
||||
match iter.peek() {
|
||||
Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Parenthesis => {
|
||||
match iter.next() {
|
||||
Some(TokenTree::Group(group)) => Ok(group),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
Some(unexpected) => Err(Error::new(unexpected.span(), "expected `(`")),
|
||||
None => Err(Error::new(
|
||||
introducer.span(),
|
||||
format!("expected `(` after `{}`", introducer),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_optional_paren(iter: Iter) -> Option<Group> {
|
||||
match iter.peek() {
|
||||
Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Parenthesis => {
|
||||
match iter.next() {
|
||||
Some(TokenTree::Group(group)) => Some(group),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_end(iter: Iter) -> Result<()> {
|
||||
match iter.next() {
|
||||
None => Ok(()),
|
||||
Some(unexpected) => Err(Error::new(unexpected.span(), "unexpected token")),
|
||||
}
|
||||
}
|
||||
18
third-party/vendor/rustversion/src/version.rs
vendored
Normal file
18
third-party/vendor/rustversion/src/version.rs
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use crate::date::Date;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub struct Version {
|
||||
pub minor: u16,
|
||||
pub patch: u16,
|
||||
pub channel: Channel,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum Channel {
|
||||
Stable,
|
||||
Beta,
|
||||
Nightly(Date),
|
||||
Dev,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue