diff options
Diffstat (limited to 'src/path.rs')
-rw-r--r-- | src/path.rs | 116 |
1 files changed, 81 insertions, 35 deletions
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. /// |