about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorvarkor <github@varkor.com>2019-02-07 10:10:11 +0100
committervarkor <github@varkor.com>2019-02-07 15:02:17 +0100
commitbbdcc4e7ce697bbd6ad398987c5e4ec4928f5da4 (patch)
tree507022857394927fbb9adb152dcb55f70887ea72 /src/libsyntax
parent899d013fefba27b66c655af4199ccecf8fb9fdae (diff)
downloadrust-bbdcc4e7ce697bbd6ad398987c5e4ec4928f5da4.tar.gz
rust-bbdcc4e7ce697bbd6ad398987c5e4ec4928f5da4.zip
Adjust parser generic parameter errors
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/parse/parser.rs53
-rw-r--r--src/libsyntax/parse/token.rs1
2 files changed, 26 insertions, 28 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2ff450af423..7640f0bdf06 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -948,10 +948,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn check_const_param(&mut self) -> bool {
-        self.check_keyword(keywords::Const)
-    }
-
     fn check_const_arg(&mut self) -> bool {
         if self.token.can_begin_const_arg() {
             true
@@ -1046,7 +1042,8 @@ impl<'a> Parser<'a> {
     }
 
     /// Attempt to consume a `<`. If `<<` is seen, replace it with a single
-    /// `<` and continue. If a `<` is not seen, return false.
+    /// `<` and continue. If `<-` is seen, replace it with a single `<`
+    /// and continue. If a `<` is not seen, return false.
     ///
     /// This is meant to be used when parsing generics on a path to get the
     /// starting token.
@@ -1062,6 +1059,11 @@ impl<'a> Parser<'a> {
                 self.bump_with(token::Lt, span);
                 true
             }
+            token::LArrow => {
+                let span = self.span.with_lo(self.span.lo() + BytePos(1));
+                self.bump_with(token::BinOp(token::Minus), span);
+                true
+            }
             _ => false,
         };
 
@@ -5518,7 +5520,6 @@ impl<'a> Parser<'a> {
     /// trailing comma and erroneous trailing attributes.
     crate fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
         let mut params = Vec::new();
-        let mut prev_param: Option<ParamKindOrd> = None;
         loop {
             let attrs = self.parse_outer_attributes()?;
             if self.check_lifetime() {
@@ -5536,29 +5537,21 @@ impl<'a> Parser<'a> {
                     bounds,
                     kind: ast::GenericParamKind::Lifetime,
                 });
-                prev_param = Some(ParamKindOrd::Lifetime);
-            } else if self.check_const_param() {
+            } else if self.check_keyword(keywords::Const) {
                 // Parse const parameter.
                 params.push(self.parse_const_param(attrs)?);
-                prev_param = Some(ParamKindOrd::Const);
             } else if self.check_ident() {
                 // Parse type parameter.
                 params.push(self.parse_ty_param(attrs)?);
-                prev_param = Some(ParamKindOrd::Type);
             } else {
                 // Check for trailing attributes and stop parsing.
-                if !attrs.is_empty() {
-                    if let Some(prev_param) = prev_param {
-                        self.struct_span_err(
-                            attrs[0].span,
-                            &format!(
-                                "trailing attribute after {} parameter",
-                                prev_param,
-                            ),
-                        )
-                        .span_label(attrs[0].span, "attributes must go before parameters")
-                        .emit();
-                    }
+                if !attrs.is_empty() && !params.is_empty() {
+                    self.struct_span_err(
+                        attrs[0].span,
+                        &format!("trailing attribute after generic parameter"),
+                    )
+                    .span_label(attrs[0].span, "attributes must go before parameters")
+                    .emit();
                 }
                 break
             }
@@ -5774,19 +5767,25 @@ impl<'a> Parser<'a> {
                 });
                 assoc_ty_bindings.push(span);
             } else if self.check_const_arg() {
+                // 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.
+
                 // Parse const argument.
                 let expr = if let token::OpenDelim(token::Brace) = self.token {
                     self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())?
-                } else if self.token.can_begin_literal_or_bool() {
-                    let lit = self.parse_lit()?;
-                    self.mk_expr(lit.span, ExprKind::Lit(lit), ThinVec::new())
-                } else {
+                } 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.
                     return Err(
                         self.fatal("identifiers may currently not be used for const generics")
                     );
+                } else {
+                    // FIXME(const_generics): this currently conflicts with emplacement syntax
+                    // with negative integer literals.
+                    let lit = self.parse_lit()?;
+                    self.mk_expr(lit.span, ExprKind::Lit(lit), ThinVec::new())
                 };
                 let value = AnonConst {
                     id: ast::DUMMY_NODE_ID,
@@ -6444,7 +6443,7 @@ impl<'a> Parser<'a> {
         //     `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
         //     `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
         //     `<` (LIFETIME|IDENT) `=` - generic parameter with a default
-        //     `<` const IDENT          - generic const parameter
+        //     `<` const                - generic const parameter
         // The only truly ambiguous case is
         //     `<` IDENT `>` `::` IDENT ...
         // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index dad32072739..c3885f0d04d 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -284,7 +284,6 @@ impl Token {
         match self {
             OpenDelim(Brace) => true,
             Interpolated(ref nt) => match nt.0 {
-                NtExpr(..) => true,
                 NtBlock(..) => true,
                 NtLiteral(..) => true,
                 _ => false,