From a0ab740044aa5f0f0ee4fa22cb4eb0fc7453268a Mon Sep 17 00:00:00 2001 From: Chih-Hung Hsieh Date: Mon, 26 Oct 2020 13:16:52 -0700 Subject: Upgrade rust/crates/syn to 1.0.48 Test: make Change-Id: I4da37029dfd0e5bc433e10ddfc1aa8dd2566af18 --- .cargo_vcs_info.json | 2 +- Android.bp | 2 +- Cargo.toml | 6 +- Cargo.toml.orig | 6 +- METADATA | 8 +- src/attr.rs | 9 +- src/await.rs | 2 +- src/buffer.rs | 4 +- src/custom_keyword.rs | 4 +- src/custom_punctuation.rs | 4 +- src/data.rs | 5 +- src/derive.rs | 7 +- src/error.rs | 16 ++-- src/expr.rs | 7 +- src/ext.rs | 6 +- src/file.rs | 1 - src/generics.rs | 7 +- src/group.rs | 3 +- src/item.rs | 87 ++++++++--------- src/lib.rs | 3 +- src/lifetime.rs | 5 +- src/lit.rs | 172 ++++++++++++++++++--------------- src/lookahead.rs | 6 +- src/mac.rs | 1 - src/op.rs | 1 - src/parse.rs | 24 +++-- src/parse_macro_input.rs | 44 +++++++++ src/parse_quote.rs | 4 +- src/pat.rs | 35 +++---- src/path.rs | 11 +-- src/stmt.rs | 2 - src/token.rs | 237 +++++++++++++++++++++++----------------------- src/tt.rs | 3 +- src/ty.rs | 7 +- tests/common/eq.rs | 54 +++++++---- tests/common/parse.rs | 1 - tests/macros/mod.rs | 1 - tests/test_grouping.rs | 3 +- tests/test_lit.rs | 24 ++++- tests/test_meta.rs | 37 ++++++++ tests/test_pat.rs | 29 ++++++ tests/test_path.rs | 56 ++++++++++- tests/test_precedence.rs | 8 +- tests/test_round_trip.rs | 6 +- 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 "] 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 "] 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 { 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 = std::result::Result; 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::()?; Ok(Item::Verbatim(verbatim::between(begin, input))) @@ -1335,46 +1334,45 @@ pub mod parsing { && fork.peek(Token![fn]) } - fn parse_signature(input: ParseStream) -> Result { - let constness: Option = input.parse()?; - let asyncness: Option = input.parse()?; - let unsafety: Option = input.parse()?; - let abi: Option = 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 { + let constness: Option = input.parse()?; + let asyncness: Option = input.parse()?; + let unsafety: Option = input.parse()?; + let abi: Option = 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 = 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 { 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 { 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 { 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 = 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 = input.parse()?; - let sig = parse_signature(input)?; + let sig: Signature = input.parse()?; let block = if let Some(semi) = input.parse::>()? { // 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, } @@ -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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 @@ /// ///
/// +/// # 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 { +/// /* ... */ +/// # 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() +/// } +/// ``` +/// +///
+/// /// # 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`] — parses the same as `Block::parse_within` /// -/// [`Punctuated`]: punctuated::Punctuated +/// [`Punctuated`]: crate::punctuated::Punctuated /// [`Vec`]: 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 { 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::()?; - ahead.parse::()?; - ahead.is_empty() || ahead.peek(Token![,]) - } - }) - || input.peek(Token![self]) && input.peek2(Token![::]) - || lookahead.peek(Token![::]) + if { + let ahead = input.fork(); + ahead.parse::>()?.is_some() + && (ahead.peek(Token![::]) + || ahead.peek(Token![!]) + || ahead.peek(token::Brace) + || ahead.peek(token::Paren) + || ahead.peek(Token![..]) + && ahead.parse::().is_ok() + && !(ahead.is_empty() || ahead.peek(Token![,]))) + } || { + let ahead = input.fork(); + ahead.parse::>()?.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 { 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 SpanlessEq for P { } } -impl SpanlessEq for Lrc { +impl SpanlessEq for Lrc { fn eq(&self, other: &Self) -> bool { SpanlessEq::eq(&**self, &**other) } @@ -57,12 +56,18 @@ impl SpanlessEq for Option { } } -impl SpanlessEq for Vec { +impl 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 SpanlessEq for Vec { + fn eq(&self, other: &Self) -> bool { + <[T] as SpanlessEq>::eq(self, other) + } +} + impl SpanlessEq for ThinVec { 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> { 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] @@ -207,6 +214,12 @@ fn negative() { assert_eq!("-1.5f64", LitFloat::new("-1.5f64", span).to_string()); } +#[test] +fn negative_overflow() { + assert!(syn::parse_str::("-1.0e99f64").is_ok()); + assert!(syn::parse_str::("-1.0e999f64").is_err()); +} + #[test] fn suffix() { fn get_suffix(token: &str) -> String { @@ -247,3 +260,12 @@ fn test_deep_group_empty() { snapshot!(tokens as Lit, @r#""hi""# ); } + +#[test] +fn test_error() { + let err = syn::parse_str::("...").unwrap_err(); + assert_eq!("expected string literal", err.to_string()); + + let err = syn::parse_str::("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::("let NS { f: | A }: NS;").unwrap_err(); syn::parse_str::("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!(::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!(::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(); -- cgit v1.2.3