about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-03-22 04:54:46 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2020-03-27 07:39:14 +0100
commitabce4881e0553aed7683ed2ade6827b9de9aedaf (patch)
tree5433e839ec5b7c652e00fa02a55efb32e9f791fa
parent91194f795c3ce323b50b5caa30c089ec026200f0 (diff)
downloadrust-abce4881e0553aed7683ed2ade6827b9de9aedaf.tar.gz
rust-abce4881e0553aed7683ed2ade6827b9de9aedaf.zip
split parse_angle_args into loop / single step
-rw-r--r--src/librustc_parse/parser/path.rs130
1 files changed, 67 insertions, 63 deletions
diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs
index 2320dcba33c..3e0fc3a5478 100644
--- a/src/librustc_parse/parser/path.rs
+++ b/src/librustc_parse/parser/path.rs
@@ -388,73 +388,77 @@ impl<'a> Parser<'a> {
     /// possibly including trailing comma.
     fn parse_angle_args(&mut self) -> PResult<'a, Vec<AngleBracketedArg>> {
         let mut args = Vec::new();
-        loop {
-            if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
-                // Parse lifetime argument.
-                args.push(AngleBracketedArg::Arg(GenericArg::Lifetime(self.expect_lifetime())));
-            } else if self.check_ident()
-                && self.look_ahead(1, |t| matches!(t.kind, token::Eq | token::Colon))
-            {
-                // Parse associated type constraint.
-                let lo = self.token.span;
-                let ident = self.parse_ident()?;
-                let kind = if self.eat(&token::Eq) {
-                    AssocTyConstraintKind::Equality { ty: self.parse_ty()? }
-                } else if self.eat(&token::Colon) {
-                    let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
-                    AssocTyConstraintKind::Bound { bounds }
-                } else {
-                    unreachable!();
-                };
-
-                let span = lo.to(self.prev_token.span);
-
-                // Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
-                if let AssocTyConstraintKind::Bound { .. } = kind {
-                    self.sess.gated_spans.gate(sym::associated_type_bounds, span);
-                }
-
-                let constraint = AssocTyConstraint { id: ast::DUMMY_NODE_ID, ident, kind, span };
-                args.push(AngleBracketedArg::Constraint(constraint));
-            } else if self.check_const_arg() {
-                // Parse const argument.
-                let expr = if let token::OpenDelim(token::Brace) = self.token.kind {
-                    self.parse_block_expr(
-                        None,
-                        self.token.span,
-                        BlockCheckMode::Default,
-                        ast::AttrVec::new(),
-                    )?
-                } else if self.token.is_ident() {
-                    // FIXME(const_generics): to distinguish between idents for types and consts,
-                    // we should introduce a GenericArg::Ident in the AST and distinguish when
-                    // lowering to the HIR. For now, idents for const args are not permitted.
-                    if self.token.is_bool_lit() {
-                        self.parse_literal_maybe_minus()?
-                    } else {
-                        let span = self.token.span;
-                        let msg = "identifiers may currently not be used for const generics";
-                        self.struct_span_err(span, msg).emit();
-                        let block = self.mk_block_err(span);
-                        self.mk_expr(span, ast::ExprKind::Block(block, None), ast::AttrVec::new())
-                    }
-                } else {
-                    self.parse_literal_maybe_minus()?
-                };
-                let value = AnonConst { id: ast::DUMMY_NODE_ID, value: expr };
-                args.push(AngleBracketedArg::Arg(GenericArg::Const(value)));
-            } else if self.check_type() {
-                // Parse type argument.
-                args.push(AngleBracketedArg::Arg(GenericArg::Type(self.parse_ty()?)));
-            } else {
-                break;
-            }
-
+        while let Some(arg) = self.parse_angle_arg()? {
+            args.push(arg);
             if !self.eat(&token::Comma) {
                 break;
             }
         }
-
         Ok(args)
     }
+
+    /// Parses a single argument in the angle arguments `<...>` of a path segment.
+    fn parse_angle_arg(&mut self) -> PResult<'a, Option<AngleBracketedArg>> {
+        let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
+            // Parse lifetime argument.
+            AngleBracketedArg::Arg(GenericArg::Lifetime(self.expect_lifetime()))
+        } else if self.check_ident()
+            && self.look_ahead(1, |t| matches!(t.kind, token::Eq | token::Colon))
+        {
+            // Parse associated type constraint.
+            let lo = self.token.span;
+            let ident = self.parse_ident()?;
+            let kind = if self.eat(&token::Eq) {
+                AssocTyConstraintKind::Equality { ty: self.parse_ty()? }
+            } else if self.eat(&token::Colon) {
+                let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
+                AssocTyConstraintKind::Bound { bounds }
+            } else {
+                unreachable!();
+            };
+
+            let span = lo.to(self.prev_token.span);
+
+            // Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
+            if let AssocTyConstraintKind::Bound { .. } = kind {
+                self.sess.gated_spans.gate(sym::associated_type_bounds, span);
+            }
+
+            let constraint = AssocTyConstraint { id: ast::DUMMY_NODE_ID, ident, kind, span };
+            AngleBracketedArg::Constraint(constraint)
+        } else if self.check_const_arg() {
+            // Parse const argument.
+            let expr = if let token::OpenDelim(token::Brace) = self.token.kind {
+                self.parse_block_expr(
+                    None,
+                    self.token.span,
+                    BlockCheckMode::Default,
+                    ast::AttrVec::new(),
+                )?
+            } else if self.token.is_ident() {
+                // FIXME(const_generics): to distinguish between idents for types and consts,
+                // we should introduce a GenericArg::Ident in the AST and distinguish when
+                // lowering to the HIR. For now, idents for const args are not permitted.
+                if self.token.is_bool_lit() {
+                    self.parse_literal_maybe_minus()?
+                } else {
+                    let span = self.token.span;
+                    let msg = "identifiers may currently not be used for const generics";
+                    self.struct_span_err(span, msg).emit();
+                    let block = self.mk_block_err(span);
+                    self.mk_expr(span, ast::ExprKind::Block(block, None), ast::AttrVec::new())
+                }
+            } else {
+                self.parse_literal_maybe_minus()?
+            };
+            let value = AnonConst { id: ast::DUMMY_NODE_ID, value: expr };
+            AngleBracketedArg::Arg(GenericArg::Const(value))
+        } else if self.check_type() {
+            // Parse type argument.
+            AngleBracketedArg::Arg(GenericArg::Type(self.parse_ty()?))
+        } else {
+            return Ok(None);
+        };
+        Ok(Some(arg))
+    }
 }