aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/custom_keyword.rs1
-rw-r--r--src/custom_punctuation.rs1
-rw-r--r--src/error.rs2
-rw-r--r--src/expr.rs370
-rw-r--r--src/generics.rs12
-rw-r--r--src/item.rs76
-rw-r--r--src/lib.rs10
-rw-r--r--src/lifetime.rs11
-rw-r--r--src/lit.rs18
-rw-r--r--src/pat.rs6
-rw-r--r--src/path.rs116
-rw-r--r--src/punctuated.rs23
12 files changed, 473 insertions, 173 deletions
diff --git a/src/custom_keyword.rs b/src/custom_keyword.rs
index a21842ef..69d787e5 100644
--- a/src/custom_keyword.rs
+++ b/src/custom_keyword.rs
@@ -198,6 +198,7 @@ macro_rules! impl_clone_for_custom_keyword {
($ident:ident) => {
impl $crate::__private::Copy for $ident {}
+ #[allow(clippy::expl_impl_clone_on_copy)]
impl $crate::__private::Clone for $ident {
fn clone(&self) -> Self {
*self
diff --git a/src/custom_punctuation.rs b/src/custom_punctuation.rs
index 128185da..118a8453 100644
--- a/src/custom_punctuation.rs
+++ b/src/custom_punctuation.rs
@@ -169,6 +169,7 @@ macro_rules! impl_clone_for_custom_punctuation {
($ident:ident, $($tt:tt)+) => {
impl $crate::__private::Copy for $ident {}
+ #[allow(clippy::expl_impl_clone_on_copy)]
impl $crate::__private::Clone for $ident {
fn clone(&self) -> Self {
*self
diff --git a/src/error.rs b/src/error.rs
index 6051f3b6..780731c8 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -349,7 +349,7 @@ impl std::error::Error for Error {}
impl From<LexError> for Error {
fn from(err: LexError) -> Self {
- Error::new(Span::call_site(), format!("{:?}", err))
+ Error::new(err.span(), "lex error")
}
}
diff --git a/src/expr.rs b/src/expr.rs
index 8e054cc7..a35532d4 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -827,7 +827,11 @@ impl Expr {
| Expr::TryBlock(ExprTryBlock { attrs, .. })
| Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new),
Expr::Verbatim(_) => Vec::new(),
- Expr::__TestExhaustive(_) => unreachable!(),
+
+ #[cfg(test)]
+ Expr::__TestExhaustive(_) => unimplemented!(),
+ #[cfg(not(test))]
+ _ => unreachable!(),
}
}
}
@@ -1418,7 +1422,9 @@ pub(crate) mod parsing {
Precedence::Assign
} else if input.peek(Token![..]) {
Precedence::Range
- } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
+ } else if input.peek(Token![as])
+ || cfg!(feature = "full") && input.peek(Token![:]) && !input.peek(Token![::])
+ {
Precedence::Cast
} else {
Precedence::Any
@@ -1488,17 +1494,9 @@ pub(crate) mod parsing {
}))
}
} else if input.peek(Token![box]) {
- Ok(Expr::Box(ExprBox {
- attrs,
- box_token: input.parse()?,
- expr: Box::new(unary_expr(input, allow_struct)?),
- }))
+ expr_box(input, attrs, allow_struct).map(Expr::Box)
} else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
- Ok(Expr::Unary(ExprUnary {
- attrs,
- op: input.parse()?,
- expr: Box::new(unary_expr(input, allow_struct)?),
- }))
+ expr_unary(input, attrs, allow_struct).map(Expr::Unary)
} else {
trailer_expr(attrs, input, allow_struct)
}
@@ -1699,9 +1697,9 @@ pub(crate) mod parsing {
} else if input.peek(Token![async])
&& (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
{
- input.call(expr_async).map(Expr::Async)
+ input.parse().map(Expr::Async)
} else if input.peek(Token![try]) && input.peek2(token::Brace) {
- input.call(expr_try_block).map(Expr::TryBlock)
+ input.parse().map(Expr::TryBlock)
} else if input.peek(Token![|])
|| input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
|| input.peek(Token![static])
@@ -1722,13 +1720,13 @@ pub(crate) mod parsing {
} else if input.peek(Token![break]) {
expr_break(input, allow_struct).map(Expr::Break)
} else if input.peek(Token![continue]) {
- input.call(expr_continue).map(Expr::Continue)
+ input.parse().map(Expr::Continue)
} else if input.peek(Token![return]) {
expr_ret(input, allow_struct).map(Expr::Return)
} else if input.peek(token::Bracket) {
array_or_repeat(input)
} else if input.peek(Token![let]) {
- input.call(expr_let).map(Expr::Let)
+ input.parse().map(Expr::Let)
} else if input.peek(Token![if]) {
input.parse().map(Expr::If)
} else if input.peek(Token![while]) {
@@ -1740,13 +1738,13 @@ pub(crate) mod parsing {
} else if input.peek(Token![match]) {
input.parse().map(Expr::Match)
} else if input.peek(Token![yield]) {
- input.call(expr_yield).map(Expr::Yield)
+ input.parse().map(Expr::Yield)
} else if input.peek(Token![unsafe]) {
- input.call(expr_unsafe).map(Expr::Unsafe)
+ input.parse().map(Expr::Unsafe)
} else if input.peek(Token![const]) {
input.call(expr_const).map(Expr::Verbatim)
} else if input.peek(token::Brace) {
- input.call(expr_block).map(Expr::Block)
+ input.parse().map(Expr::Block)
} else if input.peek(Token![..]) {
expr_range(input, allow_struct).map(Expr::Range)
} else if input.peek(Token![_]) {
@@ -1762,7 +1760,7 @@ pub(crate) mod parsing {
} else if input.peek(Token![loop]) {
Expr::Loop(input.parse()?)
} else if input.peek(token::Brace) {
- Expr::Block(input.call(expr_block)?)
+ Expr::Block(input.parse()?)
} else {
return Err(input.error("expected loop or block expression"));
};
@@ -1841,6 +1839,17 @@ pub(crate) mod parsing {
}
#[cfg(feature = "full")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprMacro {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprMacro {
+ attrs: Vec::new(),
+ mac: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
let content;
let paren_token = parenthesized!(content in input);
@@ -1927,6 +1936,48 @@ pub(crate) mod parsing {
}
#[cfg(feature = "full")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprArray {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ let bracket_token = bracketed!(content in input);
+ let inner_attrs = content.call(Attribute::parse_inner)?;
+ let mut elems = Punctuated::new();
+
+ while !content.is_empty() {
+ let first: Expr = content.parse()?;
+ elems.push_value(first);
+ if content.is_empty() {
+ break;
+ }
+ let punct = content.parse()?;
+ elems.push_punct(punct);
+ }
+
+ Ok(ExprArray {
+ attrs: inner_attrs,
+ bracket_token,
+ elems,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprRepeat {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ Ok(ExprRepeat {
+ bracket_token: bracketed!(content in input),
+ attrs: content.call(Attribute::parse_inner)?,
+ expr: content.parse()?,
+ semi_token: content.parse()?,
+ len: content.parse()?,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
pub(crate) fn expr_early(input: ParseStream) -> Result<Expr> {
let mut attrs = input.call(expr_attrs)?;
let mut expr = if input.peek(Token![if]) {
@@ -1940,13 +1991,13 @@ pub(crate) mod parsing {
} else if input.peek(Token![match]) {
Expr::Match(input.parse()?)
} else if input.peek(Token![try]) && input.peek2(token::Brace) {
- Expr::TryBlock(input.call(expr_try_block)?)
+ Expr::TryBlock(input.parse()?)
} else if input.peek(Token![unsafe]) {
- Expr::Unsafe(input.call(expr_unsafe)?)
+ Expr::Unsafe(input.parse()?)
} else if input.peek(Token![const]) {
Expr::Verbatim(input.call(expr_const)?)
} else if input.peek(token::Brace) {
- Expr::Block(input.call(expr_block)?)
+ Expr::Block(input.parse()?)
} else {
let allow_struct = AllowStruct(true);
let mut expr = unary_expr(input, allow_struct)?;
@@ -1992,7 +2043,14 @@ pub(crate) mod parsing {
})
}
- #[cfg(not(feature = "full"))]
+ #[cfg(feature = "full")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprParen {
+ fn parse(input: ParseStream) -> Result<Self> {
+ expr_paren(input)
+ }
+ }
+
fn expr_paren(input: ParseStream) -> Result<ExprParen> {
let content;
Ok(ExprParen {
@@ -2010,7 +2068,7 @@ pub(crate) mod parsing {
}
if input.peek(token::Brace) {
- let block = input.call(expr::parsing::expr_block)?;
+ let block: ExprBlock = input.parse()?;
return Ok(GenericMethodArgument::Const(Expr::Block(block)));
}
@@ -2018,14 +2076,17 @@ pub(crate) mod parsing {
}
#[cfg(feature = "full")]
- fn expr_let(input: ParseStream) -> Result<ExprLet> {
- Ok(ExprLet {
- attrs: Vec::new(),
- let_token: input.parse()?,
- pat: pat::parsing::multi_pat_with_leading_vert(input)?,
- eq_token: input.parse()?,
- expr: Box::new(input.call(Expr::parse_without_eager_brace)?),
- })
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprLet {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprLet {
+ attrs: Vec::new(),
+ let_token: input.parse()?,
+ pat: pat::parsing::multi_pat_with_leading_vert(input)?,
+ eq_token: input.parse()?,
+ expr: Box::new(input.call(Expr::parse_without_eager_brace)?),
+ })
+ }
}
#[cfg(feature = "full")]
@@ -2174,63 +2235,139 @@ pub(crate) mod parsing {
}
impl_by_parsing_expr! {
- ExprBox, Box, "expected box expression",
- ExprArray, Array, "expected slice literal expression",
ExprCall, Call, "expected function call expression",
ExprMethodCall, MethodCall, "expected method call expression",
ExprTuple, Tuple, "expected tuple expression",
ExprBinary, Binary, "expected binary operation",
- ExprUnary, Unary, "expected unary operation",
ExprCast, Cast, "expected cast expression",
ExprType, Type, "expected type ascription expression",
- ExprLet, Let, "expected let guard",
- ExprClosure, Closure, "expected closure expression",
- ExprUnsafe, Unsafe, "expected unsafe block",
- ExprBlock, Block, "expected blocked scope",
ExprAssign, Assign, "expected assignment expression",
ExprAssignOp, AssignOp, "expected compound assignment expression",
ExprField, Field, "expected struct field access",
ExprIndex, Index, "expected indexing expression",
ExprRange, Range, "expected range expression",
- ExprReference, Reference, "expected referencing operation",
- ExprBreak, Break, "expected break expression",
- ExprContinue, Continue, "expected continue expression",
- ExprReturn, Return, "expected return expression",
- ExprMacro, Macro, "expected macro invocation expression",
- ExprStruct, Struct, "expected struct literal expression",
- ExprRepeat, Repeat, "expected array literal constructed from one repeated element",
- ExprParen, Paren, "expected parenthesized expression",
ExprTry, Try, "expected try expression",
- ExprAsync, Async, "expected async block",
- ExprTryBlock, TryBlock, "expected try block",
- ExprYield, Yield, "expected yield expression",
}
#[cfg(feature = "full")]
- fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
- Ok(ExprTryBlock {
- attrs: Vec::new(),
- try_token: input.parse()?,
- block: input.parse()?,
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprBox {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = Vec::new();
+ let allow_struct = AllowStruct(true);
+ expr_box(input, attrs, allow_struct)
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn expr_box(
+ input: ParseStream,
+ attrs: Vec<Attribute>,
+ allow_struct: AllowStruct,
+ ) -> Result<ExprBox> {
+ Ok(ExprBox {
+ attrs,
+ box_token: input.parse()?,
+ expr: Box::new(unary_expr(input, allow_struct)?),
})
}
#[cfg(feature = "full")]
- fn expr_yield(input: ParseStream) -> Result<ExprYield> {
- Ok(ExprYield {
- attrs: Vec::new(),
- yield_token: input.parse()?,
- expr: {
- if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
- Some(input.parse()?)
- } else {
- None
- }
- },
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprUnary {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = Vec::new();
+ let allow_struct = AllowStruct(true);
+ expr_unary(input, attrs, allow_struct)
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn expr_unary(
+ input: ParseStream,
+ attrs: Vec<Attribute>,
+ allow_struct: AllowStruct,
+ ) -> Result<ExprUnary> {
+ Ok(ExprUnary {
+ attrs,
+ op: input.parse()?,
+ expr: Box::new(unary_expr(input, allow_struct)?),
})
}
#[cfg(feature = "full")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprClosure {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_struct = AllowStruct(true);
+ expr_closure(input, allow_struct)
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprReference {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_struct = AllowStruct(true);
+ Ok(ExprReference {
+ attrs: Vec::new(),
+ and_token: input.parse()?,
+ raw: Reserved::default(),
+ mutability: input.parse()?,
+ expr: Box::new(unary_expr(input, allow_struct)?),
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprBreak {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_struct = AllowStruct(true);
+ expr_break(input, allow_struct)
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprReturn {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_struct = AllowStruct(true);
+ expr_ret(input, allow_struct)
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprTryBlock {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprTryBlock {
+ attrs: Vec::new(),
+ try_token: input.parse()?,
+ block: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprYield {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprYield {
+ attrs: Vec::new(),
+ yield_token: input.parse()?,
+ expr: {
+ if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
+ Some(input.parse()?)
+ } else {
+ None
+ }
+ },
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
let asyncness: Option<Token![async]> = input.parse()?;
let movability: Option<Token![static]> = if asyncness.is_none() {
@@ -2287,13 +2424,16 @@ pub(crate) mod parsing {
}
#[cfg(feature = "full")]
- fn expr_async(input: ParseStream) -> Result<ExprAsync> {
- Ok(ExprAsync {
- attrs: Vec::new(),
- async_token: input.parse()?,
- capture: input.parse()?,
- block: input.parse()?,
- })
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprAsync {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprAsync {
+ attrs: Vec::new(),
+ async_token: input.parse()?,
+ capture: input.parse()?,
+ block: input.parse()?,
+ })
+ }
}
#[cfg(feature = "full")]
@@ -2326,7 +2466,11 @@ pub(crate) mod parsing {
Pat::Type(_) => unreachable!(),
Pat::Verbatim(_) => {}
Pat::Wild(pat) => pat.attrs = attrs,
- Pat::__TestExhaustive(_) => unreachable!(),
+
+ #[cfg(test)]
+ Pat::__TestExhaustive(_) => unimplemented!(),
+ #[cfg(not(test))]
+ _ => unreachable!(),
}
Ok(pat)
}
@@ -2380,12 +2524,15 @@ pub(crate) mod parsing {
}
#[cfg(feature = "full")]
- fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
- Ok(ExprContinue {
- attrs: Vec::new(),
- continue_token: input.parse()?,
- label: input.parse()?,
- })
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprContinue {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprContinue {
+ attrs: Vec::new(),
+ continue_token: input.parse()?,
+ label: input.parse()?,
+ })
+ }
}
#[cfg(feature = "full")]
@@ -2461,6 +2608,16 @@ pub(crate) mod parsing {
}
#[cfg(feature = "full")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprStruct {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = Vec::new();
+ let path: Path = input.parse()?;
+ expr_struct_helper(input, attrs, path)
+ }
+ }
+
+ #[cfg(feature = "full")]
fn expr_struct_helper(
input: ParseStream,
outer_attrs: Vec<Attribute>,
@@ -2507,19 +2664,22 @@ pub(crate) mod parsing {
}
#[cfg(feature = "full")]
- fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
- let unsafe_token: Token![unsafe] = input.parse()?;
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprUnsafe {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let unsafe_token: Token![unsafe] = input.parse()?;
- let content;
- let brace_token = braced!(content in input);
- let inner_attrs = content.call(Attribute::parse_inner)?;
- let stmts = content.call(Block::parse_within)?;
+ let content;
+ let brace_token = braced!(content in input);
+ let inner_attrs = content.call(Attribute::parse_inner)?;
+ let stmts = content.call(Block::parse_within)?;
- Ok(ExprUnsafe {
- attrs: inner_attrs,
- unsafe_token,
- block: Block { brace_token, stmts },
- })
+ Ok(ExprUnsafe {
+ attrs: inner_attrs,
+ unsafe_token,
+ block: Block { brace_token, stmts },
+ })
+ }
}
#[cfg(feature = "full")]
@@ -2536,19 +2696,23 @@ pub(crate) mod parsing {
}
#[cfg(feature = "full")]
- pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
- let label: Option<Label> = input.parse()?;
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprBlock {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let outer_attrs = input.call(Attribute::parse_outer)?;
+ let label: Option<Label> = input.parse()?;
- let content;
- let brace_token = braced!(content in input);
- let inner_attrs = content.call(Attribute::parse_inner)?;
- let stmts = content.call(Block::parse_within)?;
+ let content;
+ let brace_token = braced!(content in input);
+ let inner_attrs = content.call(Attribute::parse_inner)?;
+ let stmts = content.call(Block::parse_within)?;
- Ok(ExprBlock {
- attrs: inner_attrs,
- label,
- block: Block { brace_token, stmts },
- })
+ Ok(ExprBlock {
+ attrs: private::attrs(outer_attrs, inner_attrs),
+ label,
+ block: Block { brace_token, stmts },
+ })
+ }
}
#[cfg(feature = "full")]
diff --git a/src/generics.rs b/src/generics.rs
index a78af22e..de0772a7 100644
--- a/src/generics.rs
+++ b/src/generics.rs
@@ -598,6 +598,7 @@ ast_struct! {
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
+ use crate::ext::IdentExt;
use crate::parse::{Parse, ParseStream, Result};
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
@@ -632,6 +633,15 @@ pub mod parsing {
attrs,
..input.parse()?
}));
+ } else if input.peek(Token![_]) {
+ params.push_value(GenericParam::Type(TypeParam {
+ attrs,
+ ident: input.call(Ident::parse_any)?,
+ colon_token: None,
+ bounds: Punctuated::new(),
+ eq_token: None,
+ default: None,
+ }));
} else {
return Err(lookahead.error());
}
@@ -870,7 +880,7 @@ pub mod parsing {
eq_token: {
if input.peek(Token![=]) {
let eq_token = input.parse()?;
- default = Some(input.parse::<Expr>()?);
+ default = Some(path::parsing::const_argument(input)?);
Some(eq_token)
} else {
None
diff --git a/src/item.rs b/src/item.rs
index d5c3b277..10479ab4 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -380,7 +380,11 @@ impl Item {
| Item::Macro(ItemMacro { attrs, .. })
| Item::Macro2(ItemMacro2 { attrs, .. }) => mem::replace(attrs, new),
Item::Verbatim(_) => Vec::new(),
- Item::__TestExhaustive(_) => unreachable!(),
+
+ #[cfg(test)]
+ Item::__TestExhaustive(_) => unimplemented!(),
+ #[cfg(not(test))]
+ _ => unreachable!(),
}
}
}
@@ -982,6 +986,7 @@ pub mod parsing {
use std::iter::{self, FromIterator};
crate::custom_keyword!(existential);
+ crate::custom_keyword!(macro_rules);
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Item {
@@ -1026,24 +1031,31 @@ pub mod parsing {
let static_token = input.parse()?;
let mutability = input.parse()?;
let ident = input.parse()?;
- let colon_token = input.parse()?;
- let ty = input.parse()?;
- if input.peek(Token![;]) {
+ if input.peek(Token![=]) {
+ input.parse::<Token![=]>()?;
+ input.parse::<Expr>()?;
input.parse::<Token![;]>()?;
Ok(Item::Verbatim(verbatim::between(begin, input)))
} else {
- Ok(Item::Static(ItemStatic {
- attrs: Vec::new(),
- vis,
- static_token,
- mutability,
- ident,
- colon_token,
- ty,
- eq_token: input.parse()?,
- expr: input.parse()?,
- semi_token: input.parse()?,
- }))
+ let colon_token = input.parse()?;
+ let ty = input.parse()?;
+ if input.peek(Token![;]) {
+ input.parse::<Token![;]>()?;
+ Ok(Item::Verbatim(verbatim::between(begin, input)))
+ } else {
+ Ok(Item::Static(ItemStatic {
+ attrs: Vec::new(),
+ vis,
+ static_token,
+ mutability,
+ ident,
+ colon_token,
+ ty,
+ eq_token: input.parse()?,
+ expr: input.parse()?,
+ semi_token: input.parse()?,
+ }))
+ }
}
} else if lookahead.peek(Token![const]) {
ahead.parse::<Token![const]>()?;
@@ -1142,6 +1154,10 @@ pub mod parsing {
|| lookahead.peek(Token![::]))
{
input.parse().map(Item::Macro)
+ } else if ahead.peek(macro_rules) {
+ input.advance_to(&ahead);
+ input.parse::<ItemMacro>()?;
+ Ok(Item::Verbatim(verbatim::between(begin, input)))
} else {
Err(lookahead.error())
}?;
@@ -1164,7 +1180,6 @@ pub mod parsing {
semi_token: Token![;],
}
- #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for FlexibleItemType {
fn parse(input: ParseStream) -> Result<Self> {
let vis: Visibility = input.parse()?;
@@ -1176,14 +1191,14 @@ pub mod parsing {
let mut bounds = Punctuated::new();
if colon_token.is_some() {
loop {
- bounds.push_value(input.parse::<TypeParamBound>()?);
if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
break;
}
- bounds.push_punct(input.parse::<Token![+]>()?);
+ bounds.push_value(input.parse::<TypeParamBound>()?);
if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
break;
}
+ bounds.push_punct(input.parse::<Token![+]>()?);
}
}
generics.where_clause = input.parse()?;
@@ -1497,11 +1512,11 @@ pub mod parsing {
abi,
fn_token,
ident,
+ generics,
paren_token,
inputs,
- output,
variadic,
- generics,
+ output,
})
}
}
@@ -1787,7 +1802,11 @@ pub mod parsing {
ForeignItem::Type(item) => &mut item.attrs,
ForeignItem::Macro(item) => &mut item.attrs,
ForeignItem::Verbatim(_) => return Ok(item),
- ForeignItem::__TestExhaustive(_) => unreachable!(),
+
+ #[cfg(test)]
+ ForeignItem::__TestExhaustive(_) => unimplemented!(),
+ #[cfg(not(test))]
+ _ => unreachable!(),
};
attrs.extend(item_attrs.drain(..));
*item_attrs = attrs;
@@ -2265,7 +2284,12 @@ pub mod parsing {
TraitItem::Method(item) => &mut item.attrs,
TraitItem::Type(item) => &mut item.attrs,
TraitItem::Macro(item) => &mut item.attrs,
- TraitItem::Verbatim(_) | TraitItem::__TestExhaustive(_) => unreachable!(),
+ TraitItem::Verbatim(_) => unreachable!(),
+
+ #[cfg(test)]
+ TraitItem::__TestExhaustive(_) => unimplemented!(),
+ #[cfg(not(test))]
+ _ => unreachable!(),
};
attrs.extend(item_attrs.drain(..));
*item_attrs = attrs;
@@ -2596,7 +2620,11 @@ pub mod parsing {
ImplItem::Type(item) => &mut item.attrs,
ImplItem::Macro(item) => &mut item.attrs,
ImplItem::Verbatim(_) => return Ok(item),
- ImplItem::__TestExhaustive(_) => unreachable!(),
+
+ #[cfg(test)]
+ ImplItem::__TestExhaustive(_) => unimplemented!(),
+ #[cfg(not(test))]
+ _ => unreachable!(),
};
attrs.extend(item_attrs.drain(..));
*item_attrs = attrs;
diff --git a/src/lib.rs b/src/lib.rs
index 2c201c99..ea0c6dde 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.60")]
+#![doc(html_root_url = "https://docs.rs/syn/1.0.69")]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![allow(non_camel_case_types)]
// Ignored clippy lints.
@@ -259,13 +259,17 @@
clippy::eval_order_dependence,
clippy::inherent_to_string,
clippy::large_enum_variant,
+ clippy::manual_map, // https://github.com/rust-lang/rust-clippy/issues/6795
clippy::match_on_vec_items,
+ clippy::missing_panics_doc,
clippy::needless_doctest_main,
clippy::needless_pass_by_value,
clippy::never_loop,
clippy::too_many_arguments,
clippy::trivially_copy_pass_by_ref,
- clippy::unnecessary_unwrap
+ clippy::unnecessary_unwrap,
+ // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6983
+ clippy::wrong_self_convention
)]
// Ignored clippy_pedantic lints.
#![allow(
@@ -275,6 +279,8 @@
clippy::expl_impl_clone_on_copy,
clippy::if_not_else,
clippy::match_same_arms,
+ // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
+ clippy::match_wildcard_for_single_variants,
clippy::missing_errors_doc,
clippy::module_name_repetitions,
clippy::must_use_candidate,
diff --git a/src/lifetime.rs b/src/lifetime.rs
index 9cec5eec..28cd7e36 100644
--- a/src/lifetime.rs
+++ b/src/lifetime.rs
@@ -57,6 +57,17 @@ impl Lifetime {
ident: Ident::new(&symbol[1..], span),
}
}
+
+ pub fn span(&self) -> Span {
+ self.apostrophe
+ .join(self.ident.span())
+ .unwrap_or(self.apostrophe)
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.apostrophe = span;
+ self.ident.set_span(span);
+ }
}
impl Display for Lifetime {
diff --git a/src/lit.rs b/src/lit.rs
index d67ee884..0aa50a59 100644
--- a/src/lit.rs
+++ b/src/lit.rs
@@ -505,6 +505,24 @@ impl Display for LitFloat {
}
}
+impl LitBool {
+ pub fn new(value: bool, span: Span) -> Self {
+ LitBool { value, span }
+ }
+
+ pub fn value(&self) -> bool {
+ self.value
+ }
+
+ pub fn span(&self) -> Span {
+ self.span
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.span = span;
+ }
+}
+
#[cfg(feature = "extra-traits")]
mod debug_impls {
use super::*;
diff --git a/src/pat.rs b/src/pat.rs
index 312d3c08..d25843fc 100644
--- a/src/pat.rs
+++ b/src/pat.rs
@@ -523,7 +523,7 @@ pub mod parsing {
attrs,
member,
colon_token: input.parse()?,
- pat: Box::new(multi_pat(input)?),
+ pat: Box::new(multi_pat_with_leading_vert(input)?),
});
}
@@ -602,7 +602,7 @@ pub mod parsing {
let mut elems = Punctuated::new();
while !content.is_empty() {
- let value = multi_pat(&content)?;
+ let value = multi_pat_with_leading_vert(&content)?;
elems.push_value(value);
if content.is_empty() {
break;
@@ -701,7 +701,7 @@ pub mod parsing {
let mut elems = Punctuated::new();
while !content.is_empty() {
- let value = multi_pat(&content)?;
+ let value = multi_pat_with_leading_vert(&content)?;
elems.push_value(value);
if content.is_empty() {
break;
diff --git a/src/path.rs b/src/path.rs
index 3f668c9d..df1788db 100644
--- a/src/path.rs
+++ b/src/path.rs
@@ -213,8 +213,6 @@ ast_struct! {
pub mod parsing {
use super::*;
- #[cfg(feature = "full")]
- use crate::expr;
use crate::ext::IdentExt;
use crate::parse::{Parse, ParseStream, Result};
@@ -243,31 +241,76 @@ pub mod parsing {
}
}
- if input.peek(Lit) {
- let lit = input.parse()?;
- return Ok(GenericArgument::Const(Expr::Lit(lit)));
+ if input.peek(Lit) || input.peek(token::Brace) {
+ return const_argument(input).map(GenericArgument::Const);
}
- if input.peek(token::Brace) {
- #[cfg(feature = "full")]
- {
- let block = input.call(expr::parsing::expr_block)?;
- return Ok(GenericArgument::Const(Expr::Block(block)));
- }
+ #[cfg(feature = "full")]
+ let begin = input.fork();
- #[cfg(not(feature = "full"))]
- {
- let begin = input.fork();
- let content;
- braced!(content in input);
- content.parse::<Expr>()?;
+ let argument: Type = input.parse()?;
+
+ #[cfg(feature = "full")]
+ {
+ if match &argument {
+ Type::Path(argument)
+ if argument.qself.is_none()
+ && argument.path.leading_colon.is_none()
+ && argument.path.segments.len() == 1 =>
+ {
+ match argument.path.segments[0].arguments {
+ PathArguments::AngleBracketed(_) => true,
+ _ => false,
+ }
+ }
+ _ => false,
+ } && if input.peek(Token![=]) {
+ input.parse::<Token![=]>()?;
+ input.parse::<Type>()?;
+ true
+ } else if input.peek(Token![:]) {
+ input.parse::<Token![:]>()?;
+ input.call(constraint_bounds)?;
+ true
+ } else {
+ false
+ } {
let verbatim = verbatim::between(begin, input);
- return Ok(GenericArgument::Const(Expr::Verbatim(verbatim)));
+ return Ok(GenericArgument::Type(Type::Verbatim(verbatim)));
}
}
- input.parse().map(GenericArgument::Type)
+ Ok(GenericArgument::Type(argument))
+ }
+ }
+
+ pub fn const_argument(input: ParseStream) -> Result<Expr> {
+ let lookahead = input.lookahead1();
+
+ if input.peek(Lit) {
+ let lit = input.parse()?;
+ return Ok(Expr::Lit(lit));
+ }
+
+ if input.peek(token::Brace) {
+ #[cfg(feature = "full")]
+ {
+ let block: ExprBlock = input.parse()?;
+ return Ok(Expr::Block(block));
+ }
+
+ #[cfg(not(feature = "full"))]
+ {
+ let begin = input.fork();
+ let content;
+ braced!(content in input);
+ content.parse::<Expr>()?;
+ let verbatim = verbatim::between(begin, input);
+ return Ok(Expr::Verbatim(verbatim));
+ }
}
+
+ Err(lookahead.error())
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
@@ -360,26 +403,29 @@ pub mod parsing {
Ok(Constraint {
ident: input.parse()?,
colon_token: input.parse()?,
- bounds: {
- let mut bounds = Punctuated::new();
- loop {
- if input.peek(Token![,]) || input.peek(Token![>]) {
- break;
- }
- let value = input.parse()?;
- bounds.push_value(value);
- if !input.peek(Token![+]) {
- break;
- }
- let punct = input.parse()?;
- bounds.push_punct(punct);
- }
- bounds
- },
+ bounds: constraint_bounds(input)?,
})
}
}
+ #[cfg(feature = "full")]
+ fn constraint_bounds(input: ParseStream) -> Result<Punctuated<TypeParamBound, Token![+]>> {
+ let mut bounds = Punctuated::new();
+ loop {
+ if input.peek(Token![,]) || input.peek(Token![>]) {
+ break;
+ }
+ let value = input.parse()?;
+ bounds.push_value(value);
+ if !input.peek(Token![+]) {
+ break;
+ }
+ let punct = input.parse()?;
+ bounds.push_punct(punct);
+ }
+ Ok(bounds)
+ }
+
impl Path {
/// Parse a `Path` containing no path arguments on any of its segments.
///
diff --git a/src/punctuated.rs b/src/punctuated.rs
index 4d349697..f94edc29 100644
--- a/src/punctuated.rs
+++ b/src/punctuated.rs
@@ -162,7 +162,11 @@ impl<T, P> Punctuated<T, P> {
/// Panics if the sequence does not already have a trailing punctuation when
/// this method is called.
pub fn push_value(&mut self, value: T) {
- assert!(self.empty_or_trailing());
+ assert!(
+ self.empty_or_trailing(),
+ "Punctuated::push_value: cannot push value if Punctuated is missing trailing punctuation",
+ );
+
self.last = Some(Box::new(value));
}
@@ -174,7 +178,11 @@ impl<T, P> Punctuated<T, P> {
///
/// Panics if the sequence is empty or already has a trailing punctuation.
pub fn push_punct(&mut self, punctuation: P) {
- assert!(self.last.is_some());
+ assert!(
+ self.last.is_some(),
+ "Punctuated::push_punct: cannot push punctuation if Punctuated is empty or already has trailing punctuation",
+ );
+
let last = self.last.take().unwrap();
self.inner.push((*last, punctuation));
}
@@ -228,7 +236,10 @@ impl<T, P> Punctuated<T, P> {
where
P: Default,
{
- assert!(index <= self.len());
+ assert!(
+ index <= self.len(),
+ "Punctuated::insert: index out of range",
+ );
if index == self.len() {
self.push(value);
@@ -454,7 +465,11 @@ impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P> {
fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
- assert!(self.empty_or_trailing());
+ assert!(
+ self.empty_or_trailing(),
+ "Punctuated::extend: Punctuated is not empty or does not have a trailing punctuation",
+ );
+
let mut nomore = false;
for pair in i {
if nomore {