Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

35
vendor/rustversion/src/attr.rs vendored Normal file
View 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
vendor/rustversion/src/bound.rs vendored Normal file
View 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.85, 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
vendor/rustversion/src/constfn.rs vendored Normal file
View 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
vendor/rustversion/src/date.rs vendored Normal file
View 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
vendor/rustversion/src/error.rs vendored Normal file
View 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
}),
])
}
}

100
vendor/rustversion/src/expand.rs vendored Normal file
View File

@@ -0,0 +1,100 @@
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(allow_incompatible_msrv(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);
}
let output = match args.then {
Then::Const(const_token) => constfn::insert_const(input, const_token)?,
Then::Attribute(then) => {
TokenStream::from_iter(
// #[cfg_attr(all(), #then)]
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),
)
}
};
Ok(allow_incompatible_msrv(output))
}
fn allow_incompatible_msrv(input: TokenStream) -> TokenStream {
TokenStream::from_iter(
// #[allow(clippy::incompatible_msrv)]
vec![
TokenTree::Punct(Punct::new('#', Spacing::Alone)),
TokenTree::Group(Group::new(
Delimiter::Bracket,
TokenStream::from_iter(vec![
TokenTree::Ident(Ident::new("allow", Span::call_site())),
TokenTree::Group(Group::new(
Delimiter::Parenthesis,
TokenStream::from_iter(vec![
TokenTree::Ident(Ident::new("clippy", Span::call_site())),
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Ident(Ident::new("incompatible_msrv", Span::call_site())),
]),
)),
]),
)),
]
.into_iter()
.chain(input),
)
}

163
vendor/rustversion/src/expr.rs vendored Normal file
View 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
vendor/rustversion/src/iter.rs vendored Normal file
View 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),
}
}
}
}

282
vendor/rustversion/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,282 @@
//! [![github]](https://github.com/dtolnay/rustversion)&ensp;[![crates-io]](https://crates.io/crates/rustversion)&ensp;[![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 style="display:inline">#[rustversion::stable]</code></b>
//! —<br>
//! True on any stable compiler.
//! </p>
//!
//! - <p style="margin-left:50px;text-indent:-50px">
//! <b><code style="display:inline">#[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 style="display:inline">#[rustversion::beta]</code></b>
//! —<br>
//! True on any beta compiler.
//! </p>
//!
//! - <p style="margin-left:50px;text-indent:-50px">
//! <b><code style="display:inline">#[rustversion::nightly]</code></b>
//! —<br>
//! True on any nightly compiler or dev build.
//! </p>
//!
//! - <p style="margin-left:50px;text-indent:-50px">
//! <b><code style="display:inline">#[rustversion::nightly(2025-01-01)]</code></b>
//! —<br>
//! True on exactly one nightly.
//! </p>
//!
//! - <p style="margin-left:50px;text-indent:-50px">
//! <b><code style="display:inline">#[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 style="display:inline">#[rustversion::since(2025-01-01)]</code></b>
//! —<br>
//! True on that nightly and all newer ones.
//! </p>
//!
//! - <p style="margin-left:50px;text-indent:-50px">
//! <b><code style="display:inline">#[rustversion::before(</code></b><i>version or date</i><b><code style="display:inline">)]</code></b>
//! —<br>
//! Negative of <i>#[rustversion::since(...)]</i>.
//! </p>
//!
//! - <p style="margin-left:50px;text-indent:-50px">
//! <b><code style="display:inline">#[rustversion::not(</code></b><i>selector</i><b><code style="display:inline">)]</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 style="display:inline">#[rustversion::any(</code></b><i>selectors...</i><b><code style="display:inline">)]</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 style="display:inline">#[rustversion::all(</code></b><i>selectors...</i><b><code style="display:inline">)]</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 style="display:inline">#[rustversion::attr(</code></b><i>selector</i><b><code style="display:inline">, </code></b><i>attribute</i><b><code style="display:inline">)]</code></b>
//! —<br>
//! For conditional inclusion of attributes; analogous to
//! <code style="display:inline">cfg_attr</code>.
//! </p>
//!
//! - <p style="margin-left:50px;text-indent:-50px">
//! <b><code style="display:inline">rustversion::cfg!(</code></b><i>selector</i><b><code style="display:inline">)</code></b>
//! —<br>
//! An expression form of any of the above attributes; for example
//! <i>if rustversion::cfg!(any(stable, beta)) { ... }</i>.
//! </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
//! }
//! ```
//!
//! Emitting Cargo cfg directives from a build script. Note that this requires
//! listing `rustversion` under `[build-dependencies]` in Cargo.toml, not
//! `[dependencies]`.
//!
//! ```
//! // build.rs
//!
//! fn main() {
//! if rustversion::cfg!(since(1.36)) {
//! println!("cargo:rustc-cfg=no_std");
//! }
//! }
//! ```
//!
//! ```
//! // src/lib.rs
//!
//! #![cfg_attr(no_std, no_std)]
//!
//! #[cfg(no_std)]
//! extern crate alloc;
//! ```
//!
//! <br>
#![doc(html_root_url = "https://docs.rs/rustversion/1.0.22")]
#![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;
#[cfg(not(host_os = "windows"))]
const RUSTVERSION: Version = include!(concat!(env!("OUT_DIR"), "/version.expr"));
#[cfg(host_os = "windows")]
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
vendor/rustversion/src/release.rs vendored Normal file
View 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
vendor/rustversion/src/time.rs vendored Normal file
View 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: 2025,
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
vendor/rustversion/src/token.rs vendored Normal file
View 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
vendor/rustversion/src/version.rs vendored Normal file
View 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,
}