about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser.rs
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-05-05 08:47:04 -0400
committerNiko Matsakis <niko@alum.mit.edu>2015-05-21 11:47:30 -0400
commitdf93deab10850d52252829770895b0249b0d7f1e (patch)
tree4e8a7657c0d2714319800a07c485bff473043bad /src/libsyntax/parse/parser.rs
parentfb206bf34a2463317b9fa1ef3c0ff35d921f8920 (diff)
downloadrust-df93deab10850d52252829770895b0249b0d7f1e.tar.gz
rust-df93deab10850d52252829770895b0249b0d7f1e.zip
Make various fixes:
- add feature gate
- add basic tests
- adjust parser to eliminate conflict between `const fn` and associated
constants
- allow `const fn` in traits/trait-impls, but forbid later in type check
- correct some merge conflicts
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
-rw-r--r--src/libsyntax/parse/parser.rs68
1 files changed, 41 insertions, 27 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 6fba8fd47fd..eb6420165da 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1160,7 +1160,8 @@ impl<'a> Parser<'a> {
                 let TyParam {ident, bounds, default, ..} = try!(p.parse_ty_param());
                 try!(p.expect(&token::Semi));
                 (ident, TypeTraitItem(bounds, default))
-            } else if try!(p.eat_keyword(keywords::Const)) {
+            } else if p.is_const_item() {
+                try!(p.expect_keyword(keywords::Const));
                 let ident = try!(p.parse_ident());
                 try!(p.expect(&token::Colon));
                 let ty = try!(p.parse_ty_sum());
@@ -1175,13 +1176,7 @@ impl<'a> Parser<'a> {
                 };
                 (ident, ConstTraitItem(ty, default))
             } else {
-                let unsafety = try!(p.parse_unsafety());
-                let abi = if try!(p.eat_keyword(keywords::Extern)) {
-                    try!(p.parse_opt_abi()).unwrap_or(abi::C)
-                } else {
-                    abi::Rust
-                };
-                try!(p.expect_keyword(keywords::Fn));
+                let (constness, unsafety, abi) = try!(p.parse_fn_front_matter());
 
                 let ident = try!(p.parse_ident());
                 let mut generics = try!(p.parse_generics());
@@ -1196,7 +1191,7 @@ impl<'a> Parser<'a> {
                 generics.where_clause = try!(p.parse_where_clause());
                 let sig = ast::MethodSig {
                     unsafety: unsafety,
-                    constness: ast::Constness::NotConst;
+                    constness: constness,
                     decl: d,
                     generics: generics,
                     abi: abi,
@@ -4372,6 +4367,36 @@ impl<'a> Parser<'a> {
         Ok((ident, ItemFn(decl, unsafety, constness, abi, generics, body), Some(inner_attrs)))
     }
 
+    /// true if we are looking at `const ID`, false for things like `const fn` etc
+    pub fn is_const_item(&mut self) -> bool {
+        self.token.is_keyword(keywords::Const) &&
+            !self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
+    }
+
+    /// parses all the "front matter" for a `fn` declaration, up to
+    /// and including the `fn` keyword:
+    ///
+    /// - `const fn`
+    /// - `unsafe fn`
+    /// - `extern fn`
+    /// - etc
+    pub fn parse_fn_front_matter(&mut self) -> PResult<(ast::Constness, ast::Unsafety, abi::Abi)> {
+        let is_const_fn = try!(self.eat_keyword(keywords::Const));
+        let (constness, unsafety, abi) = if is_const_fn {
+            (Constness::Const, Unsafety::Normal, abi::Rust)
+        } else {
+            let unsafety = try!(self.parse_unsafety());
+            let abi = if try!(self.eat_keyword(keywords::Extern)) {
+                try!(self.parse_opt_abi()).unwrap_or(abi::C)
+            } else {
+                abi::Rust
+            };
+            (Constness::NotConst, unsafety, abi)
+        };
+        try!(self.expect_keyword(keywords::Fn));
+        Ok((constness, unsafety, abi))
+    }
+
     /// Parse an impl item.
     pub fn parse_impl_item(&mut self) -> PResult<P<ImplItem>> {
         maybe_whole!(no_clone self, NtImplItem);
@@ -4385,7 +4410,8 @@ impl<'a> Parser<'a> {
             let typ = try!(self.parse_ty_sum());
             try!(self.expect(&token::Semi));
             (name, TypeImplItem(typ))
-        } else if try!(self.eat_keyword(keywords::Const)) {
+        } else if self.is_const_item() {
+            try!(self.expect_keyword(keywords::Const));
             let name = try!(self.parse_ident());
             try!(self.expect(&token::Colon));
             let typ = try!(self.parse_ty_sum());
@@ -4450,19 +4476,7 @@ impl<'a> Parser<'a> {
             }
             Ok((token::special_idents::invalid, vec![], ast::MacImplItem(m)))
         } else {
-            let is_const_fn = !is_trait_impl && self.eat_keyword(keywords::Const);
-            let (constness, unsafety, abi) = if is_const_fn {
-                (Constness::Const, Unsafety::Normal, abi::Rust)
-            } else {
-                let unsafety = try!(self.parse_unsafety());
-                let abi = if try!(self.eat_keyword(keywords::Extern)) {
-                    try!(self.parse_opt_abi()).unwrap_or(abi::C)
-                } else {
-                    abi::Rust
-                };
-                (Constness::NotConst, unsafety, abi)
-            };
-            try!(self.expect_keyword(keywords::Fn));
+            let (constness, unsafety, abi) = try!(self.parse_fn_front_matter());
             let ident = try!(self.parse_ident());
             let mut generics = try!(self.parse_generics());
             let (explicit_self, decl) = try!(self.parse_fn_decl_with_self(|p| {
@@ -4475,7 +4489,7 @@ impl<'a> Parser<'a> {
                 abi: abi,
                 explicit_self: explicit_self,
                 unsafety: unsafety,
-                constness: constness;
+                constness: constness,
                 decl: decl
              }, body)))
         }
@@ -5301,9 +5315,9 @@ impl<'a> Parser<'a> {
         if try!(self.eat_keyword(keywords::Const) ){
             if self.check_keyword(keywords::Fn) {
                 // CONST FUNCTION ITEM
-                self.bump();
+                try!(self.bump());
                 let (ident, item_, extra_attrs) =
-                    self.parse_item_fn(Unsafety::Normal, Constness::Const, abi::Rust);
+                    try!(self.parse_item_fn(Unsafety::Normal, Constness::Const, abi::Rust));
                 let last_span = self.last_span;
                 let item = self.mk_item(lo,
                                         last_span.hi,
@@ -5311,7 +5325,7 @@ impl<'a> Parser<'a> {
                                         item_,
                                         visibility,
                                         maybe_append(attrs, extra_attrs));
-                return Ok(item);
+                return Ok(Some(item));
             }
 
             // CONST ITEM