diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/custom_keyword.rs | 1 | ||||
-rw-r--r-- | src/custom_punctuation.rs | 1 | ||||
-rw-r--r-- | src/error.rs | 2 | ||||
-rw-r--r-- | src/expr.rs | 370 | ||||
-rw-r--r-- | src/generics.rs | 12 | ||||
-rw-r--r-- | src/item.rs | 76 | ||||
-rw-r--r-- | src/lib.rs | 10 | ||||
-rw-r--r-- | src/lifetime.rs | 11 | ||||
-rw-r--r-- | src/lit.rs | 18 | ||||
-rw-r--r-- | src/pat.rs | 6 | ||||
-rw-r--r-- | src/path.rs | 116 | ||||
-rw-r--r-- | src/punctuated.rs | 23 |
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; @@ -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 { @@ -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::*; @@ -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 { |