Bug 1716518 - Upgrade proc-macro-hack to v0.5.19. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D117837
This commit is contained in:
Mike Hommey 2021-06-15 22:17:28 +00:00
Родитель 478846d726
Коммит efeccaf651
19 изменённых файлов: 858 добавлений и 378 удалений

9
Cargo.lock сгенерированный
Просмотреть файл

@ -3918,14 +3918,9 @@ version = "0.0.1"
[[package]]
name = "proc-macro-hack"
version = "0.5.11"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"f1b283315c58f380d50c15f4017fb388ef166c8ee9c6fbc2503a1d666290d356","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"d59d2723bbc1627b629429a9c779d5dcfde579c9723e6ded1052931c4e8efa0a","README.md":"a4b9c5234ba1e780e1b30957ae0b77c5e018a4fc84e39b2a2dc643e02610ae1c","src/lib.rs":"58aba2a6cd51185be905214eefd4485fe2eef8e52f55c469bda0ccfe63b07c26"},"package":"ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"}
{"files":{"Cargo.toml":"4676ee2135f0167cbdd7abe42349084e0107b9614804caf5049c714170f181ec","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"d59d2723bbc1627b629429a9c779d5dcfde579c9723e6ded1052931c4e8efa0a","README.md":"5b08393db968a3113d81d991365c354dbf7ac84d02f6afbdda99732b80620812","build.rs":"eae956d2a2de606f0c26741fbc849f3c9db89bf14f743d76a452b85c7904860c","src/error.rs":"d31547fe853819b03cf1a485827ceaa7ebffbd45a8d5ef066e94cc862f499583","src/iter.rs":"8d4b817b9abc4e817105b673e15f29ef9bb8284a010ce01ac2d83387fe136947","src/lib.rs":"3a9de3931a57b7673dcee9341823b9ec7a350aae391e987ea74166f495e6dc5a","src/parse.rs":"84901bdb47460286d7ae6840c057a09ffc88906b097da2bcb32056a7190fade7","src/quote.rs":"2f8c5ff5174f8869f4fd317156396be6d90b0af566f44840a2cadb2d1180fb45","tests/compiletest.rs":"0a52a44786aea1c299c695bf948b2ed2081e4cc344e5c2cadceab4eb03d0010d","tests/ui/private.rs":"f58d9fafe29bb624cbd8b2fbfce4e0ba9526d5e7a7bcb4366ebe02a192d742e4","tests/ui/private.stderr":"d0204151ff6347cb5d37bef41879183322dd2ad3749dcb51586e834a605e9d09","tests/ui/unexpected-arg.rs":"27f8baf78620673ce49eb4a376dd2210e446d2fbc33a4160aa72c40f597a599a","tests/ui/unexpected-arg.stderr":"6a380293011f7f4f513d982ad3af0ce0c9629a2284d9bdbdf171badb8af31f77","tests/ui/unexpected.rs":"157afd8323c9226a8f9ac1f1623a7747d8b9563e95b66d0208020d2d15781adc","tests/ui/unexpected.stderr":"2c07c1a739dc889cde323e0a4d337f7c596c928e7b7e479ee27cc4a85b124927","tests/ui/unknown-arg.rs":"724aeb6614c96e925856fb0e73ec38312cc9abc918094188d928e41626fbe512","tests/ui/unknown-arg.stderr":"20fdd8652293733c5edc8a6fb1dc3296094ab98a56fc9cf2e538be2d09703c38"},"package":"dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"}

26
third_party/rust/proc-macro-hack/Cargo.toml поставляемый
Просмотреть файл

@ -13,28 +13,32 @@
[package]
edition = "2018"
name = "proc-macro-hack"
version = "0.5.11"
version = "0.5.19"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "Procedural macros in expression position"
readme = "README.md"
categories = ["development-tools::procedural-macro-helpers"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/dtolnay/proc-macro-hack"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[lib]
proc-macro = true
[dependencies.proc-macro2]
version = "1.0"
[dependencies.quote]
version = "1.0"
[dependencies.syn]
version = "1.0.5"
[dev-dependencies.demo-hack]
version = "0.0.5"
[dev-dependencies.demo-hack-impl]
version = "0.0.5"
[badges.travis-ci]
repository = "dtolnay/proc-macro-hack"
[dev-dependencies.quote]
version = "1.0"
[dev-dependencies.rustversion]
version = "1.0"
[dev-dependencies.syn]
version = "1.0.5"
[dev-dependencies.trybuild]
version = "1.0"

39
third_party/rust/proc-macro-hack/README.md поставляемый
Просмотреть файл

@ -1,17 +1,25 @@
Procedural macros in expression position
========================================
[![Build Status](https://api.travis-ci.org/dtolnay/proc-macro-hack.svg?branch=master)](https://travis-ci.org/dtolnay/proc-macro-hack)
[![Latest Version](https://img.shields.io/crates/v/proc-macro-hack.svg)](https://crates.io/crates/proc-macro-hack)
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/proc--macro--hack-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/proc-macro-hack)
[<img alt="crates.io" src="https://img.shields.io/crates/v/proc-macro-hack.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/proc-macro-hack)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-proc--macro--hack-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/proc-macro-hack)
[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/proc-macro-hack/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/proc-macro-hack/actions?query=branch%3Amaster)
As of Rust 1.30, the language supports user-defined function-like procedural
macros. However these can only be invoked in item position, not in
statements or expressions.
<table><tr><td><hr>
<b>Note:</b> <i>As of Rust 1.45 this crate is superseded by native support for
#[proc_macro] in expression position. Only consider using this crate if you care
about supporting compilers between 1.31 and 1.45.</i>
<hr></td></tr></table>
Since Rust 1.30, the language supports user-defined function-like procedural
macros. However these can only be invoked in item position, not in statements or
expressions.
This crate implements an alternative type of procedural macro that can be
invoked in statement or expression position.
This approach works with any stable or nightly Rust version 1.31+.
This approach works with any Rust version 1.31+.
## Defining procedural macros
@ -22,7 +30,7 @@ Two crates are required to define a procedural macro.
This crate must contain nothing but procedural macros. Private helper
functions and private modules are fine but nothing can be public.
[> example of an implementation crate][demo-hack-impl]
[&raquo; example of an implementation crate][demo-hack-impl]
Just like you would use a #\[proc_macro\] attribute to define a natively
supported procedural macro, use proc-macro-hack's #\[proc_macro_hack\]
@ -31,8 +39,6 @@ The function signature is the same as for ordinary function-like procedural
macros.
```rust
extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro_hack::proc_macro_hack;
use quote::quote;
@ -52,7 +58,7 @@ pub fn add_one(input: TokenStream) -> TokenStream {
This crate is allowed to contain other public things if you need, for
example traits or functions or ordinary macros.
[> example of a declaration crate][demo-hack]
[&raquo; example of a declaration crate][demo-hack]
Within the declaration crate there needs to be a re-export of your
procedural macro from the implementation crate. The re-export also carries a
@ -88,7 +94,7 @@ proc-macro = true
Users of your crate depend on your declaration crate (not your
implementation crate), then use your procedural macros as usual.
[> example of a downstream crate][example]
[&raquo; example of a downstream crate][example]
```rust
use demo_hack::add_one;
@ -106,8 +112,8 @@ fn main() {
## Limitations
- Only proc macros in expression position are supported. Proc macros in type
position ([#10]) or pattern position ([#20]) are not supported.
- Only proc macros in expression position are supported. Proc macros in pattern
position ([#20]) are not supported.
- By default, nested invocations are not supported i.e. the code emitted by a
proc-macro-hack macro invocation cannot contain recursive calls to the same
@ -120,6 +126,13 @@ fn main() {
macro input, use `#[proc_macro_hack(fake_call_site)]` on the re-export in your
declaration crate. *Most macros won't need this.*
- On compilers that are new enough to natively support proc macros in expression
position, proc-macro-hack does not automatically use that support, since the
hygiene can be subtly different between the two implementations. To opt in to
compiling your macro to native `#[proc_macro]` on sufficiently new compilers,
use `#[proc_macro_hack(only_hack_old_rustc)]` on the re-export in your
declaration crate.
[#10]: https://github.com/dtolnay/proc-macro-hack/issues/10
[#20]: https://github.com/dtolnay/proc-macro-hack/issues/20
[`proc-macro-nested`]: https://docs.rs/proc-macro-nested

31
third_party/rust/proc-macro-hack/build.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,31 @@
use std::env;
use std::process::Command;
use std::str;
// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
let minor = match rustc_minor_version() {
Some(minor) => minor,
None => return,
};
// Function-like procedural macros in expressions, patterns, and statements
// stabilized in Rust 1.45:
// https://blog.rust-lang.org/2020/07/16/Rust-1.45.0.html#stabilizing-function-like-procedural-macros-in-expressions-patterns-and-statements
if minor < 45 {
println!("cargo:rustc-cfg=need_proc_macro_hack");
}
}
fn rustc_minor_version() -> Option<u32> {
let rustc = env::var_os("RUSTC")?;
let output = Command::new(rustc).arg("--version").output().ok()?;
let version = str::from_utf8(&output.stdout).ok()?;
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
pieces.next()?.parse().ok()
}

39
third_party/rust/proc-macro-hack/src/error.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,39 @@
use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
use std::iter::FromIterator;
pub struct Error {
span: Span,
msg: String,
}
impl Error {
pub fn new(span: Span, msg: impl Into<String>) -> Self {
Error {
span,
msg: msg.into(),
}
}
}
pub fn compile_error(err: Error) -> TokenStream {
// compile_error!($msg)
TokenStream::from_iter(vec![
TokenTree::Ident(Ident::new("compile_error", err.span)),
TokenTree::Punct({
let mut punct = Punct::new('!', Spacing::Alone);
punct.set_span(err.span);
punct
}),
TokenTree::Group({
let mut group = Group::new(Delimiter::Brace, {
TokenStream::from_iter(vec![TokenTree::Literal({
let mut string = Literal::string(&err.msg);
string.set_span(err.span);
string
})])
});
group.set_span(err.span);
group
}),
])
}

42
third_party/rust/proc-macro-hack/src/iter.rs поставляемый 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),
}
}
}
}

626
third_party/rust/proc-macro-hack/src/lib.rs поставляемый
Просмотреть файл

@ -1,4 +1,18 @@
//! As of Rust 1.30, the language supports user-defined function-like procedural
//! [![github]](https://github.com/dtolnay/proc-macro-hack)&ensp;[![crates-io]](https://crates.io/crates/proc-macro-hack)&ensp;[![docs-rs]](https://docs.rs/proc-macro-hack)
//!
//! [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&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
//!
//! <br>
//!
//! <table><tr><td><hr>
//! <b>Note:</b> <i>As of Rust 1.45 this crate is superseded by native support
//! for #[proc_macro] in expression position. Only consider using this crate if
//! you care about supporting compilers between 1.31 and 1.45.</i>
//! <hr></td></tr></table>
//!
//! Since Rust 1.30, the language supports user-defined function-like procedural
//! macros. However these can only be invoked in item position, not in
//! statements or expressions.
//!
@ -14,7 +28,7 @@
//! This crate must contain nothing but procedural macros. Private helper
//! functions and private modules are fine but nothing can be public.
//!
//! [> example of an implementation crate][demo-hack-impl]
//! [&raquo; example of an implementation crate][demo-hack-impl]
//!
//! Just like you would use a #\[proc_macro\] attribute to define a natively
//! supported procedural macro, use proc-macro-hack's #\[proc_macro_hack\]
@ -23,8 +37,8 @@
//! macros.
//!
//! ```
//! extern crate proc_macro;
//!
//! # extern crate proc_macro;
//! #
//! use proc_macro::TokenStream;
//! use proc_macro_hack::proc_macro_hack;
//! use quote::quote;
@ -48,7 +62,7 @@
//! This crate is allowed to contain other public things if you need, for
//! example traits or functions or ordinary macros.
//!
//! [> example of a declaration crate][demo-hack]
//! [&raquo; example of a declaration crate][demo-hack]
//!
//! Within the declaration crate there needs to be a re-export of your
//! procedural macro from the implementation crate. The re-export also carries a
@ -86,7 +100,7 @@
//! Users of your crate depend on your declaration crate (not your
//! implementation crate), then use your procedural macros as usual.
//!
//! [> example of a downstream crate][example]
//! [&raquo; example of a downstream crate][example]
//!
//! ```
//! use demo_hack::add_one;
@ -104,8 +118,8 @@
//!
//! # Limitations
//!
//! - Only proc macros in expression position are supported. Proc macros in type
//! position ([#10]) or pattern position ([#20]) are not supported.
//! - Only proc macros in expression position are supported. Proc macros in
//! pattern position ([#20]) are not supported.
//!
//! - By default, nested invocations are not supported i.e. the code emitted by
//! a proc-macro-hack macro invocation cannot contain recursive calls to the
@ -118,24 +132,39 @@
//! in the macro input, use `#[proc_macro_hack(fake_call_site)]` on the
//! re-export in your declaration crate. *Most macros won't need this.*
//!
//! - On compilers that are new enough to natively support proc macros in
//! expression position, proc-macro-hack does not automatically use that
//! support, since the hygiene can be subtly different between the two
//! implementations. To opt in to compiling your macro to native
//! `#[proc_macro]` on sufficiently new compilers, use
//! `#[proc_macro_hack(only_hack_old_rustc)]` on the re-export in your
//! declaration crate.
//!
//! [#10]: https://github.com/dtolnay/proc-macro-hack/issues/10
//! [#20]: https://github.com/dtolnay/proc-macro-hack/issues/20
//! [`proc-macro-nested`]: https://docs.rs/proc-macro-nested
#![recursion_limit = "512"]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
#![allow(clippy::needless_doctest_main, clippy::toplevel_ref_arg)]
extern crate proc_macro;
use proc_macro2::{Span, TokenStream, TokenTree};
use quote::{format_ident, quote, ToTokens};
use std::fmt::Write;
use syn::ext::IdentExt;
use syn::parse::{Parse, ParseStream, Result};
use syn::{braced, bracketed, parenthesized, parse_macro_input, token, Ident, LitInt, Token};
#[macro_use]
mod quote;
type Visibility = Option<Token![pub]>;
mod error;
mod iter;
mod parse;
use crate::error::{compile_error, Error};
use crate::iter::Iter;
use crate::parse::{
parse_define_args, parse_enum_hack, parse_export_args, parse_fake_call_site, parse_input,
};
use proc_macro::{Ident, Punct, Spacing, Span, TokenStream, TokenTree};
use std::fmt::Write;
type Visibility = Option<Ident>;
enum Input {
Export(Export),
@ -162,210 +191,31 @@ struct Macro {
export_as: Ident,
}
impl Parse for Input {
fn parse(input: ParseStream) -> Result<Self> {
let ahead = input.fork();
parse_attributes(&ahead)?;
ahead.parse::<Visibility>()?;
if ahead.peek(Token![use]) {
input.parse().map(Input::Export)
} else if ahead.peek(Token![fn]) {
input.parse().map(Input::Define)
} else {
Err(input.error("unexpected input to #[proc_macro_hack]"))
}
}
}
impl Parse for Export {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(parse_attributes)?;
let vis: Visibility = input.parse()?;
input.parse::<Token![use]>()?;
input.parse::<Option<Token![::]>>()?;
let from: Ident = input.parse()?;
input.parse::<Token![::]>()?;
let mut macros = Vec::new();
if input.peek(token::Brace) {
let content;
braced!(content in input);
loop {
macros.push(content.parse()?);
if content.is_empty() {
break;
}
content.parse::<Token![,]>()?;
if content.is_empty() {
break;
}
}
} else {
macros.push(input.parse()?);
}
input.parse::<Token![;]>()?;
Ok(Export {
attrs,
vis,
from,
macros,
})
}
}
impl Parse for Define {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(parse_attributes)?;
let vis: Visibility = input.parse()?;
if vis.is_none() {
return Err(input.error("functions tagged with `#[proc_macro_hack]` must be `pub`"));
}
input.parse::<Token![fn]>()?;
let name: Ident = input.parse()?;
let body: TokenStream = input.parse()?;
Ok(Define { attrs, name, body })
}
}
impl Parse for Macro {
fn parse(input: ParseStream) -> Result<Self> {
let name: Ident = input.parse()?;
let renamed: Option<Token![as]> = input.parse()?;
let export_as = if renamed.is_some() {
input.parse()?
} else {
name.clone()
};
Ok(Macro { name, export_as })
}
}
fn parse_attributes(input: ParseStream) -> Result<TokenStream> {
let mut attrs = TokenStream::new();
while input.peek(Token![#]) {
let pound: Token![#] = input.parse()?;
pound.to_tokens(&mut attrs);
let content;
let bracket_token = bracketed!(content in input);
let content: TokenStream = content.parse()?;
bracket_token.surround(&mut attrs, |tokens| content.to_tokens(tokens));
}
Ok(attrs)
}
#[proc_macro_attribute]
pub fn proc_macro_hack(
args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
proc_macro::TokenStream::from(match parse_macro_input!(input) {
pub fn proc_macro_hack(args: TokenStream, input: TokenStream) -> TokenStream {
let ref mut args = iter::new(args);
let ref mut input = iter::new(input);
expand_proc_macro_hack(args, input).unwrap_or_else(compile_error)
}
fn expand_proc_macro_hack(args: Iter, input: Iter) -> Result<TokenStream, Error> {
match parse_input(input)? {
Input::Export(export) => {
let args = parse_macro_input!(args as ExportArgs);
expand_export(export, args)
let args = parse_export_args(args)?;
Ok(expand_export(export, args))
}
Input::Define(define) => {
parse_macro_input!(args as DefineArgs);
expand_define(define)
parse_define_args(args)?;
Ok(expand_define(define))
}
})
}
mod kw {
syn::custom_keyword!(derive);
syn::custom_keyword!(fake_call_site);
syn::custom_keyword!(internal_macro_calls);
syn::custom_keyword!(support_nested);
}
struct ExportArgs {
support_nested: bool,
internal_macro_calls: u16,
fake_call_site: bool,
}
impl Parse for ExportArgs {
fn parse(input: ParseStream) -> Result<Self> {
let mut args = ExportArgs {
support_nested: false,
internal_macro_calls: 0,
fake_call_site: false,
};
while !input.is_empty() {
let ahead = input.lookahead1();
if ahead.peek(kw::support_nested) {
input.parse::<kw::support_nested>()?;
args.support_nested = true;
} else if ahead.peek(kw::internal_macro_calls) {
input.parse::<kw::internal_macro_calls>()?;
input.parse::<Token![=]>()?;
let calls = input.parse::<LitInt>()?.base10_parse()?;
args.internal_macro_calls = calls;
} else if ahead.peek(kw::fake_call_site) {
input.parse::<kw::fake_call_site>()?;
args.fake_call_site = true;
} else {
return Err(ahead.error());
}
if input.is_empty() {
break;
}
input.parse::<Token![,]>()?;
}
Ok(args)
}
}
struct DefineArgs;
impl Parse for DefineArgs {
fn parse(_input: ParseStream) -> Result<Self> {
Ok(DefineArgs)
}
}
struct EnumHack {
token_stream: TokenStream,
}
impl Parse for EnumHack {
fn parse(input: ParseStream) -> Result<Self> {
input.parse::<Token![enum]>()?;
input.parse::<Ident>()?;
let braces;
braced!(braces in input);
braces.parse::<Ident>()?;
braces.parse::<Token![=]>()?;
let parens;
parenthesized!(parens in braces);
parens.parse::<Ident>()?;
parens.parse::<Token![!]>()?;
let inner;
braced!(inner in parens);
let token_stream: TokenStream = inner.parse()?;
parens.parse::<Token![,]>()?;
parens.parse::<TokenTree>()?;
braces.parse::<Token![.]>()?;
braces.parse::<TokenTree>()?;
braces.parse::<Token![,]>()?;
Ok(EnumHack { token_stream })
}
}
#[doc(hidden)]
#[proc_macro_derive(ProcMacroHack)]
pub fn enum_hack(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let inner = parse_macro_input!(input as EnumHack);
proc_macro::TokenStream::from(inner.token_stream)
pub fn enum_hack(input: TokenStream) -> TokenStream {
let ref mut input = iter::new(input);
parse_enum_hack(input).unwrap_or_else(compile_error)
}
struct FakeCallSite {
@ -373,47 +223,43 @@ struct FakeCallSite {
rest: TokenStream,
}
impl Parse for FakeCallSite {
fn parse(input: ParseStream) -> Result<Self> {
input.parse::<Token![#]>()?;
let attr;
bracketed!(attr in input);
attr.parse::<kw::derive>()?;
let path;
parenthesized!(path in attr);
Ok(FakeCallSite {
derive: path.parse()?,
rest: input.parse()?,
})
}
}
#[doc(hidden)]
#[proc_macro_attribute]
pub fn fake_call_site(
args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let args = TokenStream::from(args);
let span = match args.into_iter().next() {
pub fn fake_call_site(args: TokenStream, input: TokenStream) -> TokenStream {
let ref mut args = iter::new(args);
let ref mut input = iter::new(input);
expand_fake_call_site(args, input).unwrap_or_else(compile_error)
}
fn expand_fake_call_site(args: Iter, input: Iter) -> Result<TokenStream, Error> {
let span = match args.next() {
Some(token) => token.span(),
None => return input,
None => return Ok(input.collect()),
};
let input = parse_macro_input!(input as FakeCallSite);
let input = parse_fake_call_site(input)?;
let mut derive = input.derive;
derive.set_span(span);
let rest = input.rest;
let expanded = quote! {
Ok(quote! {
#[derive(#derive)]
#rest
};
})
}
proc_macro::TokenStream::from(expanded)
struct ExportArgs {
support_nested: bool,
internal_macro_calls: u16,
fake_call_site: bool,
only_hack_old_rustc: bool,
}
fn expand_export(export: Export, args: ExportArgs) -> TokenStream {
if args.only_hack_old_rustc && cfg!(not(need_proc_macro_hack)) {
return expand_export_nohack(export);
}
let dummy = dummy_name_for_export(&export);
let attrs = export.attrs;
@ -422,120 +268,177 @@ fn expand_export(export: Export, args: ExportArgs) -> TokenStream {
Some(_) => quote!(#[macro_export]),
None => quote!(),
};
let crate_prefix = vis.map(|_| quote!($crate::));
let crate_prefix = vis.as_ref().map(|_| quote!($crate::));
let enum_variant = if args.support_nested {
if args.internal_macro_calls == 0 {
quote!(Nested)
Ident::new("Nested", Span::call_site())
} else {
format_ident!("Nested{}", args.internal_macro_calls).to_token_stream()
let name = format!("Nested{}", args.internal_macro_calls);
Ident::new(&name, Span::call_site())
}
} else {
quote!(Value)
Ident::new("Value", Span::call_site())
};
let from = export.from;
let rules = export
.macros
.into_iter()
.map(|Macro { name, export_as }| {
let actual_name = actual_proc_macro_name(&name);
let dispatch = dispatch_macro_name(&name);
let call_site = call_site_macro_name(&name);
let mut actual_names = TokenStream::new();
let mut export_dispatch = TokenStream::new();
let mut export_call_site = TokenStream::new();
let mut macro_rules = TokenStream::new();
for Macro { name, export_as } in &export.macros {
let hacked = hacked_proc_macro_name(&name);
let dispatch = dispatch_macro_name(&name);
let call_site = call_site_macro_name(&name);
let export_dispatch = if args.support_nested {
quote! {
#[doc(hidden)]
#vis use proc_macro_nested::dispatch as #dispatch;
}
} else {
quote!()
};
if !actual_names.is_empty() {
actual_names.extend(quote!(,));
}
actual_names.extend(quote!(#hacked));
let proc_macro_call = if args.support_nested {
let extra_bangs = (0..args.internal_macro_calls).map(|_| quote!(!));
quote! {
#crate_prefix #dispatch! { ($($proc_macro)*) #(#extra_bangs)* }
}
} else {
quote! {
proc_macro_call!()
}
};
if !export_dispatch.is_empty() {
export_dispatch.extend(quote!(,));
}
export_dispatch.extend(quote!(dispatch as #dispatch));
let export_call_site = if args.fake_call_site {
quote! {
#[doc(hidden)]
#vis use proc_macro_hack::fake_call_site as #call_site;
}
} else {
quote!()
};
let do_derive = if !args.fake_call_site {
quote! {
#[derive(#crate_prefix #actual_name)]
}
} else if crate_prefix.is_some() {
quote! {
use #crate_prefix #actual_name;
#[#crate_prefix #call_site ($($proc_macro)*)]
#[derive(#actual_name)]
}
} else {
quote! {
#[#call_site ($($proc_macro)*)]
#[derive(#actual_name)]
}
};
if !export_call_site.is_empty() {
export_call_site.extend(quote!(,));
}
export_call_site.extend(quote!(fake_call_site as #call_site));
let do_derive = if !args.fake_call_site {
quote! {
#[doc(hidden)]
#vis use #from::#actual_name;
#export_dispatch
#export_call_site
#attrs
#macro_export
macro_rules! #export_as {
($($proc_macro:tt)*) => {{
#do_derive
enum ProcMacroHack {
#enum_variant = (stringify! { $($proc_macro)* }, 0).1,
}
#proc_macro_call
}};
}
#[derive(#crate_prefix #hacked)]
}
})
.collect();
} else if crate_prefix.is_some() {
quote! {
use #crate_prefix #hacked;
#[#crate_prefix #call_site ($($proc_macro)*)]
#[derive(#hacked)]
}
} else {
quote! {
#[#call_site ($($proc_macro)*)]
#[derive(#hacked)]
}
};
wrap_in_enum_hack(dummy, rules)
let proc_macro_call = if args.support_nested {
let extra_bangs = (0..args.internal_macro_calls)
.map(|_| TokenTree::Punct(Punct::new('!', Spacing::Alone)))
.collect::<TokenStream>();
quote! {
#crate_prefix #dispatch! { ($($proc_macro)*) #extra_bangs }
}
} else {
quote! {
proc_macro_call!()
}
};
macro_rules.extend(quote! {
#attrs
#macro_export
macro_rules! #export_as {
($($proc_macro:tt)*) => {{
#do_derive
#[allow(dead_code)]
enum ProcMacroHack {
#enum_variant = (stringify! { $($proc_macro)* }, 0).1,
}
#proc_macro_call
}};
}
});
}
if export.macros.len() != 1 {
export_dispatch = quote!({#export_dispatch});
export_call_site = quote!({#export_call_site});
actual_names = quote!({#actual_names});
}
let export_dispatch = if args.support_nested {
quote! {
#[doc(hidden)]
#vis use proc_macro_nested::#export_dispatch;
}
} else {
quote!()
};
let export_call_site = if args.fake_call_site {
quote! {
#[doc(hidden)]
#vis use proc_macro_hack::#export_call_site;
}
} else {
quote!()
};
let expanded = quote! {
#[doc(hidden)]
#vis use #from::#actual_names;
#export_dispatch
#export_call_site
#macro_rules
};
wrap_in_enum_hack(dummy, expanded)
}
fn expand_export_nohack(export: Export) -> TokenStream {
let attrs = export.attrs;
let vis = export.vis;
let from = export.from;
let mut names = TokenStream::new();
for Macro { name, export_as } in &export.macros {
let pub_name = pub_proc_macro_name(&name);
if !names.is_empty() {
names.extend(quote!(,));
}
names.extend(quote!(#pub_name as #export_as));
}
if export.macros.len() != 1 {
names = quote!({#names});
}
quote! {
#attrs
#vis use #from::#names;
}
}
fn expand_define(define: Define) -> TokenStream {
let attrs = define.attrs;
let name = define.name;
let dummy = actual_proc_macro_name(&name);
let pub_name = pub_proc_macro_name(&name);
let hacked = hacked_proc_macro_name(&name);
let body = define.body;
quote! {
mod #dummy {
mod #pub_name {
extern crate proc_macro;
pub use self::proc_macro::*;
}
#attrs
#[proc_macro_derive(#dummy)]
pub fn #dummy(input: #dummy::TokenStream) -> #dummy::TokenStream {
#[doc(hidden)]
#[proc_macro_derive(#hacked)]
pub fn #hacked(input: #pub_name::TokenStream) -> #pub_name::TokenStream {
use std::iter::FromIterator;
let mut iter = input.into_iter();
iter.next().unwrap(); // `enum`
iter.next().unwrap(); // `ProcMacroHack`
iter.next().unwrap(); // `#`
iter.next().unwrap(); // `[allow(dead_code)]`
let mut braces = match iter.next().unwrap() {
#dummy::TokenTree::Group(group) => group.stream().into_iter(),
#pub_name::TokenTree::Group(group) => group.stream().into_iter(),
_ => unimplemented!(),
};
let variant = braces.next().unwrap(); // `Value` or `Nested`
@ -544,29 +447,29 @@ fn expand_define(define: Define) -> TokenStream {
braces.next().unwrap(); // `=`
let mut parens = match braces.next().unwrap() {
#dummy::TokenTree::Group(group) => group.stream().into_iter(),
#pub_name::TokenTree::Group(group) => group.stream().into_iter(),
_ => unimplemented!(),
};
parens.next().unwrap(); // `stringify`
parens.next().unwrap(); // `!`
let inner = match parens.next().unwrap() {
#dummy::TokenTree::Group(group) => group.stream(),
#pub_name::TokenTree::Group(group) => group.stream(),
_ => unimplemented!(),
};
let output: #dummy::TokenStream = #name(inner.clone());
let output: #pub_name::TokenStream = #name(inner.clone());
fn count_bangs(input: #dummy::TokenStream) -> usize {
fn count_bangs(input: #pub_name::TokenStream) -> usize {
let mut count = 0;
for token in input {
match token {
#dummy::TokenTree::Punct(punct) => {
#pub_name::TokenTree::Punct(punct) => {
if punct.as_char() == '!' {
count += 1;
}
}
#dummy::TokenTree::Group(group) => {
#pub_name::TokenTree::Group(group) => {
count += count_bangs(group.stream());
}
_ => {}
@ -578,15 +481,15 @@ fn expand_define(define: Define) -> TokenStream {
// macro_rules! proc_macro_call {
// () => { #output }
// }
#dummy::TokenStream::from_iter(vec![
#dummy::TokenTree::Ident(
#dummy::Ident::new("macro_rules", #dummy::Span::call_site()),
#pub_name::TokenStream::from_iter(vec![
#pub_name::TokenTree::Ident(
#pub_name::Ident::new("macro_rules", #pub_name::Span::call_site()),
),
#dummy::TokenTree::Punct(
#dummy::Punct::new('!', #dummy::Spacing::Alone),
#pub_name::TokenTree::Punct(
#pub_name::Punct::new('!', #pub_name::Spacing::Alone),
),
#dummy::TokenTree::Ident(
#dummy::Ident::new(
#pub_name::TokenTree::Ident(
#pub_name::Ident::new(
&if support_nested {
let extra_bangs = if varname == "Nested" {
0
@ -597,55 +500,86 @@ fn expand_define(define: Define) -> TokenStream {
} else {
String::from("proc_macro_call")
},
#dummy::Span::call_site(),
#pub_name::Span::call_site(),
),
),
#dummy::TokenTree::Group(
#dummy::Group::new(#dummy::Delimiter::Brace, #dummy::TokenStream::from_iter(vec![
#dummy::TokenTree::Group(
#dummy::Group::new(#dummy::Delimiter::Parenthesis, #dummy::TokenStream::new()),
#pub_name::TokenTree::Group(
#pub_name::Group::new(#pub_name::Delimiter::Brace, #pub_name::TokenStream::from_iter(vec![
#pub_name::TokenTree::Group(
#pub_name::Group::new(#pub_name::Delimiter::Parenthesis, #pub_name::TokenStream::new()),
),
#dummy::TokenTree::Punct(
#dummy::Punct::new('=', #dummy::Spacing::Joint),
#pub_name::TokenTree::Punct(
#pub_name::Punct::new('=', #pub_name::Spacing::Joint),
),
#dummy::TokenTree::Punct(
#dummy::Punct::new('>', #dummy::Spacing::Alone),
#pub_name::TokenTree::Punct(
#pub_name::Punct::new('>', #pub_name::Spacing::Alone),
),
#dummy::TokenTree::Group(
#dummy::Group::new(#dummy::Delimiter::Brace, output),
#pub_name::TokenTree::Group(
#pub_name::Group::new(#pub_name::Delimiter::Brace, output),
),
])),
),
])
}
#attrs
#[proc_macro]
pub fn #pub_name(input: #pub_name::TokenStream) -> #pub_name::TokenStream {
#name(input)
}
fn #name #body
}
}
fn actual_proc_macro_name(conceptual: &Ident) -> Ident {
format_ident!("proc_macro_hack_{}", conceptual)
fn pub_proc_macro_name(conceptual: &Ident) -> Ident {
Ident::new(
&format!("proc_macro_hack_{}", conceptual),
conceptual.span(),
)
}
fn hacked_proc_macro_name(conceptual: &Ident) -> Ident {
Ident::new(
&format!("_proc_macro_hack_{}", conceptual),
conceptual.span(),
)
}
fn dispatch_macro_name(conceptual: &Ident) -> Ident {
format_ident!("proc_macro_call_{}", conceptual)
Ident::new(
&format!("proc_macro_call_{}", conceptual),
conceptual.span(),
)
}
fn call_site_macro_name(conceptual: &Ident) -> Ident {
format_ident!("proc_macro_fake_call_site_{}", conceptual)
Ident::new(
&format!("proc_macro_fake_call_site_{}", conceptual),
conceptual.span(),
)
}
fn dummy_name_for_export(export: &Export) -> String {
let mut dummy = String::new();
let from = export.from.unraw().to_string();
let from = unraw(&export.from).to_string();
write!(dummy, "_{}{}", from.len(), from).unwrap();
for m in &export.macros {
let name = m.name.unraw().to_string();
let name = unraw(&m.name).to_string();
write!(dummy, "_{}{}", name.len(), name).unwrap();
}
dummy
}
fn unraw(ident: &Ident) -> Ident {
let string = ident.to_string();
if string.starts_with("r#") {
Ident::new(&string[2..], ident.span())
} else {
ident.clone()
}
}
fn wrap_in_enum_hack(dummy: String, inner: TokenStream) -> TokenStream {
let dummy = Ident::new(&dummy, Span::call_site());
quote! {

254
third_party/rust/proc-macro-hack/src/parse.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,254 @@
use crate::iter::{self, Iter, IterImpl};
use crate::{Define, Error, Export, ExportArgs, FakeCallSite, Input, Macro, Visibility};
use proc_macro::Delimiter::{Brace, Bracket, Parenthesis};
use proc_macro::{Delimiter, Ident, Span, TokenStream, TokenTree};
pub(crate) fn parse_input(tokens: Iter) -> Result<Input, Error> {
let attrs = parse_attributes(tokens)?;
let vis = parse_visibility(tokens)?;
let kw = parse_ident(tokens)?;
if kw.to_string() == "use" {
parse_export(attrs, vis, tokens).map(Input::Export)
} else if kw.to_string() == "fn" {
parse_define(attrs, vis, kw.span(), tokens).map(Input::Define)
} else {
Err(Error::new(
kw.span(),
"unexpected input to #[proc_macro_hack]",
))
}
}
fn parse_export(attrs: TokenStream, vis: Visibility, tokens: Iter) -> Result<Export, Error> {
let _ = parse_punct(tokens, ':');
let _ = parse_punct(tokens, ':');
let from = parse_ident(tokens)?;
parse_punct(tokens, ':')?;
parse_punct(tokens, ':')?;
let mut macros = Vec::new();
match tokens.peek() {
Some(TokenTree::Group(group)) if group.delimiter() == Brace => {
let ref mut content = iter::new(group.stream());
loop {
macros.push(parse_macro(content)?);
if content.peek().is_none() {
break;
}
parse_punct(content, ',')?;
if content.peek().is_none() {
break;
}
}
tokens.next().unwrap();
}
_ => macros.push(parse_macro(tokens)?),
}
parse_punct(tokens, ';')?;
Ok(Export {
attrs,
vis,
from,
macros,
})
}
fn parse_punct(tokens: Iter, ch: char) -> Result<(), Error> {
match tokens.peek() {
Some(TokenTree::Punct(punct)) if punct.as_char() == ch => {
tokens.next().unwrap();
Ok(())
}
tt => Err(Error::new(
tt.map_or_else(Span::call_site, TokenTree::span),
format!("expected `{}`", ch),
)),
}
}
fn parse_define(
attrs: TokenStream,
vis: Visibility,
fn_token: Span,
tokens: Iter,
) -> Result<Define, Error> {
if vis.is_none() {
return Err(Error::new(
fn_token,
"functions tagged with `#[proc_macro_hack]` must be `pub`",
));
}
let name = parse_ident(tokens)?;
let body = tokens.collect();
Ok(Define { attrs, name, body })
}
fn parse_macro(tokens: Iter) -> Result<Macro, Error> {
let name = parse_ident(tokens)?;
let export_as = match tokens.peek() {
Some(TokenTree::Ident(ident)) if ident.to_string() == "as" => {
tokens.next().unwrap();
parse_ident(tokens)?
}
_ => name.clone(),
};
Ok(Macro { name, export_as })
}
fn parse_ident(tokens: Iter) -> Result<Ident, Error> {
match tokens.next() {
Some(TokenTree::Ident(ident)) => Ok(ident),
tt => Err(Error::new(
tt.as_ref().map_or_else(Span::call_site, TokenTree::span),
"expected identifier",
)),
}
}
fn parse_keyword(tokens: Iter, kw: &'static str) -> Result<(), Error> {
match &tokens.next() {
Some(TokenTree::Ident(ident)) if ident.to_string() == kw => Ok(()),
tt => Err(Error::new(
tt.as_ref().map_or_else(Span::call_site, TokenTree::span),
format!("expected `{}`", kw),
)),
}
}
fn parse_int(tokens: Iter) -> Result<u16, Span> {
match tokens.next() {
Some(TokenTree::Literal(lit)) => lit.to_string().parse().map_err(|_| lit.span()),
Some(tt) => Err(tt.span()),
None => Err(Span::call_site()),
}
}
fn parse_group(tokens: Iter, delimiter: Delimiter) -> Result<IterImpl, Error> {
match &tokens.next() {
Some(TokenTree::Group(group)) if group.delimiter() == delimiter => {
Ok(iter::new(group.stream()))
}
tt => Err(Error::new(
tt.as_ref().map_or_else(Span::call_site, TokenTree::span),
"expected delimiter",
)),
}
}
fn parse_visibility(tokens: Iter) -> Result<Visibility, Error> {
if let Some(TokenTree::Ident(ident)) = tokens.peek() {
if ident.to_string() == "pub" {
match tokens.next().unwrap() {
TokenTree::Ident(vis) => return Ok(Some(vis)),
_ => unreachable!(),
}
}
}
Ok(None)
}
fn parse_attributes(tokens: Iter) -> Result<TokenStream, Error> {
let mut attrs = TokenStream::new();
while let Some(TokenTree::Punct(punct)) = tokens.peek() {
if punct.as_char() != '#' {
break;
}
let span = punct.span();
attrs.extend(tokens.next());
match tokens.peek() {
Some(TokenTree::Group(group)) if group.delimiter() == Bracket => {
attrs.extend(tokens.next());
}
_ => return Err(Error::new(span, "unexpected input")),
}
}
Ok(attrs)
}
pub(crate) fn parse_export_args(tokens: Iter) -> Result<ExportArgs, Error> {
let mut args = ExportArgs {
support_nested: false,
internal_macro_calls: 0,
fake_call_site: false,
only_hack_old_rustc: false,
};
while let Some(tt) = tokens.next() {
match &tt {
TokenTree::Ident(ident) if ident.to_string() == "support_nested" => {
args.support_nested = true;
}
TokenTree::Ident(ident) if ident.to_string() == "internal_macro_calls" => {
parse_punct(tokens, '=')?;
let calls = parse_int(tokens).map_err(|span| {
Error::new(span, "expected integer value for internal_macro_calls")
})?;
args.internal_macro_calls = calls;
}
TokenTree::Ident(ident) if ident.to_string() == "fake_call_site" => {
args.fake_call_site = true;
}
TokenTree::Ident(ident) if ident.to_string() == "only_hack_old_rustc" => {
args.only_hack_old_rustc = true;
}
_ => {
return Err(Error::new(
tt.span(),
"expected one of: `support_nested`, `internal_macro_calls`, `fake_call_site`, `only_hack_old_rustc`",
));
}
}
if tokens.peek().is_none() {
break;
}
parse_punct(tokens, ',')?;
}
Ok(args)
}
pub(crate) fn parse_define_args(tokens: Iter) -> Result<(), Error> {
match tokens.peek() {
None => Ok(()),
Some(token) => Err(Error::new(
token.span(),
"unexpected argument to proc_macro_hack macro implementation; args are only accepted on the macro declaration (the `pub use`)",
)),
}
}
pub(crate) fn parse_enum_hack(tokens: Iter) -> Result<TokenStream, Error> {
parse_keyword(tokens, "enum")?;
parse_ident(tokens)?;
let ref mut braces = parse_group(tokens, Brace)?;
parse_ident(braces)?;
parse_punct(braces, '=')?;
let ref mut parens = parse_group(braces, Parenthesis)?;
parse_ident(parens)?;
parse_punct(parens, '!')?;
let ref mut inner = parse_group(parens, Brace)?;
let token_stream = inner.collect();
parse_punct(parens, ',')?;
let _ = parens.next();
parse_punct(braces, '.')?;
let _ = braces.next();
parse_punct(braces, ',')?;
Ok(token_stream)
}
pub(crate) fn parse_fake_call_site(tokens: Iter) -> Result<FakeCallSite, Error> {
parse_punct(tokens, '#')?;
let ref mut attr = parse_group(tokens, Bracket)?;
parse_keyword(attr, "derive")?;
let ref mut path = parse_group(attr, Parenthesis)?;
Ok(FakeCallSite {
derive: parse_ident(path)?,
rest: tokens.collect(),
})
}

114
third_party/rust/proc-macro-hack/src/quote.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,114 @@
use proc_macro::{Ident, TokenStream, TokenTree};
use std::iter;
macro_rules! quote {
() => {
::proc_macro::TokenStream::new()
};
($($tt:tt)*) => {{
let mut tokens = ::proc_macro::TokenStream::new();
quote_each_token!(tokens $($tt)*);
tokens
}};
}
macro_rules! quote_each_token {
($tokens:ident # $var:ident $($rest:tt)*) => {
$crate::quote::Tokens::extend(&mut $tokens, &$var);
quote_each_token!($tokens $($rest)*);
};
($tokens:ident $ident:ident $($rest:tt)*) => {
<::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend(
&mut $tokens,
::std::iter::once(
::proc_macro::TokenTree::Ident(
::proc_macro::Ident::new(
stringify!($ident),
::proc_macro::Span::call_site(),
),
),
),
);
quote_each_token!($tokens $($rest)*);
};
($tokens:ident ( $($inner:tt)* ) $($rest:tt)*) => {
<::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend(
&mut $tokens,
::std::iter::once(
::proc_macro::TokenTree::Group(
::proc_macro::Group::new(
::proc_macro::Delimiter::Parenthesis,
quote!($($inner)*),
),
),
),
);
quote_each_token!($tokens $($rest)*);
};
($tokens:ident [ $($inner:tt)* ] $($rest:tt)*) => {
<::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend(
&mut $tokens,
::std::iter::once(
::proc_macro::TokenTree::Group(
::proc_macro::Group::new(
::proc_macro::Delimiter::Bracket,
quote!($($inner)*),
),
),
),
);
quote_each_token!($tokens $($rest)*);
};
($tokens:ident { $($inner:tt)* } $($rest:tt)*) => {
<::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend(
&mut $tokens,
::std::iter::once(
::proc_macro::TokenTree::Group(
::proc_macro::Group::new(
::proc_macro::Delimiter::Brace,
quote!($($inner)*),
),
),
),
);
quote_each_token!($tokens $($rest)*);
};
($tokens:ident $punct:tt $($rest:tt)*) => {
<::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend(
&mut $tokens,
stringify!($punct).parse::<::proc_macro::TokenStream>(),
);
quote_each_token!($tokens $($rest)*);
};
($tokens:ident) => {};
}
pub trait Tokens {
fn extend(tokens: &mut TokenStream, var: &Self);
}
impl Tokens for Ident {
fn extend(tokens: &mut TokenStream, var: &Self) {
tokens.extend(iter::once(TokenTree::Ident(var.clone())));
}
}
impl Tokens for TokenStream {
fn extend(tokens: &mut TokenStream, var: &Self) {
tokens.extend(var.clone());
}
}
impl<T: Tokens> Tokens for Option<T> {
fn extend(tokens: &mut TokenStream, var: &Self) {
if let Some(var) = var {
T::extend(tokens, var);
}
}
}
impl<T: Tokens> Tokens for &T {
fn extend(tokens: &mut TokenStream, var: &Self) {
T::extend(tokens, var);
}
}

6
third_party/rust/proc-macro-hack/tests/compiletest.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
#[rustversion::attr(not(nightly), ignore)]
#[test]
fn ui() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/*.rs");
}

8
third_party/rust/proc-macro-hack/tests/ui/private.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,8 @@
use proc_macro_hack::proc_macro_hack;
#[proc_macro_hack]
fn my_macro(input: TokenStream) -> TokenStream {
unimplemented!()
}
fn main() {}

5
third_party/rust/proc-macro-hack/tests/ui/private.stderr поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
error: functions tagged with `#[proc_macro_hack]` must be `pub`
--> $DIR/private.rs:4:1
|
4 | fn my_macro(input: TokenStream) -> TokenStream {
| ^^

8
third_party/rust/proc-macro-hack/tests/ui/unexpected-arg.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,8 @@
use proc_macro_hack::proc_macro_hack;
#[proc_macro_hack(fake_call_site)]
pub fn my_macro(input: TokenStream) -> TokenStream {
unimplemented!()
}
fn main() {}

Просмотреть файл

@ -0,0 +1,5 @@
error: unexpected argument to proc_macro_hack macro implementation; args are only accepted on the macro declaration (the `pub use`)
--> $DIR/unexpected-arg.rs:3:19
|
3 | #[proc_macro_hack(fake_call_site)]
| ^^^^^^^^^^^^^^

6
third_party/rust/proc-macro-hack/tests/ui/unexpected.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
use proc_macro_hack::proc_macro_hack;
#[proc_macro_hack]
pub struct What;
fn main() {}

5
third_party/rust/proc-macro-hack/tests/ui/unexpected.stderr поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
error: unexpected input to #[proc_macro_hack]
--> $DIR/unexpected.rs:4:5
|
4 | pub struct What;
| ^^^^^^

6
third_party/rust/proc-macro-hack/tests/ui/unknown-arg.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
use proc_macro_hack::proc_macro_hack;
#[proc_macro_hack(fake_call_site, support_nexted)]
pub use demo::some_macro;
fn main() {}

5
third_party/rust/proc-macro-hack/tests/ui/unknown-arg.stderr поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
error: expected one of: `support_nested`, `internal_macro_calls`, `fake_call_site`, `only_hack_old_rustc`
--> $DIR/unknown-arg.rs:3:35
|
3 | #[proc_macro_hack(fake_call_site, support_nexted)]
| ^^^^^^^^^^^^^^