about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-08-10 15:10:17 +0000
committerbors <bors@rust-lang.org>2017-08-10 15:10:17 +0000
commitb6179602bea71607a9ea63197eca423fcce5f7b0 (patch)
tree6bfe47d69f9df71b8e5682c7d6d61333194c76a9 /src/libsyntax/parse
parent2400ebfe76225745d1591c8a63c54570174ab22c (diff)
parentcabc9be9e2057c5197db273ba0c750aad5ff3366 (diff)
downloadrust-b6179602bea71607a9ea63197eca423fcce5f7b0.tar.gz
rust-b6179602bea71607a9ea63197eca423fcce5f7b0.zip
Auto merge of #43720 - pornel:staticconst, r=petrochenkov
Hint correct extern constant syntax

Error message for `extern "C" { const …}` is terse, and the right syntax is hard to guess given unfortunate difference between meaning of `static` in C and Rust.

I've added a hint for the right syntax.
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser.rs23
1 files changed, 13 insertions, 10 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index ca362ec9368..7bf4c6799b3 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5518,12 +5518,11 @@ impl<'a> Parser<'a> {
         })
     }
 
-    /// Parse a static item from a foreign module
+    /// Parse a static item from a foreign module.
+    /// Assumes that the `static` keyword is already parsed.
     fn parse_item_foreign_static(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<Attribute>)
                                  -> PResult<'a, ForeignItem> {
-        self.expect_keyword(keywords::Static)?;
         let mutbl = self.eat_keyword(keywords::Mut);
-
         let ident = self.parse_ident()?;
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
@@ -5997,19 +5996,23 @@ impl<'a> Parser<'a> {
         let lo = self.span;
         let visibility = self.parse_visibility(false)?;
 
-        if self.check_keyword(keywords::Static) {
-            // FOREIGN STATIC ITEM
+        // FOREIGN STATIC ITEM
+        // Treat `const` as `static` for error recovery, but don't add it to expected tokens.
+        if self.check_keyword(keywords::Static) || self.token.is_keyword(keywords::Const) {
+            if self.token.is_keyword(keywords::Const) {
+                self.diagnostic()
+                    .struct_span_err(self.span, "extern items cannot be `const`")
+                    .span_suggestion(self.span, "instead try using", "static".to_owned())
+                    .emit();
+            }
+            self.bump(); // `static` or `const`
             return Ok(Some(self.parse_item_foreign_static(visibility, lo, attrs)?));
         }
+        // FOREIGN FUNCTION ITEM
         if self.check_keyword(keywords::Fn) {
-            // FOREIGN FUNCTION ITEM
             return Ok(Some(self.parse_item_foreign_fn(visibility, lo, attrs)?));
         }
 
-        if self.check_keyword(keywords::Const) {
-            return Err(self.span_fatal(self.span, "extern items cannot be `const`"));
-        }
-
         // FIXME #5668: this will occur for a macro invocation:
         match self.parse_macro_use_or_failure(attrs, true, false, lo, visibility)? {
             Some(item) => {