aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChih-Hung Hsieh <chh@google.com>2020-10-29 09:24:12 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-10-29 09:24:12 +0000
commit855ae69748fae4b3c92e3c21c2c7aadd6da85ea6 (patch)
tree1e2eb4c5e83186eac368d296310722e78521046c
parent63a4081a8cd7da1da178d69998d8fd28f5ef397a (diff)
parentfc7244423b3c3ac67f970d12ca36539e4ce7644f (diff)
downloadplatform_external_rust_crates_syn-855ae69748fae4b3c92e3c21c2c7aadd6da85ea6.tar.gz
platform_external_rust_crates_syn-855ae69748fae4b3c92e3c21c2c7aadd6da85ea6.tar.bz2
platform_external_rust_crates_syn-855ae69748fae4b3c92e3c21c2c7aadd6da85ea6.zip
Upgrade rust/crates/syn to 1.0.48 am: a0ab740044 am: 19bcb7b269 am: fc7244423b
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/syn/+/1474978 Change-Id: Ifac10711939e244e46ca2193ca4341bd18d7a085
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp2
-rw-r--r--Cargo.toml6
-rw-r--r--Cargo.toml.orig6
-rw-r--r--METADATA8
-rw-r--r--src/attr.rs9
-rw-r--r--src/await.rs2
-rw-r--r--src/buffer.rs4
-rw-r--r--src/custom_keyword.rs4
-rw-r--r--src/custom_punctuation.rs4
-rw-r--r--src/data.rs5
-rw-r--r--src/derive.rs7
-rw-r--r--src/error.rs16
-rw-r--r--src/expr.rs7
-rw-r--r--src/ext.rs6
-rw-r--r--src/file.rs1
-rw-r--r--src/generics.rs7
-rw-r--r--src/group.rs3
-rw-r--r--src/item.rs87
-rw-r--r--src/lib.rs3
-rw-r--r--src/lifetime.rs5
-rw-r--r--src/lit.rs172
-rw-r--r--src/lookahead.rs6
-rw-r--r--src/mac.rs1
-rw-r--r--src/op.rs1
-rw-r--r--src/parse.rs24
-rw-r--r--src/parse_macro_input.rs44
-rw-r--r--src/parse_quote.rs4
-rw-r--r--src/pat.rs35
-rw-r--r--src/path.rs11
-rw-r--r--src/stmt.rs2
-rw-r--r--src/token.rs237
-rw-r--r--src/tt.rs3
-rw-r--r--src/ty.rs7
-rw-r--r--tests/common/eq.rs54
-rw-r--r--tests/common/parse.rs1
-rw-r--r--tests/macros/mod.rs1
-rw-r--r--tests/test_grouping.rs3
-rw-r--r--tests/test_lit.rs24
-rw-r--r--tests/test_meta.rs37
-rw-r--r--tests/test_pat.rs29
-rw-r--r--tests/test_path.rs56
-rw-r--r--tests/test_precedence.rs8
-rw-r--r--tests/test_round_trip.rs6
44 files changed, 560 insertions, 400 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index cf4bf5f3..9fdbc5a7 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "b66b940dbb15baa435a843d005221d87baca4cb4"
+ "sha1": "1c8ec7953893310c0ff10cbe27567846a0541187"
}
}
diff --git a/Android.bp b/Android.bp
index c0a28143..ba706b5b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -30,6 +30,6 @@ rust_library_host {
}
// dependent_library ["feature_list"]
-// proc-macro2-1.0.18 "default,proc-macro"
+// proc-macro2-1.0.24 "default,proc-macro"
// quote-1.0.7 "default,proc-macro"
// unicode-xid-0.2.1 "default"
diff --git a/Cargo.toml b/Cargo.toml
index 20277fc4..d5df3275 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "syn"
-version = "1.0.40"
+version = "1.0.48"
authors = ["David Tolnay <dtolnay@gmail.com>"]
include = ["/benches/**", "/build.rs", "/Cargo.toml", "/LICENSE-APACHE", "/LICENSE-MIT", "/README.md", "/src/**", "/tests/**"]
description = "Parser for Rust source code"
@@ -38,7 +38,7 @@ required-features = ["full", "parsing"]
name = "file"
required-features = ["full", "parsing"]
[dependencies.proc-macro2]
-version = "1.0.13"
+version = "1.0.23"
default-features = false
[dependencies.quote]
@@ -55,7 +55,7 @@ version = "1.0"
version = "1.0"
[dev-dependencies.insta]
-version = "0.16"
+version = "1.0"
[dev-dependencies.rayon]
version = "1.0"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index c61c5562..0e17af4f 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "syn"
-version = "1.0.40" # don't forget to update html_root_url and syn.json
+version = "1.0.48" # don't forget to update html_root_url and syn.json
authors = ["David Tolnay <dtolnay@gmail.com>"]
license = "MIT OR Apache-2.0"
description = "Parser for Rust source code"
@@ -35,14 +35,14 @@ proc-macro = ["proc-macro2/proc-macro", "quote/proc-macro"]
test = ["syn-test-suite/all-features"]
[dependencies]
-proc-macro2 = { version = "1.0.13", default-features = false }
+proc-macro2 = { version = "1.0.23", default-features = false }
quote = { version = "1.0", optional = true, default-features = false }
unicode-xid = "0.2"
[dev-dependencies]
anyhow = "1.0"
flate2 = "1.0"
-insta = "0.16"
+insta = "1.0"
rayon = "1.0"
ref-cast = "1.0"
regex = "1.0"
diff --git a/METADATA b/METADATA
index e522afde..0f019edb 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/syn/syn-1.0.40.crate"
+ value: "https://static.crates.io/crates/syn/syn-1.0.48.crate"
}
- version: "1.0.40"
+ version: "1.0.48"
license_type: NOTICE
last_upgrade_date {
year: 2020
- month: 9
- day: 8
+ month: 10
+ day: 26
}
}
diff --git a/src/attr.rs b/src/attr.rs
index fa4f1cb2..ea6ab09d 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -1,9 +1,7 @@
use super::*;
use crate::punctuated::Punctuated;
-
-use std::iter;
-
use proc_macro2::TokenStream;
+use std::iter;
#[cfg(feature = "parsing")]
use crate::parse::{Parse, ParseBuffer, ParseStream, Parser, Result};
@@ -494,7 +492,6 @@ where
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
-
use crate::ext::IdentExt;
use crate::parse::{Parse, ParseStream, Result};
#[cfg(feature = "full")]
@@ -581,7 +578,9 @@ pub mod parsing {
fn parse(input: ParseStream) -> Result<Self> {
if input.peek(Lit) && !(input.peek(LitBool) && input.peek2(Token![=])) {
input.parse().map(NestedMeta::Lit)
- } else if input.peek(Ident::peek_any) {
+ } else if input.peek(Ident::peek_any)
+ || input.peek(Token![::]) && input.peek3(Ident::peek_any)
+ {
input.parse().map(NestedMeta::Meta)
} else {
Err(input.error("expected identifier or literal"))
diff --git a/src/await.rs b/src/await.rs
index a8e24fd4..038c6a5d 100644
--- a/src/await.rs
+++ b/src/await.rs
@@ -1,2 +1,2 @@
// See include!("await.rs") in token.rs.
-export_token_macro![(await)];
+export_token_macro! {[await]}
diff --git a/src/buffer.rs b/src/buffer.rs
index a461cc49..ec172259 100644
--- a/src/buffer.rs
+++ b/src/buffer.rs
@@ -12,13 +12,11 @@
feature = "proc-macro"
))]
use crate::proc_macro as pm;
+use crate::Lifetime;
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
-
use std::marker::PhantomData;
use std::ptr;
-use crate::Lifetime;
-
/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
enum Entry {
diff --git a/src/custom_keyword.rs b/src/custom_keyword.rs
index a33044a5..eb9726ed 100644
--- a/src/custom_keyword.rs
+++ b/src/custom_keyword.rs
@@ -26,8 +26,8 @@
///
/// - Field access to its span — `let sp = whatever_token.span`
///
-/// [Peeking]: parse::ParseBuffer::peek
-/// [Parsing]: parse::ParseBuffer::parse
+/// [Peeking]: crate::parse::ParseBuffer::peek
+/// [Parsing]: crate::parse::ParseBuffer::parse
/// [Printing]: quote::ToTokens
/// [`Span`]: proc_macro2::Span
///
diff --git a/src/custom_punctuation.rs b/src/custom_punctuation.rs
index 70dff428..2156ec2c 100644
--- a/src/custom_punctuation.rs
+++ b/src/custom_punctuation.rs
@@ -22,8 +22,8 @@
///
/// - Field access to its spans — `let spans = lrarrow.spans`
///
-/// [Peeking]: parse::ParseBuffer::peek
-/// [Parsing]: parse::ParseBuffer::parse
+/// [Peeking]: crate::parse::ParseBuffer::peek
+/// [Parsing]: crate::parse::ParseBuffer::parse
/// [Printing]: quote::ToTokens
/// [`Span`]: proc_macro2::Span
///
diff --git a/src/data.rs b/src/data.rs
index b217b8ca..bb6a854f 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -236,7 +236,6 @@ ast_struct! {
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
-
use crate::ext::IdentExt;
use crate::parse::discouraged::Speculative;
use crate::parse::{Parse, ParseStream, Result};
@@ -405,12 +404,10 @@ pub mod parsing {
#[cfg(feature = "printing")]
mod printing {
use super::*;
-
+ use crate::print::TokensOrDefault;
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt};
- use crate::print::TokensOrDefault;
-
impl ToTokens for Variant {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(&self.attrs);
diff --git a/src/derive.rs b/src/derive.rs
index 3fa9d89a..cbfd0da5 100644
--- a/src/derive.rs
+++ b/src/derive.rs
@@ -88,7 +88,6 @@ ast_struct! {
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
-
use crate::parse::{Parse, ParseStream, Result};
impl Parse for DeriveInput {
@@ -221,12 +220,10 @@ pub mod parsing {
#[cfg(feature = "printing")]
mod printing {
use super::*;
-
- use proc_macro2::TokenStream;
- use quote::ToTokens;
-
use crate::attr::FilterAttrs;
use crate::print::TokensOrDefault;
+ use proc_macro2::TokenStream;
+ use quote::ToTokens;
impl ToTokens for DeriveInput {
fn to_tokens(&self, tokens: &mut TokenStream) {
diff --git a/src/error.rs b/src/error.rs
index dba34f92..8d65a1b4 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,17 +1,15 @@
-use std::fmt::{self, Debug, Display};
-use std::iter::FromIterator;
-use std::slice;
-use std::vec;
-
+#[cfg(feature = "parsing")]
+use crate::buffer::Cursor;
+use crate::thread::ThreadBound;
use proc_macro2::{
Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;
-
-#[cfg(feature = "parsing")]
-use crate::buffer::Cursor;
-use crate::thread::ThreadBound;
+use std::fmt::{self, Debug, Display};
+use std::iter::FromIterator;
+use std::slice;
+use std::vec;
/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;
diff --git a/src/expr.rs b/src/expr.rs
index 2fe0e0b5..45dd0ce3 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -994,7 +994,6 @@ pub(crate) fn requires_terminator(expr: &Expr) -> bool {
#[cfg(feature = "parsing")]
pub(crate) mod parsing {
use super::*;
-
use crate::parse::{Parse, ParseStream, Result};
use crate::path;
use std::cmp::Ordering;
@@ -2589,14 +2588,12 @@ pub(crate) mod parsing {
#[cfg(feature = "printing")]
pub(crate) mod printing {
use super::*;
-
- use proc_macro2::{Literal, TokenStream};
- use quote::{ToTokens, TokenStreamExt};
-
#[cfg(feature = "full")]
use crate::attr::FilterAttrs;
#[cfg(feature = "full")]
use crate::print::TokensOrDefault;
+ use proc_macro2::{Literal, TokenStream};
+ use quote::{ToTokens, TokenStreamExt};
// If the given expression is a bare `ExprStruct`, wraps it in parenthesis
// before appending it to `TokenStream`.
diff --git a/src/ext.rs b/src/ext.rs
index 4f9bc145..98d5550f 100644
--- a/src/ext.rs
+++ b/src/ext.rs
@@ -2,14 +2,12 @@
//!
//! *This module is available only if Syn is built with the `"parsing"` feature.*
-use proc_macro2::Ident;
-
-use crate::parse::{ParseStream, Result};
-
use crate::buffer::Cursor;
use crate::parse::Peek;
+use crate::parse::{ParseStream, Result};
use crate::sealed::lookahead;
use crate::token::CustomToken;
+use proc_macro2::Ident;
/// Additional methods for `Ident` not provided by proc-macro2 or libproc_macro.
///
diff --git a/src/file.rs b/src/file.rs
index c8fab63c..4a1a8196 100644
--- a/src/file.rs
+++ b/src/file.rs
@@ -79,7 +79,6 @@ ast_struct! {
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
-
use crate::parse::{Parse, ParseStream, Result};
impl Parse for File {
diff --git a/src/generics.rs b/src/generics.rs
index 05e8ef5c..db6de9d2 100644
--- a/src/generics.rs
+++ b/src/generics.rs
@@ -563,7 +563,6 @@ ast_struct! {
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
-
use crate::parse::{Parse, ParseStream, Result};
impl Parse for Generics {
@@ -945,15 +944,13 @@ pub mod parsing {
#[cfg(feature = "printing")]
mod printing {
use super::*;
-
+ use crate::attr::FilterAttrs;
+ use crate::print::TokensOrDefault;
use proc_macro2::TokenStream;
#[cfg(feature = "full")]
use proc_macro2::TokenTree;
use quote::{ToTokens, TokenStreamExt};
- use crate::attr::FilterAttrs;
- use crate::print::TokensOrDefault;
-
impl ToTokens for Generics {
fn to_tokens(&self, tokens: &mut TokenStream) {
if self.params.is_empty() {
diff --git a/src/group.rs b/src/group.rs
index ed5b151c..3c23f80f 100644
--- a/src/group.rs
+++ b/src/group.rs
@@ -1,8 +1,7 @@
-use proc_macro2::{Delimiter, Span};
-
use crate::error::Result;
use crate::parse::ParseBuffer;
use crate::token;
+use proc_macro2::{Delimiter, Span};
// Not public API.
#[doc(hidden)]
diff --git a/src/item.rs b/src/item.rs
index 0d8f7d3d..b7759c71 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -856,7 +856,6 @@ impl Receiver {
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
-
use crate::ext::IdentExt;
use crate::parse::discouraged::Speculative;
use crate::parse::{Parse, ParseBuffer, ParseStream, Result};
@@ -876,7 +875,7 @@ pub mod parsing {
let lookahead = ahead.lookahead1();
let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead) {
let vis: Visibility = input.parse()?;
- let sig = parse_signature(input)?;
+ let sig: Signature = input.parse()?;
if input.peek(Token![;]) {
input.parse::<Token![;]>()?;
Ok(Item::Verbatim(verbatim::between(begin, input)))
@@ -1335,46 +1334,45 @@ pub mod parsing {
&& fork.peek(Token![fn])
}
- fn parse_signature(input: ParseStream) -> Result<Signature> {
- let constness: Option<Token![const]> = input.parse()?;
- let asyncness: Option<Token![async]> = input.parse()?;
- let unsafety: Option<Token![unsafe]> = input.parse()?;
- let abi: Option<Abi> = input.parse()?;
- let fn_token: Token![fn] = input.parse()?;
- let ident: Ident = input.parse()?;
- let generics: Generics = input.parse()?;
+ impl Parse for Signature {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let constness: Option<Token![const]> = input.parse()?;
+ let asyncness: Option<Token![async]> = input.parse()?;
+ let unsafety: Option<Token![unsafe]> = input.parse()?;
+ let abi: Option<Abi> = input.parse()?;
+ let fn_token: Token![fn] = input.parse()?;
+ let ident: Ident = input.parse()?;
+ let mut generics: Generics = input.parse()?;
- let content;
- let paren_token = parenthesized!(content in input);
- let mut inputs = parse_fn_args(&content)?;
- let variadic = pop_variadic(&mut inputs);
+ let content;
+ let paren_token = parenthesized!(content in input);
+ let mut inputs = parse_fn_args(&content)?;
+ let variadic = pop_variadic(&mut inputs);
- let output: ReturnType = input.parse()?;
- let where_clause: Option<WhereClause> = input.parse()?;
+ let output: ReturnType = input.parse()?;
+ generics.where_clause = input.parse()?;
- Ok(Signature {
- constness,
- asyncness,
- unsafety,
- abi,
- fn_token,
- ident,
- paren_token,
- inputs,
- output,
- variadic,
- generics: Generics {
- where_clause,
- ..generics
- },
- })
+ Ok(Signature {
+ constness,
+ asyncness,
+ unsafety,
+ abi,
+ fn_token,
+ ident,
+ paren_token,
+ inputs,
+ output,
+ variadic,
+ generics,
+ })
+ }
}
impl Parse for ItemFn {
fn parse(input: ParseStream) -> Result<Self> {
let outer_attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
- let sig = parse_signature(input)?;
+ let sig: Signature = input.parse()?;
parse_rest_of_fn(input, outer_attrs, vis, sig)
}
}
@@ -1585,7 +1583,7 @@ pub mod parsing {
let lookahead = ahead.lookahead1();
let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead) {
let vis: Visibility = input.parse()?;
- let sig = parse_signature(input)?;
+ let sig: Signature = input.parse()?;
if input.peek(token::Brace) {
let content;
braced!(content in input);
@@ -1658,7 +1656,7 @@ pub mod parsing {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
- let sig = parse_signature(input)?;
+ let sig: Signature = input.parse()?;
let semi_token: Token![;] = input.parse()?;
Ok(ForeignItemFn {
attrs,
@@ -2152,7 +2150,7 @@ pub mod parsing {
impl Parse for TraitItemMethod {
fn parse(input: ParseStream) -> Result<Self> {
let outer_attrs = input.call(Attribute::parse_outer)?;
- let sig = parse_signature(input)?;
+ let sig: Signature = input.parse()?;
let lookahead = input.lookahead1();
let (brace_token, inner_attrs, stmts, semi_token) = if lookahead.peek(token::Brace) {
@@ -2286,7 +2284,7 @@ pub mod parsing {
|| input.peek3(Token![,])
|| input.peek3(Token![>]))
|| input.peek2(Token![const]));
- let generics: Generics = if has_generics {
+ let mut generics: Generics = if has_generics {
input.parse()?
} else {
Generics::default()
@@ -2313,7 +2311,7 @@ pub mod parsing {
})();
let self_ty: Type = input.parse()?;
- let where_clause: Option<WhereClause> = input.parse()?;
+ generics.where_clause = input.parse()?;
let content;
let brace_token = braced!(content in input);
@@ -2332,10 +2330,7 @@ pub mod parsing {
defaultness,
unsafety,
impl_token,
- generics: Generics {
- where_clause,
- ..generics
- },
+ generics,
trait_,
self_ty: Box::new(self_ty),
brace_token,
@@ -2453,7 +2448,7 @@ pub mod parsing {
let mut attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let defaultness: Option<Token![default]> = input.parse()?;
- let sig = parse_signature(input)?;
+ let sig: Signature = input.parse()?;
let block = if let Some(semi) = input.parse::<Option<Token![;]>>()? {
// Accept methods without a body in an impl block because
@@ -2577,13 +2572,11 @@ pub mod parsing {
#[cfg(feature = "printing")]
mod printing {
use super::*;
-
- use proc_macro2::TokenStream;
- use quote::{ToTokens, TokenStreamExt};
-
use crate::attr::FilterAttrs;
use crate::print::TokensOrDefault;
use crate::punctuated::Pair;
+ use proc_macro2::TokenStream;
+ use quote::{ToTokens, TokenStreamExt};
impl ToTokens for ItemExternCrate {
fn to_tokens(&self, tokens: &mut TokenStream) {
diff --git a/src/lib.rs b/src/lib.rs
index 3da50673..3a34eaa6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -250,7 +250,7 @@
//! dynamic library libproc_macro from rustc toolchain.
// Syn types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/syn/1.0.40")]
+#![doc(html_root_url = "https://docs.rs/syn/1.0.48")]
#![deny(clippy::all, clippy::pedantic)]
// Ignored clippy lints.
#![allow(
@@ -261,6 +261,7 @@
clippy::inherent_to_string,
clippy::large_enum_variant,
clippy::manual_non_exhaustive,
+ clippy::manual_strip,
clippy::match_like_matches_macro,
clippy::match_on_vec_items,
clippy::needless_doctest_main,
diff --git a/src/lifetime.rs b/src/lifetime.rs
index 959cc5f9..19f8a22f 100644
--- a/src/lifetime.rs
+++ b/src/lifetime.rs
@@ -1,9 +1,8 @@
+use proc_macro2::{Ident, Span};
use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};
-use proc_macro2::{Ident, Span};
-
#[cfg(feature = "parsing")]
use crate::lookahead;
@@ -115,7 +114,6 @@ pub fn Lifetime(marker: lookahead::TokenMarker) -> Lifetime {
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
-
use crate::parse::{Parse, ParseStream, Result};
impl Parse for Lifetime {
@@ -132,7 +130,6 @@ pub mod parsing {
#[cfg(feature = "printing")]
mod printing {
use super::*;
-
use proc_macro2::{Punct, Spacing, TokenStream};
use quote::{ToTokens, TokenStreamExt};
diff --git a/src/lit.rs b/src/lit.rs
index ee77e75b..e45b81ba 100644
--- a/src/lit.rs
+++ b/src/lit.rs
@@ -1,23 +1,18 @@
-use proc_macro2::{Literal, Span};
-use std::fmt::{self, Display};
-use std::str::{self, FromStr};
-
+#[cfg(feature = "parsing")]
+use crate::lookahead;
+#[cfg(feature = "parsing")]
+use crate::parse::{Parse, Parser};
+use crate::{Error, Result};
#[cfg(feature = "printing")]
use proc_macro2::Ident;
-
#[cfg(feature = "parsing")]
use proc_macro2::TokenStream;
-
use proc_macro2::TokenTree;
-
+use proc_macro2::{Literal, Span};
+use std::fmt::{self, Display};
#[cfg(feature = "extra-traits")]
use std::hash::{Hash, Hasher};
-
-#[cfg(feature = "parsing")]
-use crate::lookahead;
-#[cfg(feature = "parsing")]
-use crate::parse::{Parse, Parser};
-use crate::{Error, Result};
+use std::str::{self, FromStr};
ast_enum_of_structs! {
/// A Rust literal such as a string or integer or boolean.
@@ -108,7 +103,7 @@ struct LitIntRepr {
ast_struct! {
/// A floating point literal: `1f64` or `1.0e10f64`.
///
- /// Must be finite. May not be infinte or NaN.
+ /// Must be finite. May not be infinite or NaN.
pub struct LitFloat {
repr: Box<LitFloatRepr>,
}
@@ -730,21 +725,19 @@ pub mod parsing {
let mut repr = lit.to_string();
repr.insert(0, '-');
- if !(repr.ends_with("f32") || repr.ends_with("f64")) {
- if let Some((digits, suffix)) = value::parse_lit_int(&repr) {
- if let Some(mut token) = value::to_literal(&repr, &digits, &suffix) {
- token.set_span(span);
- return Some((
- Lit::Int(LitInt {
- repr: Box::new(LitIntRepr {
- token,
- digits,
- suffix,
- }),
+ if let Some((digits, suffix)) = value::parse_lit_int(&repr) {
+ if let Some(mut token) = value::to_literal(&repr, &digits, &suffix) {
+ token.set_span(span);
+ return Some((
+ Lit::Int(LitInt {
+ repr: Box::new(LitIntRepr {
+ token,
+ digits,
+ suffix,
}),
- rest,
- ));
- }
+ }),
+ rest,
+ ));
}
}
@@ -766,8 +759,8 @@ pub mod parsing {
impl Parse for LitStr {
fn parse(input: ParseStream) -> Result<Self> {
let head = input.fork();
- match input.parse()? {
- Lit::Str(lit) => Ok(lit),
+ match input.parse() {
+ Ok(Lit::Str(lit)) => Ok(lit),
_ => Err(head.error("expected string literal")),
}
}
@@ -776,8 +769,8 @@ pub mod parsing {
impl Parse for LitByteStr {
fn parse(input: ParseStream) -> Result<Self> {
let head = input.fork();
- match input.parse()? {
- Lit::ByteStr(lit) => Ok(lit),
+ match input.parse() {
+ Ok(Lit::ByteStr(lit)) => Ok(lit),
_ => Err(head.error("expected byte string literal")),
}
}
@@ -786,8 +779,8 @@ pub mod parsing {
impl Parse for LitByte {
fn parse(input: ParseStream) -> Result<Self> {
let head = input.fork();
- match input.parse()? {
- Lit::Byte(lit) => Ok(lit),
+ match input.parse() {
+ Ok(Lit::Byte(lit)) => Ok(lit),
_ => Err(head.error("expected byte literal")),
}
}
@@ -796,8 +789,8 @@ pub mod parsing {
impl Parse for LitChar {
fn parse(input: ParseStream) -> Result<Self> {
let head = input.fork();
- match input.parse()? {
- Lit::Char(lit) => Ok(lit),
+ match input.parse() {
+ Ok(Lit::Char(lit)) => Ok(lit),
_ => Err(head.error("expected character literal")),
}
}
@@ -806,8 +799,8 @@ pub mod parsing {
impl Parse for LitInt {
fn parse(input: ParseStream) -> Result<Self> {
let head = input.fork();
- match input.parse()? {
- Lit::Int(lit) => Ok(lit),
+ match input.parse() {
+ Ok(Lit::Int(lit)) => Ok(lit),
_ => Err(head.error("expected integer literal")),
}
}
@@ -816,8 +809,8 @@ pub mod parsing {
impl Parse for LitFloat {
fn parse(input: ParseStream) -> Result<Self> {
let head = input.fork();
- match input.parse()? {
- Lit::Float(lit) => Ok(lit),
+ match input.parse() {
+ Ok(Lit::Float(lit)) => Ok(lit),
_ => Err(head.error("expected floating point literal")),
}
}
@@ -826,8 +819,8 @@ pub mod parsing {
impl Parse for LitBool {
fn parse(input: ParseStream) -> Result<Self> {
let head = input.fork();
- match input.parse()? {
- Lit::Bool(lit) => Ok(lit),
+ match input.parse() {
+ Ok(Lit::Bool(lit)) => Ok(lit),
_ => Err(head.error("expected boolean literal")),
}
}
@@ -925,16 +918,14 @@ mod value {
});
}
b'0'..=b'9' | b'-' => {
- if !(repr.ends_with("f32") || repr.ends_with("f64")) {
- if let Some((digits, suffix)) = parse_lit_int(&repr) {
- return Lit::Int(LitInt {
- repr: Box::new(LitIntRepr {
- token,
- digits,
- suffix,
- }),
- });
- }
+ if let Some((digits, suffix)) = parse_lit_int(&repr) {
+ return Lit::Int(LitInt {
+ repr: Box::new(LitIntRepr {
+ token,
+ digits,
+ suffix,
+ }),
+ });
}
if let Some((digits, suffix)) = parse_lit_float(&repr) {
return Lit::Float(LitFloat {
@@ -1294,27 +1285,28 @@ mod value {
s = &s[1..];
let mut ch = 0;
- for _ in 0..6 {
+ let mut digits = 0;
+ loop {
let b = byte(s, 0);
- match b {
- b'0'..=b'9' => {
- ch *= 0x10;
- ch += u32::from(b - b'0');
- s = &s[1..];
- }
- b'a'..=b'f' => {
- ch *= 0x10;
- ch += u32::from(10 + b - b'a');
- s = &s[1..];
- }
- b'A'..=b'F' => {
- ch *= 0x10;
- ch += u32::from(10 + b - b'A');
+ let digit = match b {
+ b'0'..=b'9' => b - b'0',
+ b'a'..=b'f' => 10 + b - b'a',
+ b'A'..=b'F' => 10 + b - b'A',
+ b'_' if digits > 0 => {
s = &s[1..];
+ continue;
}
+ b'}' if digits == 0 => panic!("invalid empty unicode escape"),
b'}' => break,
_ => panic!("unexpected non-hex character after \\u"),
+ };
+ if digits == 6 {
+ panic!("overlong unicode escape (must have at most 6 hex digits)");
}
+ ch *= 0x10;
+ ch += u32::from(digit);
+ digits += 1;
+ s = &s[1..];
}
assert!(byte(s, 0) == b'}');
s = &s[1..];
@@ -1351,7 +1343,7 @@ mod value {
};
let mut value = BigInt::new();
- loop {
+ 'outer: loop {
let b = byte(s, 0);
let digit = match b {
b'0'..=b'9' => b - b'0',
@@ -1361,10 +1353,32 @@ mod value {
s = &s[1..];
continue;
}
- // NOTE: Looking at a floating point literal, we don't want to
- // consider these integers.
+ // If looking at a floating point literal, we don't want to
+ // consider it an integer.
b'.' if base == 10 => return None,
- b'e' | b'E' if base == 10 => return None,
+ b'e' | b'E' if base == 10 => {
+ let mut has_exp = false;
+ for (i, b) in s[1..].bytes().enumerate() {
+ match b {
+ b'_' => {}
+ b'-' | b'+' => return None,
+ b'0'..=b'9' => has_exp = true,
+ _ => {
+ let suffix = &s[1 + i..];
+ if has_exp && crate::ident::xid_ok(suffix) {
+ return None;
+ } else {
+ break 'outer;
+ }
+ }
+ }
+ }
+ if has_exp {
+ return None;
+ } else {
+ break;
+ }
+ }
_ => break,
};
@@ -1430,6 +1444,14 @@ mod value {
bytes[write] = b'.';
}
b'e' | b'E' => {
+ match bytes[read + 1..]
+ .iter()
+ .find(|b| **b != b'_')
+ .unwrap_or(&b'\0')
+ {
+ b'-' | b'+' | b'0'..=b'9' => {}
+ _ => break,
+ }
if has_e {
if has_exponent {
break;
@@ -1475,10 +1497,12 @@ mod value {
pub fn to_literal(repr: &str, digits: &str, suffix: &str) -> Option<Literal> {
if repr.starts_with('-') {
+ let f64_parse_finite = || digits.parse().ok().filter(|x: &f64| x.is_finite());
+ let f32_parse_finite = || digits.parse().ok().filter(|x: &f32| x.is_finite());
if suffix == "f64" {
- digits.parse().ok().map(Literal::f64_suffixed)
+ f64_parse_finite().map(Literal::f64_suffixed)
} else if suffix == "f32" {
- digits.parse().ok().map(Literal::f32_suffixed)
+ f32_parse_finite().map(Literal::f32_suffixed)
} else if suffix == "i64" {
digits.parse().ok().map(Literal::i64_suffixed)
} else if suffix == "i32" {
@@ -1490,7 +1514,7 @@ mod value {
} else if !suffix.is_empty() {
None
} else if digits.contains('.') {
- digits.parse().ok().map(Literal::f64_unsuffixed)
+ f64_parse_finite().map(Literal::f64_unsuffixed)
} else {
digits.parse().ok().map(Literal::i64_unsuffixed)
}
diff --git a/src/lookahead.rs b/src/lookahead.rs
index 6a67909f..f0ed628e 100644
--- a/src/lookahead.rs
+++ b/src/lookahead.rs
@@ -1,12 +1,10 @@
-use std::cell::RefCell;
-
-use proc_macro2::{Delimiter, Span};
-
use crate::buffer::Cursor;
use crate::error::{self, Error};
use crate::sealed::lookahead::Sealed;
use crate::span::IntoSpans;
use crate::token::Token;
+use proc_macro2::{Delimiter, Span};
+use std::cell::RefCell;
/// Support for checking the next token in a stream to decide how to parse.
///
diff --git a/src/mac.rs b/src/mac.rs
index de288a34..374400c9 100644
--- a/src/mac.rs
+++ b/src/mac.rs
@@ -168,7 +168,6 @@ pub fn parse_delimiter(input: ParseStream) -> Result<(MacroDelimiter, TokenStrea
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
-
use crate::parse::{Parse, ParseStream, Result};
impl Parse for Macro {
diff --git a/src/op.rs b/src/op.rs
index d254673b..f9edc635 100644
--- a/src/op.rs
+++ b/src/op.rs
@@ -81,7 +81,6 @@ ast_enum! {
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
-
use crate::parse::{Parse, ParseStream, Result};
fn parse_binop(input: ParseStream) -> Result<BinOp> {
diff --git a/src/parse.rs b/src/parse.rs
index abb4c4c1..f1aecada 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -189,26 +189,24 @@
#[path = "discouraged.rs"]
pub mod discouraged;
-use std::cell::Cell;
-use std::fmt::{self, Debug, Display};
-use std::marker::PhantomData;
-use std::mem;
-use std::ops::Deref;
-use std::rc::Rc;
-use std::str::FromStr;
-
+use crate::buffer::{Cursor, TokenBuffer};
+use crate::error;
+use crate::lookahead;
#[cfg(all(
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
feature = "proc-macro"
))]
use crate::proc_macro;
-use proc_macro2::{self, Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};
-
-use crate::buffer::{Cursor, TokenBuffer};
-use crate::error;
-use crate::lookahead;
use crate::punctuated::Punctuated;
use crate::token::Token;
+use proc_macro2::{self, Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};
+use std::cell::Cell;
+use std::fmt::{self, Debug, Display};
+use std::marker::PhantomData;
+use std::mem;
+use std::ops::Deref;
+use std::rc::Rc;
+use std::str::FromStr;
pub use crate::error::{Error, Result};
pub use crate::lookahead::{Lookahead1, Peek};
diff --git a/src/parse_macro_input.rs b/src/parse_macro_input.rs
index c8fc1cea..79c0de40 100644
--- a/src/parse_macro_input.rs
+++ b/src/parse_macro_input.rs
@@ -46,6 +46,42 @@
///
/// <br>
///
+/// # Usage with Parser
+///
+/// This macro can also be used with the [`Parser` trait] for types that have
+/// multiple ways that they can be parsed.
+///
+/// [`Parser` trait]: crate::rustdoc_workaround::parse_module::Parser
+///
+/// ```
+/// # extern crate proc_macro;
+/// #
+/// # use proc_macro::TokenStream;
+/// # use syn::{parse_macro_input, Result};
+/// # use syn::parse::ParseStream;
+/// #
+/// # struct MyMacroInput {}
+/// #
+/// impl MyMacroInput {
+/// fn parse_alternate(input: ParseStream) -> Result<Self> {
+/// /* ... */
+/// # Ok(MyMacroInput {})
+/// }
+/// }
+///
+/// # const IGNORE: &str = stringify! {
+/// #[proc_macro]
+/// # };
+/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
+/// let input = parse_macro_input!(tokens with MyMacroInput::parse_alternate);
+///
+/// /* ... */
+/// # "".parse().unwrap()
+/// }
+/// ```
+///
+/// <br>
+///
/// # Expansion
///
/// `parse_macro_input!($variable as $Type)` expands to something like:
@@ -77,6 +113,14 @@ macro_rules! parse_macro_input {
}
}
};
+ ($tokenstream:ident with $parser:path) => {
+ match $crate::parse::Parser::parse($parser, $tokenstream) {
+ $crate::export::Ok(data) => data,
+ $crate::export::Err(err) => {
+ return $crate::export::TokenStream::from(err.to_compile_error());
+ }
+ }
+ };
($tokenstream:ident) => {
$crate::parse_macro_input!($tokenstream as _)
};
diff --git a/src/parse_quote.rs b/src/parse_quote.rs
index 66aa818c..772671be 100644
--- a/src/parse_quote.rs
+++ b/src/parse_quote.rs
@@ -6,7 +6,7 @@
/// The return type can be any syntax tree node that implements the [`Parse`]
/// trait.
///
-/// [`Parse`]: parse::Parse
+/// [`Parse`]: crate::parse::Parse
///
/// ```
/// use quote::quote;
@@ -58,7 +58,7 @@
/// `P` with optional trailing punctuation
/// - [`Vec<Stmt>`] — parses the same as `Block::parse_within`
///
-/// [`Punctuated<T, P>`]: punctuated::Punctuated
+/// [`Punctuated<T, P>`]: crate::punctuated::Punctuated
/// [`Vec<Stmt>`]: Block::parse_within
///
/// # Panics
diff --git a/src/pat.rs b/src/pat.rs
index e9576a23..473ee1c8 100644
--- a/src/pat.rs
+++ b/src/pat.rs
@@ -277,7 +277,6 @@ ast_struct! {
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
-
use crate::ext::IdentExt;
use crate::parse::{Parse, ParseBuffer, ParseStream, Result};
use crate::path;
@@ -286,22 +285,20 @@ pub mod parsing {
fn parse(input: ParseStream) -> Result<Self> {
let begin = input.fork();
let lookahead = input.lookahead1();
- if lookahead.peek(Ident)
- && ({
- input.peek2(Token![::])
- || input.peek2(Token![!])
- || input.peek2(token::Brace)
- || input.peek2(token::Paren)
- || input.peek2(Token![..])
- && !{
- let ahead = input.fork();
- ahead.parse::<Ident>()?;
- ahead.parse::<RangeLimits>()?;
- ahead.is_empty() || ahead.peek(Token![,])
- }
- })
- || input.peek(Token![self]) && input.peek2(Token![::])
- || lookahead.peek(Token![::])
+ if {
+ let ahead = input.fork();
+ ahead.parse::<Option<Ident>>()?.is_some()
+ && (ahead.peek(Token![::])
+ || ahead.peek(Token![!])
+ || ahead.peek(token::Brace)
+ || ahead.peek(token::Paren)
+ || ahead.peek(Token![..])
+ && ahead.parse::<RangeLimits>().is_ok()
+ && !(ahead.is_empty() || ahead.peek(Token![,])))
+ } || {
+ let ahead = input.fork();
+ ahead.parse::<Option<Token![self]>>()?.is_some() && ahead.peek(Token![::])
+ } || lookahead.peek(Token![::])
|| lookahead.peek(Token![<])
|| input.peek(Token![Self])
|| input.peek(Token![super])
@@ -710,12 +707,10 @@ pub mod parsing {
#[cfg(feature = "printing")]
mod printing {
use super::*;
-
+ use crate::attr::FilterAttrs;
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt};
- use crate::attr::FilterAttrs;
-
impl ToTokens for PatWild {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
diff --git a/src/path.rs b/src/path.rs
index 15c0fcc6..217a72e3 100644
--- a/src/path.rs
+++ b/src/path.rs
@@ -555,11 +555,10 @@ pub mod parsing {
#[cfg(feature = "printing")]
mod printing {
use super::*;
-
+ use crate::print::TokensOrDefault;
use proc_macro2::TokenStream;
use quote::ToTokens;
-
- use crate::print::TokensOrDefault;
+ use std::cmp;
impl ToTokens for Path {
fn to_tokens(&self, tokens: &mut TokenStream) {
@@ -709,11 +708,7 @@ mod printing {
qself.lt_token.to_tokens(tokens);
qself.ty.to_tokens(tokens);
- let pos = if qself.position > 0 && qself.position >= path.segments.len() {
- path.segments.len() - 1
- } else {
- qself.position
- };
+ let pos = cmp::min(qself.position, path.segments.len());
let mut segments = path.segments.pairs();
if pos > 0 {
TokensOrDefault(&qself.as_token).to_tokens(tokens);
diff --git a/src/stmt.rs b/src/stmt.rs
index b06e843d..873e713a 100644
--- a/src/stmt.rs
+++ b/src/stmt.rs
@@ -46,7 +46,6 @@ ast_struct! {
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
-
use crate::parse::discouraged::Speculative;
use crate::parse::{Parse, ParseStream, Result};
use proc_macro2::TokenStream;
@@ -274,7 +273,6 @@ pub mod parsing {
#[cfg(feature = "printing")]
mod printing {
use super::*;
-
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt};
diff --git a/src/token.rs b/src/token.rs
index 8539378c..e5c6d1f8 100644
--- a/src/token.rs
+++ b/src/token.rs
@@ -88,24 +88,6 @@
//! [Printing]: https://docs.rs/quote/1.0/quote/trait.ToTokens.html
//! [`Span`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.Span.html
-#[cfg(feature = "extra-traits")]
-use std::cmp;
-#[cfg(feature = "extra-traits")]
-use std::fmt::{self, Debug};
-#[cfg(feature = "extra-traits")]
-use std::hash::{Hash, Hasher};
-use std::ops::{Deref, DerefMut};
-
-#[cfg(any(feature = "parsing", feature = "printing"))]
-use proc_macro2::Ident;
-use proc_macro2::Span;
-#[cfg(feature = "printing")]
-use proc_macro2::TokenStream;
-#[cfg(feature = "parsing")]
-use proc_macro2::{Delimiter, Literal, Punct, TokenTree};
-#[cfg(feature = "printing")]
-use quote::{ToTokens, TokenStreamExt};
-
use self::private::WithSpan;
#[cfg(feature = "parsing")]
use crate::buffer::Cursor;
@@ -120,6 +102,22 @@ use crate::lookahead;
#[cfg(feature = "parsing")]
use crate::parse::{Parse, ParseStream};
use crate::span::IntoSpans;
+#[cfg(any(feature = "parsing", feature = "printing"))]
+use proc_macro2::Ident;
+use proc_macro2::Span;
+#[cfg(feature = "printing")]
+use proc_macro2::TokenStream;
+#[cfg(feature = "parsing")]
+use proc_macro2::{Delimiter, Literal, Punct, TokenTree};
+#[cfg(feature = "printing")]
+use quote::{ToTokens, TokenStreamExt};
+#[cfg(feature = "extra-traits")]
+use std::cmp;
+#[cfg(feature = "extra-traits")]
+use std::fmt::{self, Debug};
+#[cfg(feature = "extra-traits")]
+use std::hash::{Hash, Hasher};
+use std::ops::{Deref, DerefMut};
/// Marker trait for types that represent single tokens.
///
@@ -750,105 +748,105 @@ macro_rules! export_token_macro {
// https://github.com/rust-lang/rust/issues/45939
#[macro_export]
macro_rules! Token {
- (abstract) => { $crate::token::Abstract };
- (as) => { $crate::token::As };
- (async) => { $crate::token::Async };
- (auto) => { $crate::token::Auto };
+ [abstract] => { $crate::token::Abstract };
+ [as] => { $crate::token::As };
+ [async] => { $crate::token::Async };
+ [auto] => { $crate::token::Auto };
$($await_rule => { $crate::token::Await };)*
- (become) => { $crate::token::Become };
- (box) => { $crate::token::Box };
- (break) => { $crate::token::Break };
- (const) => { $crate::token::Const };
- (continue) => { $crate::token::Continue };
- (crate) => { $crate::token::Crate };
- (default) => { $crate::token::Default };
- (do) => { $crate::token::Do };
- (dyn) => { $crate::token::Dyn };
- (else) => { $crate::token::Else };
- (enum) => { $crate::token::Enum };
- (extern) => { $crate::token::Extern };
- (final) => { $crate::token::Final };
- (fn) => { $crate::token::Fn };
- (for) => { $crate::token::For };
- (if) => { $crate::token::If };
- (impl) => { $crate::token::Impl };
- (in) => { $crate::token::In };
- (let) => { $crate::token::Let };
- (loop) => { $crate::token::Loop };
- (macro) => { $crate::token::Macro };
- (match) => { $crate::token::Match };
- (mod) => { $crate::token::Mod };
- (move) => { $crate::token::Move };
- (mut) => { $crate::token::Mut };
- (override) => { $crate::token::Override };
- (priv) => { $crate::token::Priv };
- (pub) => { $crate::token::Pub };
- (ref) => { $crate::token::Ref };
- (return) => { $crate::token::Return };
- (Self) => { $crate::token::SelfType };
- (self) => { $crate::token::SelfValue };
- (static) => { $crate::token::Static };
- (struct) => { $crate::token::Struct };
- (super) => { $crate::token::Super };
- (trait) => { $crate::token::Trait };
- (try) => { $crate::token::Try };
- (type) => { $crate::token::Type };
- (typeof) => { $crate::token::Typeof };
- (union) => { $crate::token::Union };
- (unsafe) => { $crate::token::Unsafe };
- (unsized) => { $crate::token::Unsized };
- (use) => { $crate::token::Use };
- (virtual) => { $crate::token::Virtual };
- (where) => { $crate::token::Where };
- (while) => { $crate::token::While };
- (yield) => { $crate::token::Yield };
- (+) => { $crate::token::Add };
- (+=) => { $crate::token::AddEq };
- (&) => { $crate::token::And };
- (&&) => { $crate::token::AndAnd };
- (&=) => { $crate::token::AndEq };
- (@) => { $crate::token::At };
- (!) => { $crate::token::Bang };
- (^) => { $crate::token::Caret };
- (^=) => { $crate::token::CaretEq };
- (:) => { $crate::token::Colon };
- (::) => { $crate::token::Colon2 };
- (,) => { $crate::token::Comma };
- (/) => { $crate::token::Div };
- (/=) => { $crate::token::DivEq };
- ($) => { $crate::token::Dollar };
- (.) => { $crate::token::Dot };
- (..) => { $crate::token::Dot2 };
- (...) => { $crate::token::Dot3 };
- (..=) => { $crate::token::DotDotEq };
- (=) => { $crate::token::Eq };
- (==) => { $crate::token::EqEq };
- (>=) => { $crate::token::Ge };
- (>) => { $crate::token::Gt };
- (<=) => { $crate::token::Le };
- (<) => { $crate::token::Lt };
- (*=) => { $crate::token::MulEq };
- (!=) => { $crate::token::Ne };
- (|) => { $crate::token::Or };
- (|=) => { $crate::token::OrEq };
- (||) => { $crate::token::OrOr };
- (#) => { $crate::token::Pound };
- (?) => { $crate::token::Question };
- (->) => { $crate::token::RArrow };
- (<-) => { $crate::token::LArrow };
- (%) => { $crate::token::Rem };
- (%=) => { $crate::token::RemEq };
- (=>) => { $crate::token::FatArrow };
- (;) => { $crate::token::Semi };
- (<<) => { $crate::token::Shl };
- (<<=) => { $crate::token::ShlEq };
- (>>) => { $crate::token::Shr };
- (>>=) => { $crate::token::ShrEq };
- (*) => { $crate::token::Star };
- (-) => { $crate::token::Sub };
- (-=) => { $crate::token::SubEq };
- (~) => { $crate::token::Tilde };
- (_) => { $crate::token::Underscore };
+ [become] => { $crate::token::Become };
+ [box] => { $crate::token::Box };
+ [break] => { $crate::token::Break };
+ [const] => { $crate::token::Const };
+ [continue] => { $crate::token::Continue };
+ [crate] => { $crate::token::Crate };
+ [default] => { $crate::token::Default };
+ [do] => { $crate::token::Do };
+ [dyn] => { $crate::token::Dyn };
+ [else] => { $crate::token::Else };
+ [enum] => { $crate::token::Enum };
+ [extern] => { $crate::token::Extern };
+ [final] => { $crate::token::Final };
+ [fn] => { $crate::token::Fn };
+ [for] => { $crate::token::For };
+ [if] => { $crate::token::If };
+ [impl] => { $crate::token::Impl };
+ [in] => { $crate::token::In };
+ [let] => { $crate::token::Let };
+ [loop] => { $crate::token::Loop };
+ [macro] => { $crate::token::Macro };
+ [match] => { $crate::token::Match };
+ [mod] => { $crate::token::Mod };
+ [move] => { $crate::token::Move };
+ [mut] => { $crate::token::Mut };
+ [override] => { $crate::token::Override };
+ [priv] => { $crate::token::Priv };
+ [pub] => { $crate::token::Pub };
+ [ref] => { $crate::token::Ref };
+ [return] => { $crate::token::Return };
+ [Self] => { $crate::token::SelfType };
+ [self] => { $crate::token::SelfValue };
+ [static] => { $crate::token::Static };
+ [struct] => { $crate::token::Struct };
+ [super] => { $crate::token::Super };
+ [trait] => { $crate::token::Trait };
+ [try] => { $crate::token::Try };
+ [type] => { $crate::token::Type };
+ [typeof] => { $crate::token::Typeof };
+ [union] => { $crate::token::Union };
+ [unsafe] => { $crate::token::Unsafe };
+ [unsized] => { $crate::token::Unsized };
+ [use] => { $crate::token::Use };
+ [virtual] => { $crate::token::Virtual };
+ [where] => { $crate::token::Where };
+ [while] => { $crate::token::While };
+ [yield] => { $crate::token::Yield };
+ [+] => { $crate::token::Add };
+ [+=] => { $crate::token::AddEq };
+ [&] => { $crate::token::And };
+ [&&] => { $crate::token::AndAnd };
+ [&=] => { $crate::token::AndEq };
+ [@] => { $crate::token::At };
+ [!] => { $crate::token::Bang };
+ [^] => { $crate::token::Caret };
+ [^=] => { $crate::token::CaretEq };
+ [:] => { $crate::token::Colon };
+ [::] => { $crate::token::Colon2 };
+ [,] => { $crate::token::Comma };
+ [/] => { $crate::token::Div };
+ [/=] => { $crate::token::DivEq };
+ [$] => { $crate::token::Dollar };
+ [.] => { $crate::token::Dot };
+ [..] => { $crate::token::Dot2 };
+ [...] => { $crate::token::Dot3 };
+ [..=] => { $crate::token::DotDotEq };
+ [=] => { $crate::token::Eq };
+ [==] => { $crate::token::EqEq };
+ [>=] => { $crate::token::Ge };
+ [>] => { $crate::token::Gt };
+ [<=] => { $crate::token::Le };
+ [<] => { $crate::token::Lt };
+ [*=] => { $crate::token::MulEq };
+ [!=] => { $crate::token::Ne };
+ [|] => { $crate::token::Or };
+ [|=] => { $crate::token::OrEq };
+ [||] => { $crate::token::OrOr };
+ [#] => { $crate::token::Pound };
+ [?] => { $crate::token::Question };
+ [->] => { $crate::token::RArrow };
+ [<-] => { $crate::token::LArrow };
+ [%] => { $crate::token::Rem };
+ [%=] => { $crate::token::RemEq };
+ [=>] => { $crate::token::FatArrow };
+ [;] => { $crate::token::Semi };
+ [<<] => { $crate::token::Shl };
+ [<<=] => { $crate::token::ShlEq };
+ [>>] => { $crate::token::Shr };
+ [>>=] => { $crate::token::ShrEq };
+ [*] => { $crate::token::Star };
+ [-] => { $crate::token::Sub };
+ [-=] => { $crate::token::SubEq };
+ [~] => { $crate::token::Tilde };
+ [_] => { $crate::token::Underscore };
}
};
}
@@ -857,20 +855,19 @@ macro_rules! export_token_macro {
// https://github.com/rust-lang/rust/issues/57919
// We put the Token![await] rule in a place that is not lexed by old rustc.
#[cfg(not(syn_omit_await_from_token_macro))]
-include!("await.rs"); // export_token_macro![(await)];
+include!("await.rs"); // export_token_macro! {[await]}
#[cfg(syn_omit_await_from_token_macro)]
-export_token_macro![];
+export_token_macro! {}
// Not public API.
#[doc(hidden)]
#[cfg(feature = "parsing")]
pub mod parsing {
- use proc_macro2::{Spacing, Span};
-
use crate::buffer::Cursor;
use crate::error::{Error, Result};
use crate::parse::ParseStream;
use crate::span::FromSpans;
+ use proc_macro2::{Spacing, Span};
pub fn keyword(input: ParseStream, token: &str) -> Result<Span> {
input.step(|cursor| {
diff --git a/src/tt.rs b/src/tt.rs
index 8dba0627..d87c0ed4 100644
--- a/src/tt.rs
+++ b/src/tt.rs
@@ -1,6 +1,5 @@
-use std::hash::{Hash, Hasher};
-
use proc_macro2::{Delimiter, TokenStream, TokenTree};
+use std::hash::{Hash, Hasher};
pub struct TokenTreeHelper<'a>(pub &'a TokenTree);
diff --git a/src/ty.rs b/src/ty.rs
index fd7c97ea..fb90e26f 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -298,7 +298,6 @@ ast_enum! {
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
-
use crate::ext::IdentExt;
use crate::parse::{Parse, ParseStream, Result};
use crate::path;
@@ -964,12 +963,10 @@ pub mod parsing {
#[cfg(feature = "printing")]
mod printing {
use super::*;
-
- use proc_macro2::TokenStream;
- use quote::{ToTokens, TokenStreamExt};
-
use crate::attr::FilterAttrs;
use crate::print::TokensOrDefault;
+ use proc_macro2::TokenStream;
+ use quote::{ToTokens, TokenStreamExt};
impl ToTokens for TypeSlice {
fn to_tokens(&self, tokens: &mut TokenStream) {
diff --git a/tests/common/eq.rs b/tests/common/eq.rs
index 7589a075..4ec910b5 100644
--- a/tests/common/eq.rs
+++ b/tests/common/eq.rs
@@ -3,8 +3,6 @@ extern crate rustc_data_structures;
extern crate rustc_span;
extern crate rustc_target;
-use std::mem;
-
use rustc_ast::ast::{
AngleBracketedArg, AngleBracketedArgs, AnonConst, Arm, AssocItemKind, AssocTyConstraint,
AssocTyConstraintKind, Async, AttrId, AttrItem, AttrKind, AttrStyle, Attribute, BareFnTy,
@@ -19,17 +17,18 @@ use rustc_ast::ast::{
Pat, PatKind, Path, PathSegment, PolyTraitRef, QSelf, RangeEnd, RangeLimits, RangeSyntax, Stmt,
StmtKind, StrLit, StrStyle, StructField, TraitBoundModifier, TraitObjectSyntax, TraitRef, Ty,
TyKind, UintTy, UnOp, Unsafe, UnsafeSource, UseTree, UseTreeKind, Variant, VariantData,
- VisibilityKind, WhereBoundPredicate, WhereClause, WhereEqPredicate, WherePredicate,
+ Visibility, VisibilityKind, WhereBoundPredicate, WhereClause, WhereEqPredicate, WherePredicate,
WhereRegionPredicate,
};
use rustc_ast::ptr::P;
use rustc_ast::token::{self, CommentKind, DelimToken, Token, TokenKind};
-use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::Ident;
use rustc_span::{Span, Symbol, SyntaxContext};
+use std::mem;
pub trait SpanlessEq {
fn eq(&self, other: &Self) -> bool;
@@ -41,7 +40,7 @@ impl<T: SpanlessEq> SpanlessEq for P<T> {
}
}
-impl<T: SpanlessEq> SpanlessEq for Lrc<T> {
+impl<T: ?Sized + SpanlessEq> SpanlessEq for Lrc<T> {
fn eq(&self, other: &Self) -> bool {
SpanlessEq::eq(&**self, &**other)
}
@@ -57,12 +56,18 @@ impl<T: SpanlessEq> SpanlessEq for Option<T> {
}
}
-impl<T: SpanlessEq> SpanlessEq for Vec<T> {
+impl<T: SpanlessEq> SpanlessEq for [T] {
fn eq(&self, other: &Self) -> bool {
self.len() == other.len() && self.iter().zip(other).all(|(a, b)| SpanlessEq::eq(a, b))
}
}
+impl<T: SpanlessEq> SpanlessEq for Vec<T> {
+ fn eq(&self, other: &Self) -> bool {
+ <[T] as SpanlessEq>::eq(self, other)
+ }
+}
+
impl<T: SpanlessEq> SpanlessEq for ThinVec<T> {
fn eq(&self, other: &Self) -> bool {
self.len() == other.len()
@@ -260,10 +265,10 @@ spanless_eq_struct!(AngleBracketedArgs; span args);
spanless_eq_struct!(AnonConst; id value);
spanless_eq_struct!(Arm; attrs pat guard body span id is_placeholder);
spanless_eq_struct!(AssocTyConstraint; id ident kind span);
-spanless_eq_struct!(AttrItem; path args);
+spanless_eq_struct!(AttrItem; path args tokens);
spanless_eq_struct!(Attribute; kind id style span);
spanless_eq_struct!(BareFnTy; unsafety ext generic_params decl);
-spanless_eq_struct!(Block; stmts id rules span);
+spanless_eq_struct!(Block; stmts id rules span tokens);
spanless_eq_struct!(Crate; module attrs span proc_macros);
spanless_eq_struct!(EnumDef; variants);
spanless_eq_struct!(Expr; id kind span attrs !tokens);
@@ -272,7 +277,7 @@ spanless_eq_struct!(FieldPat; ident pat is_shorthand attrs id span is_placeholde
spanless_eq_struct!(FnDecl; inputs output);
spanless_eq_struct!(FnHeader; constness asyncness unsafety ext);
spanless_eq_struct!(FnSig; header decl span);
-spanless_eq_struct!(ForeignMod; abi items);
+spanless_eq_struct!(ForeignMod; unsafety abi items);
spanless_eq_struct!(GenericParam; id ident attrs bounds is_placeholder kind);
spanless_eq_struct!(Generics; params where_clause span);
spanless_eq_struct!(GlobalAsm; asm);
@@ -287,23 +292,24 @@ spanless_eq_struct!(Local; pat ty init id span attrs);
spanless_eq_struct!(MacCall; path args prior_type_ascription);
spanless_eq_struct!(MacCallStmt; mac style attrs);
spanless_eq_struct!(MacroDef; body macro_rules);
-spanless_eq_struct!(Mod; inner items inline);
+spanless_eq_struct!(Mod; inner unsafety items inline);
spanless_eq_struct!(MutTy; ty mutbl);
spanless_eq_struct!(Param; attrs ty pat id span is_placeholder);
spanless_eq_struct!(ParenthesizedArgs; span inputs output);
spanless_eq_struct!(Pat; id kind span tokens);
-spanless_eq_struct!(Path; span segments);
+spanless_eq_struct!(Path; span segments tokens);
spanless_eq_struct!(PathSegment; ident id args);
spanless_eq_struct!(PolyTraitRef; bound_generic_params trait_ref span);
spanless_eq_struct!(QSelf; ty path_span position);
-spanless_eq_struct!(Stmt; id kind span);
+spanless_eq_struct!(Stmt; id kind span tokens);
spanless_eq_struct!(StrLit; style symbol suffix span symbol_unescaped);
spanless_eq_struct!(StructField; attrs id span vis ident ty is_placeholder);
spanless_eq_struct!(Token; kind span);
spanless_eq_struct!(TraitRef; path ref_id);
-spanless_eq_struct!(Ty; id kind span);
+spanless_eq_struct!(Ty; id kind span tokens);
spanless_eq_struct!(UseTree; prefix kind span);
spanless_eq_struct!(Variant; attrs id span vis ident data disr_expr is_placeholder);
+spanless_eq_struct!(Visibility; kind span tokens);
spanless_eq_struct!(WhereBoundPredicate; span bound_generic_params bounded_ty bounds);
spanless_eq_struct!(WhereClause; has_where_token predicates span);
spanless_eq_struct!(WhereEqPredicate; id span lhs_ty rhs_ty);
@@ -358,13 +364,13 @@ spanless_eq_enum!(UseTreeKind; Simple(0 1 2) Nested(0) Glob);
spanless_eq_enum!(VariantData; Struct(0 1) Tuple(0 1) Unit(0));
spanless_eq_enum!(VisibilityKind; Public Crate(0) Restricted(path id) Inherited);
spanless_eq_enum!(WherePredicate; BoundPredicate(0) RegionPredicate(0) EqPredicate(0));
-spanless_eq_enum!(ExprKind; Box(0) Array(0) Call(0 1) MethodCall(0 1 2) Tup(0)
- Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1) Type(0 1) Let(0 1) If(0 1 2)
- While(0 1 2) ForLoop(0 1 2 3) Loop(0 1) Match(0 1) Closure(0 1 2 3 4 5)
- Block(0 1) Async(0 1 2) Await(0) TryBlock(0) Assign(0 1 2) AssignOp(0 1 2)
- Field(0 1) Index(0 1) Range(0 1 2) Path(0 1) AddrOf(0 1 2) Break(0 1)
- Continue(0) Ret(0) InlineAsm(0) LlvmInlineAsm(0) MacCall(0) Struct(0 1 2)
- Repeat(0 1) Paren(0) Try(0) Yield(0) Err);
+spanless_eq_enum!(ExprKind; Box(0) Array(0) ConstBlock(0) Call(0 1)
+ MethodCall(0 1 2) Tup(0) Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1) Type(0 1)
+ Let(0 1) If(0 1 2) While(0 1 2) ForLoop(0 1 2 3) Loop(0 1) Match(0 1)
+ Closure(0 1 2 3 4 5) Block(0 1) Async(0 1 2) Await(0) TryBlock(0)
+ Assign(0 1 2) AssignOp(0 1 2) Field(0 1) Index(0 1) Range(0 1 2) Path(0 1)
+ AddrOf(0 1 2) Break(0 1) Continue(0) Ret(0) InlineAsm(0) LlvmInlineAsm(0)
+ MacCall(0) Struct(0 1 2) Repeat(0 1) Paren(0) Try(0) Yield(0) Err);
spanless_eq_enum!(InlineAsmOperand; In(reg expr) Out(reg late expr)
InOut(reg late expr) SplitInOut(reg late in_expr out_expr) Const(expr)
Sym(expr));
@@ -436,3 +442,11 @@ impl SpanlessEq for TokenStream {
}
}
}
+
+impl SpanlessEq for LazyTokenStream {
+ fn eq(&self, other: &Self) -> bool {
+ let this = self.into_token_stream();
+ let other = other.into_token_stream();
+ SpanlessEq::eq(&this, &other)
+ }
+}
diff --git a/tests/common/parse.rs b/tests/common/parse.rs
index 192828fe..636d0a37 100644
--- a/tests/common/parse.rs
+++ b/tests/common/parse.rs
@@ -9,7 +9,6 @@ use rustc_ast::ptr::P;
use rustc_session::parse::ParseSess;
use rustc_span::source_map::FilePathMapping;
use rustc_span::FileName;
-
use std::panic;
pub fn librustc_expr(input: &str) -> Option<P<ast::Expr>> {
diff --git a/tests/macros/mod.rs b/tests/macros/mod.rs
index 3994615f..db90818e 100644
--- a/tests/macros/mod.rs
+++ b/tests/macros/mod.rs
@@ -1,7 +1,6 @@
#[path = "../debug/mod.rs"]
pub mod debug;
-use syn;
use syn::parse::{Parse, Result};
#[macro_export]
diff --git a/tests/test_grouping.rs b/tests/test_grouping.rs
index a0fe7163..9eb7eee9 100644
--- a/tests/test_grouping.rs
+++ b/tests/test_grouping.rs
@@ -2,9 +2,8 @@
mod macros;
use proc_macro2::{Delimiter, Group, Literal, Punct, Spacing, TokenStream, TokenTree};
-use syn::Expr;
-
use std::iter::FromIterator;
+use syn::Expr;
#[test]
fn test_grouping() {
diff --git a/tests/test_lit.rs b/tests/test_lit.rs
index e995f228..099daf10 100644
--- a/tests/test_lit.rs
+++ b/tests/test_lit.rs
@@ -5,7 +5,7 @@ use proc_macro2::{Delimiter, Group, Literal, Span, TokenStream, TokenTree};
use quote::ToTokens;
use std::iter::FromIterator;
use std::str::FromStr;
-use syn::{Lit, LitFloat, LitInt};
+use syn::{Lit, LitFloat, LitInt, LitStr};
fn lit(s: &str) -> Lit {
match TokenStream::from_str(s)
@@ -43,6 +43,7 @@ fn strings() {
test_string("\"'\"", "'");
test_string("\"\"", "");
test_string("\"\\u{1F415}\"", "\u{1F415}");
+ test_string("\"\\u{1_2__3_}\"", "\u{123}");
test_string(
"\"contains\nnewlines\\\nescaped newlines\"",
"contains\nnewlinesescaped newlines",
@@ -151,6 +152,9 @@ fn ints() {
test_int("5", 5, "");
test_int("5u32", 5, "u32");
+ test_int("0E", 0, "E");
+ test_int("0ECMA", 0, "ECMA");
+ test_int("0o0A", 0, "A");
test_int("5_0", 50, "");
test_int("5_____0_____", 50, "");
test_int("0x7f", 127, "");
@@ -167,6 +171,7 @@ fn ints() {
test_int("0x_7F__u8", 127, "u8");
test_int("0b__10__0_1i8", 9, "i8");
test_int("0o__7__________________3u32", 59, "u32");
+ test_int("0e1\u{5c5}", 0, "e1\u{5c5}");
}
#[test]
@@ -192,6 +197,8 @@ fn floats() {
test_float("1.0__3e-12", 1.03e-12, "");
test_float("1.03e+12", 1.03e12, "");
test_float("9e99e99", 9e99, "e99");
+ test_float("1e_0", 1.0, "");
+ test_float("0.0ECMA", 0.0, "ECMA");
}
#[test]
@@ -208,6 +215,12 @@ fn negative() {
}
#[test]
+fn negative_overflow() {
+ assert!(syn::parse_str::<LitFloat>("-1.0e99f64").is_ok());
+ assert!(syn::parse_str::<LitFloat>("-1.0e999f64").is_err());
+}
+
+#[test]
fn suffix() {
fn get_suffix(token: &str) -> String {
let lit = syn::parse_str::<Lit>(token).unwrap();
@@ -247,3 +260,12 @@ fn test_deep_group_empty() {
snapshot!(tokens as Lit, @r#""hi""# );
}
+
+#[test]
+fn test_error() {
+ let err = syn::parse_str::<LitStr>("...").unwrap_err();
+ assert_eq!("expected string literal", err.to_string());
+
+ let err = syn::parse_str::<LitStr>("5").unwrap_err();
+ assert_eq!("expected string literal", err.to_string());
+}
diff --git a/tests/test_meta.rs b/tests/test_meta.rs
index d37dda94..de6cc4da 100644
--- a/tests/test_meta.rs
+++ b/tests/test_meta.rs
@@ -337,3 +337,40 @@ fn test_parse_nested_meta() {
})
"###);
}
+
+#[test]
+fn test_parse_path() {
+ let input = "::serde::Serialize";
+ snapshot!(input as Meta, @r###"
+ Path(Path {
+ leading_colon: Some,
+ segments: [
+ PathSegment {
+ ident: "serde",
+ arguments: None,
+ },
+ PathSegment {
+ ident: "Serialize",
+ arguments: None,
+ },
+ ],
+ })
+ "###);
+
+ let input = "::serde::Serialize";
+ snapshot!(input as NestedMeta, @r###"
+ Meta(Path(Path {
+ leading_colon: Some,
+ segments: [
+ PathSegment {
+ ident: "serde",
+ arguments: None,
+ },
+ PathSegment {
+ ident: "Serialize",
+ arguments: None,
+ },
+ ],
+ }))
+ "###);
+}
diff --git a/tests/test_pat.rs b/tests/test_pat.rs
index 73388dd7..399de028 100644
--- a/tests/test_pat.rs
+++ b/tests/test_pat.rs
@@ -1,4 +1,9 @@
+#[macro_use]
+mod macros;
+
+use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
use quote::quote;
+use std::iter::FromIterator;
use syn::{Item, Pat, Stmt};
#[test]
@@ -36,3 +41,27 @@ fn test_leading_vert() {
syn::parse_str::<Stmt>("let NS { f: | A }: NS;").unwrap_err();
syn::parse_str::<Stmt>("let NS { f: || A }: NS;").unwrap_err();
}
+
+#[test]
+fn test_group() {
+ let group = Group::new(Delimiter::None, quote!(Some(_)));
+ let tokens = TokenStream::from_iter(vec![TokenTree::Group(group)]);
+
+ snapshot!(tokens as Pat, @r###"
+ Pat::TupleStruct {
+ path: Path {
+ segments: [
+ PathSegment {
+ ident: "Some",
+ arguments: None,
+ },
+ ],
+ },
+ pat: PatTuple {
+ elems: [
+ Pat::Wild,
+ ],
+ },
+ }
+ "###);
+}
diff --git a/tests/test_path.rs b/tests/test_path.rs
index 2ce12066..e05b52ee 100644
--- a/tests/test_path.rs
+++ b/tests/test_path.rs
@@ -2,9 +2,9 @@
mod macros;
use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
-use quote::quote;
+use quote::{quote, ToTokens};
use std::iter::FromIterator;
-use syn::{Expr, Type};
+use syn::{parse_quote, Expr, Type, TypePath};
#[test]
fn parse_interpolated_leading_component() {
@@ -50,3 +50,55 @@ fn parse_interpolated_leading_component() {
}
"###);
}
+
+#[test]
+fn print_incomplete_qpath() {
+ // qpath with `as` token
+ let mut ty: TypePath = parse_quote!(<Self as A>::Q);
+ snapshot!(ty.to_token_stream(), @r###"
+ TokenStream(`< Self as A > :: Q`)
+ "###);
+ assert!(ty.path.segments.pop().is_some());
+ snapshot!(ty.to_token_stream(), @r###"
+ TokenStream(`< Self as A > ::`)
+ "###);
+ assert!(ty.path.segments.pop().is_some());
+ snapshot!(ty.to_token_stream(), @r###"
+ TokenStream(`< Self >`)
+ "###);
+ assert!(ty.path.segments.pop().is_none());
+
+ // qpath without `as` token
+ let mut ty: TypePath = parse_quote!(<Self>::A::B);
+ snapshot!(ty.to_token_stream(), @r###"
+ TokenStream(`< Self > :: A :: B`)
+ "###);
+ assert!(ty.path.segments.pop().is_some());
+ snapshot!(ty.to_token_stream(), @r###"
+ TokenStream(`< Self > :: A ::`)
+ "###);
+ assert!(ty.path.segments.pop().is_some());
+ snapshot!(ty.to_token_stream(), @r###"
+ TokenStream(`< Self > ::`)
+ "###);
+ assert!(ty.path.segments.pop().is_none());
+
+ // normal path
+ let mut ty: TypePath = parse_quote!(Self::A::B);
+ snapshot!(ty.to_token_stream(), @r###"
+ TokenStream(`Self :: A :: B`)
+ "###);
+ assert!(ty.path.segments.pop().is_some());
+ snapshot!(ty.to_token_stream(), @r###"
+ TokenStream(`Self :: A ::`)
+ "###);
+ assert!(ty.path.segments.pop().is_some());
+ snapshot!(ty.to_token_stream(), @r###"
+ TokenStream(`Self ::`)
+ "###);
+ assert!(ty.path.segments.pop().is_some());
+ snapshot!(ty.to_token_stream(), @r###"
+ TokenStream(``)
+ "###);
+ assert!(ty.path.segments.pop().is_none());
+}
diff --git a/tests/test_precedence.rs b/tests/test_precedence.rs
index a586b3fe..1519cf02 100644
--- a/tests/test_precedence.rs
+++ b/tests/test_precedence.rs
@@ -18,21 +18,19 @@ extern crate rustc_ast;
extern crate rustc_data_structures;
extern crate rustc_span;
+use crate::common::eq::SpanlessEq;
+use crate::common::parse;
use quote::quote;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use regex::Regex;
use rustc_ast::ast;
use rustc_ast::ptr::P;
use rustc_span::edition::Edition;
-use walkdir::{DirEntry, WalkDir};
-
use std::fs::File;
use std::io::Read;
use std::process;
use std::sync::atomic::{AtomicUsize, Ordering};
-
-use common::eq::SpanlessEq;
-use common::parse;
+use walkdir::{DirEntry, WalkDir};
#[macro_use]
mod macros;
diff --git a/tests/test_round_trip.rs b/tests/test_round_trip.rs
index 260dd0c3..b7420346 100644
--- a/tests/test_round_trip.rs
+++ b/tests/test_round_trip.rs
@@ -9,6 +9,7 @@ extern crate rustc_parse as parse;
extern crate rustc_session;
extern crate rustc_span;
+use crate::common::eq::SpanlessEq;
use quote::quote;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use rustc_ast::ast;
@@ -16,14 +17,13 @@ use rustc_errors::PResult;
use rustc_session::parse::ParseSess;
use rustc_span::source_map::FilePathMapping;
use rustc_span::FileName;
-use walkdir::{DirEntry, WalkDir};
-
use std::fs::File;
use std::io::Read;
use std::panic;
use std::process;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Instant;
+use walkdir::{DirEntry, WalkDir};
#[macro_use]
mod macros;
@@ -33,8 +33,6 @@ mod common;
mod repo;
-use common::eq::SpanlessEq;
-
#[test]
fn test_round_trip() {
common::rayon_init();