about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-09-24 21:46:26 +0000
committerbors <bors@rust-lang.org>2019-09-24 21:46:26 +0000
commitdcd473d7b554a82013913244da8aba1e22a002a9 (patch)
treee3d95102edba19987d74cf0c961be6c86d5d8cab /src/libsyntax/parse
parent6ef275e6c3cb1384ec78128eceeb4963ff788dca (diff)
parentaeb24142be8f39975c72a63f57c70d0adc6cc7a6 (diff)
downloadrust-dcd473d7b554a82013913244da8aba1e22a002a9.tar.gz
rust-dcd473d7b554a82013913244da8aba1e22a002a9.zip
Auto merge of #64751 - Centril:rollup-hpbmcfj, r=Centril
Rollup of 16 pull requests

Successful merges:

 - #63356 (Issue#63183: Add fs::read_dir() and ReadDir warning about iterator order + example)
 - #63934 (Fix coherence checking for impl trait in type aliases)
 - #64016 (Streamline `Compiler`)
 - #64296 (Document the unstable iter_order_by library feature)
 - #64443 (rustdoc: general cleanup)
 - #64622 (Add a cycle detector for generic `Graph`s and `mir::Body`s)
 - #64689 (Refactor macro by example)
 - #64698 (Recover on `const X = 42;` and infer type + Error Stash API)
 - #64702 (Remove unused dependencies)
 - #64717 (update mem::discriminant test to use assert_eq and assert_ne over comparison operators)
 - #64720 ( remove rtp.rs, and move rtpSpawn and RTP_ID_ERROR to libc)
 - #64721 (Fixed issue from #64447)
 - #64725 (fix one typo)
 - #64737 (fix several issues in String docs)
 - #64742 (relnotes: make compatibility section more sterile and fix rustc version)
 - #64748 (Fix #64744. Account for the Zero sub-pattern case.)

Failed merges:

r? @ghost
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser/item.rs47
1 files changed, 44 insertions, 3 deletions
diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index cf196645e4f..0d073f0cc97 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -24,7 +24,7 @@ use crate::symbol::{kw, sym};
 use std::mem;
 use log::debug;
 use rustc_target::spec::abi::Abi;
-use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
+use errors::{Applicability, DiagnosticBuilder, DiagnosticId, StashKey};
 
 /// Whether the type alias or associated type is a concrete type or an opaque type.
 #[derive(Debug)]
@@ -1477,10 +1477,23 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty = $expr` with
+    /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`.
+    ///
+    /// When `m` is `"const"`, `$ident` may also be `"_"`.
     fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> {
         let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?;
-        self.expect(&token::Colon)?;
-        let ty = self.parse_ty()?;
+
+        // Parse the type of a `const` or `static mut?` item.
+        // That is, the `":" $ty` fragment.
+        let ty = if self.token == token::Eq {
+            self.recover_missing_const_type(id, m)
+        } else {
+            // Not `=` so expect `":"" $ty` as usual.
+            self.expect(&token::Colon)?;
+            self.parse_ty()?
+        };
+
         self.expect(&token::Eq)?;
         let e = self.parse_expr()?;
         self.expect(&token::Semi)?;
@@ -1491,6 +1504,34 @@ impl<'a> Parser<'a> {
         Ok((id, item, None))
     }
 
+    /// We were supposed to parse `:` but instead, we're already at `=`.
+    /// This means that the type is missing.
+    fn recover_missing_const_type(&mut self, id: Ident, m: Option<Mutability>) -> P<Ty> {
+        // Construct the error and stash it away with the hope
+        // that typeck will later enrich the error with a type.
+        let kind = match m {
+            Some(Mutability::Mutable) => "static mut",
+            Some(Mutability::Immutable) => "static",
+            None => "const",
+        };
+        let mut err = self.struct_span_err(id.span, &format!("missing type for `{}` item", kind));
+        err.span_suggestion(
+            id.span,
+            "provide a type for the item",
+            format!("{}: <type>", id),
+            Applicability::HasPlaceholders,
+        );
+        err.stash(id.span, StashKey::ItemNoType);
+
+        // The user intended that the type be inferred,
+        // so treat this as if the user wrote e.g. `const A: _ = expr;`.
+        P(Ty {
+            node: TyKind::Infer,
+            span: id.span,
+            id: ast::DUMMY_NODE_ID,
+        })
+    }
+
     /// Parses `type Foo = Bar;` or returns `None`
     /// without modifying the parser state.
     fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, Generics)>> {