aboutsummaryrefslogtreecommitdiffstats
path: root/src/path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/path.rs')
-rw-r--r--src/path.rs116
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.
///