about summary refs log tree commit diff
path: root/src/librustc_parse/parser
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-01-30 02:42:33 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2020-02-13 10:39:23 +0100
commite839b2ec849246ec5efe5069c8d874dbef289462 (patch)
tree36489d29fe26c85fd9f283335acfb37d4915ee40 /src/librustc_parse/parser
parent2e6eaceedeeda764056eb0e2134735793533770d (diff)
downloadrust-e839b2ec849246ec5efe5069c8d874dbef289462.tar.gz
rust-e839b2ec849246ec5efe5069c8d874dbef289462.zip
Constness -> enum Const { Yes(Span), No }
Same idea for `Unsafety` & use new span for better diagnostics.
Diffstat (limited to 'src/librustc_parse/parser')
-rw-r--r--src/librustc_parse/parser/item.rs77
-rw-r--r--src/librustc_parse/parser/mod.rs12
2 files changed, 43 insertions, 46 deletions
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 07d8bae4725..a66a85b2b83 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -12,7 +12,7 @@ use rustc_span::BytePos;
 use syntax::ast::{self, AttrKind, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID};
 use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind};
 use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind};
-use syntax::ast::{Constness, Defaultness, Extern, IsAsync, IsAuto, PathSegment, StrLit, Unsafety};
+use syntax::ast::{Const, Defaultness, Extern, IsAsync, IsAuto, PathSegment, StrLit, Unsafe};
 use syntax::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData};
 use syntax::ast::{FnHeader, ForeignItem, ForeignItemKind, Mutability, Visibility, VisibilityKind};
 use syntax::ptr::P;
@@ -107,9 +107,9 @@ impl<'a> Parser<'a> {
                 // EXTERN FUNCTION ITEM
                 let fn_span = self.prev_span;
                 let header = FnHeader {
-                    unsafety: Unsafety::Normal,
+                    unsafety: Unsafe::No,
                     asyncness: respan(fn_span, IsAsync::NotAsync),
-                    constness: respan(fn_span, Constness::NotConst),
+                    constness: Const::No,
                     ext: Extern::from_abi(abi),
                 };
                 return self.parse_item_fn(lo, vis, attrs, header);
@@ -128,8 +128,8 @@ impl<'a> Parser<'a> {
             return self.mk_item_with_info(attrs, lo, vis, info);
         }
 
-        if self.eat_keyword(kw::Const) {
-            let const_span = self.prev_span;
+        let constness = self.parse_constness();
+        if let Const::Yes(const_span) = constness {
             if [kw::Fn, kw::Unsafe, kw::Extern].iter().any(|k| self.check_keyword(*k)) {
                 // CONST FUNCTION ITEM
                 let unsafety = self.parse_unsafety();
@@ -143,7 +143,7 @@ impl<'a> Parser<'a> {
                 let header = FnHeader {
                     unsafety,
                     asyncness: respan(const_span, IsAsync::NotAsync),
-                    constness: respan(const_span, Constness::Const),
+                    constness,
                     ext,
                 };
                 return self.parse_item_fn(lo, vis, attrs, header);
@@ -175,7 +175,6 @@ impl<'a> Parser<'a> {
                 self.bump(); // `async`
                 let unsafety = self.parse_unsafety(); // `unsafe`?
                 self.expect_keyword(kw::Fn)?; // `fn`
-                let fn_span = self.prev_span;
                 let asyncness = respan(
                     async_span,
                     IsAsync::Async {
@@ -184,20 +183,16 @@ impl<'a> Parser<'a> {
                     },
                 );
                 self.ban_async_in_2015(async_span);
-                let header = FnHeader {
-                    unsafety,
-                    asyncness,
-                    constness: respan(fn_span, Constness::NotConst),
-                    ext: Extern::None,
-                };
+                let header =
+                    FnHeader { unsafety, asyncness, constness: Const::No, ext: Extern::None };
                 return self.parse_item_fn(lo, vis, attrs, header);
             }
         }
 
         if self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) {
             // UNSAFE TRAIT ITEM
-            self.bump(); // `unsafe`
-            let info = self.parse_item_trait(lo, Unsafety::Unsafe)?;
+            let unsafety = self.parse_unsafety();
+            let info = self.parse_item_trait(lo, unsafety)?;
             return self.mk_item_with_info(attrs, lo, vis, info);
         }
 
@@ -218,9 +213,9 @@ impl<'a> Parser<'a> {
             self.bump();
             let fn_span = self.prev_span;
             let header = FnHeader {
-                unsafety: Unsafety::Normal,
+                unsafety: Unsafe::No,
                 asyncness: respan(fn_span, IsAsync::NotAsync),
-                constness: respan(fn_span, Constness::NotConst),
+                constness: Const::No,
                 ext: Extern::None,
             };
             return self.parse_item_fn(lo, vis, attrs, header);
@@ -230,16 +225,16 @@ impl<'a> Parser<'a> {
             && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace))
         {
             // UNSAFE FUNCTION ITEM
-            self.bump(); // `unsafe`
+            let unsafety = self.parse_unsafety();
             // `{` is also expected after `unsafe`; in case of error, include it in the diagnostic.
             self.check(&token::OpenDelim(token::Brace));
             let ext = self.parse_extern()?;
             self.expect_keyword(kw::Fn)?;
             let fn_span = self.prev_span;
             let header = FnHeader {
-                unsafety: Unsafety::Unsafe,
+                unsafety,
                 asyncness: respan(fn_span, IsAsync::NotAsync),
-                constness: respan(fn_span, Constness::NotConst),
+                constness: Const::No,
                 ext,
             };
             return self.parse_item_fn(lo, vis, attrs, header);
@@ -268,7 +263,7 @@ impl<'a> Parser<'a> {
             || (self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait]))
         {
             // TRAIT ITEM
-            let info = self.parse_item_trait(lo, Unsafety::Normal)?;
+            let info = self.parse_item_trait(lo, Unsafe::No)?;
             return self.mk_item_with_info(attrs, lo, vis, info);
         }
 
@@ -547,7 +542,7 @@ impl<'a> Parser<'a> {
     ///   `impl` GENERICS `const`? `!`? TYPE (`where` PREDICATES)? `{` BODY `}`
     fn parse_item_impl(
         &mut self,
-        unsafety: Unsafety,
+        unsafety: Unsafe,
         defaultness: Defaultness,
     ) -> PResult<'a, ItemInfo> {
         // First, parse generic parameters if necessary.
@@ -561,13 +556,10 @@ impl<'a> Parser<'a> {
             generics
         };
 
-        let constness = if self.eat_keyword(kw::Const) {
-            let span = self.prev_span;
+        let constness = self.parse_constness();
+        if let Const::Yes(span) = constness {
             self.sess.gated_spans.gate(sym::const_trait_impl, span);
-            Constness::Const
-        } else {
-            Constness::NotConst
-        };
+        }
 
         // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
         let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
@@ -707,7 +699,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`.
-    fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
+    fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafe) -> PResult<'a, ItemInfo> {
         // Parse optional `auto` prefix.
         let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No };
 
@@ -734,11 +726,11 @@ impl<'a> Parser<'a> {
             self.expect_semi()?;
 
             let whole_span = lo.to(self.prev_span);
-            if is_auto == IsAuto::Yes {
+            if let IsAuto::Yes = is_auto {
                 let msg = "trait aliases cannot be `auto`";
                 self.struct_span_err(whole_span, msg).span_label(whole_span, msg).emit();
             }
-            if unsafety != Unsafety::Normal {
+            if let Unsafe::Yes(_) = unsafety {
                 let msg = "trait aliases cannot be `unsafe`";
                 self.struct_span_err(whole_span, msg).span_label(whole_span, msg).emit();
             }
@@ -1785,28 +1777,27 @@ impl<'a> Parser<'a> {
         Ok(body)
     }
 
-    /// Parses all the "front matter" for a `fn` declaration, up to
-    /// and including the `fn` keyword:
+    /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration,
+    /// up to and including the `fn` keyword. The formal grammar is:
     ///
-    /// - `const fn`
-    /// - `unsafe fn`
-    /// - `const unsafe fn`
-    /// - `extern fn`
-    /// - etc.
+    /// ```
+    /// Extern = "extern" StringLit ;
+    /// FnQual = "const"? "async"? "unsafe"? Extern? ;
+    /// FnFrontMatter = FnQual? "fn" ;
+    /// ```
     fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
-        let is_const_fn = self.eat_keyword(kw::Const);
-        let const_span = self.prev_span;
+        let constness = self.parse_constness();
         let asyncness = self.parse_asyncness();
         if let IsAsync::Async { .. } = asyncness {
             self.ban_async_in_2015(self.prev_span);
         }
         let asyncness = respan(self.prev_span, asyncness);
         let unsafety = self.parse_unsafety();
-        let (constness, unsafety, ext) = if is_const_fn {
-            (respan(const_span, Constness::Const), unsafety, Extern::None)
+        let (constness, unsafety, ext) = if let Const::Yes(_) = constness {
+            (constness, unsafety, Extern::None)
         } else {
             let ext = self.parse_extern()?;
-            (respan(self.prev_span, Constness::NotConst), unsafety, ext)
+            (Const::No, unsafety, ext)
         };
         if !self.eat_keyword(kw::Fn) {
             // It is possible for `expect_one_of` to recover given the contents of
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index e1461dbb8e7..bccf5968118 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -22,7 +22,8 @@ use rustc_session::parse::ParseSess;
 use rustc_span::source_map::respan;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{FileName, Span, DUMMY_SP};
-use syntax::ast::{self, AttrStyle, AttrVec, CrateSugar, Extern, Ident, Unsafety, DUMMY_NODE_ID};
+use syntax::ast::DUMMY_NODE_ID;
+use syntax::ast::{self, AttrStyle, AttrVec, Const, CrateSugar, Extern, Ident, Unsafe};
 use syntax::ast::{IsAsync, MacArgs, MacDelimiter, Mutability, StrLit, Visibility, VisibilityKind};
 use syntax::ptr::P;
 use syntax::token::{self, DelimToken, Token, TokenKind};
@@ -962,8 +963,13 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses unsafety: `unsafe` or nothing.
-    fn parse_unsafety(&mut self) -> Unsafety {
-        if self.eat_keyword(kw::Unsafe) { Unsafety::Unsafe } else { Unsafety::Normal }
+    fn parse_unsafety(&mut self) -> Unsafe {
+        if self.eat_keyword(kw::Unsafe) { Unsafe::Yes(self.prev_span) } else { Unsafe::No }
+    }
+
+    /// Parses constness: `const` or nothing.
+    fn parse_constness(&mut self) -> Const {
+        if self.eat_keyword(kw::Const) { Const::Yes(self.prev_span) } else { Const::No }
     }
 
     /// Parses mutability (`mut` or nothing).