about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-12-01 04:12:28 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2019-12-12 17:54:48 +0100
commit73557faed23678fc443f3fa52727b5f200f597d2 (patch)
treed5b14c48ff17af72abccd66ce88397d1a57490ad
parentc4bbe9cbbe9921646cdedb856e34dc951641ed96 (diff)
downloadrust-73557faed23678fc443f3fa52727b5f200f597d2.tar.gz
rust-73557faed23678fc443f3fa52727b5f200f597d2.zip
Use `Option` in `ImplItemKind::Const`.
-rw-r--r--src/librustc/hir/lowering/item.rs8
-rw-r--r--src/librustc_parse/parser/item.rs17
-rw-r--r--src/librustc_passes/ast_validation.rs26
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs2
-rw-r--r--src/libsyntax/ast.rs4
-rw-r--r--src/libsyntax/mut_visit.rs2
-rw-r--r--src/libsyntax/print/pprust.rs2
-rw-r--r--src/libsyntax/visit.rs2
-rw-r--r--src/test/ui/parser/impl-item-const-pass.rs8
-rw-r--r--src/test/ui/parser/impl-item-const-semantic-fail.rs7
-rw-r--r--src/test/ui/parser/impl-item-const-semantic-fail.stderr8
11 files changed, 66 insertions, 20 deletions
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index ff9d8c85df8..32b36d2021b 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -899,7 +899,13 @@ impl LoweringContext<'_> {
                 self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
                 hir::ImplItemKind::Const(
                     self.lower_ty(ty, ImplTraitContext::disallowed()),
-                    self.lower_const_body(expr),
+                    match expr {
+                        Some(expr) => self.lower_const_body(expr),
+                        None => self.lower_body(|this| (
+                            hir_vec![],
+                            this.expr(i.span, hir::ExprKind::Err, ThinVec::new()),
+                        )),
+                    }
                 ),
             ),
             ImplItemKind::Method(ref sig, ref body) => {
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index c159fb66d50..68fdfd24d61 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -756,13 +756,16 @@ impl<'a> Parser<'a> {
     ///     ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
     fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> {
         self.expect_keyword(kw::Const)?;
-        let name = self.parse_ident()?;
+        let ident = self.parse_ident()?;
         self.expect(&token::Colon)?;
-        let typ = self.parse_ty()?;
-        self.expect(&token::Eq)?;
-        let expr = self.parse_expr()?;
+        let ty = self.parse_ty()?;
+        let expr = if self.eat(&token::Eq) {
+            Some(self.parse_expr()?)
+        } else {
+            None
+        };
         self.expect_semi()?;
-        Ok((name, ImplItemKind::Const(typ, expr), Generics::default()))
+        Ok((ident, ImplItemKind::Const(ty, expr), Generics::default()))
     }
 
     /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`.
@@ -912,13 +915,13 @@ impl<'a> Parser<'a> {
         let ident = self.parse_ident()?;
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
-        let default = if self.eat(&token::Eq) {
+        let expr = if self.eat(&token::Eq) {
             Some(self.parse_expr()?)
         } else {
             None
         };
         self.expect_semi()?;
-        Ok((ident, TraitItemKind::Const(ty, default), Generics::default()))
+        Ok((ident, TraitItemKind::Const(ty, expr), Generics::default()))
     }
 
     /// Parses the following grammar:
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index a078a36db7a..ba0e6b100ee 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -259,12 +259,12 @@ impl<'a> AstValidator<'a> {
                 !arr.contains(&attr.name_or_empty()) && attr::is_builtin_attr(attr)
             })
             .for_each(|attr| if attr.is_doc_comment() {
-                let mut err = self.err_handler().struct_span_err(
+                self.err_handler().struct_span_err(
                     attr.span,
                     "documentation comments cannot be applied to function parameters"
-                );
-                err.span_label(attr.span, "doc comments are not allowed here");
-                err.emit();
+                )
+                .span_label(attr.span, "doc comments are not allowed here")
+                .emit();
             }
             else {
                 self.err_handler().span_err(attr.span, "allow, cfg, cfg_attr, deny, \
@@ -746,8 +746,22 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     }
 
     fn visit_impl_item(&mut self, ii: &'a ImplItem) {
-        if let ImplItemKind::Method(ref sig, _) = ii.kind {
-            self.check_fn_decl(&sig.decl);
+        match &ii.kind {
+            ImplItemKind::Const(ty, None) => {
+                self.err_handler()
+                    .struct_span_err(ii.span, "associated constant in `impl` without body")
+                    .span_suggestion(
+                        ii.span,
+                        "provide a definition for the constant",
+                        format!("const {}: {} = <expr>;", ii.ident, pprust::ty_to_string(ty)),
+                        Applicability::HasPlaceholders,
+                    )
+                    .emit();
+            }
+            ImplItemKind::Method(sig, _) => {
+                self.check_fn_decl(&sig.decl);
+            }
+            _ => {}
         }
         visit::walk_impl_item(self, ii);
     }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 396d9484339..97cbcb6401c 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1110,7 +1110,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     impl_item.id,
                     impl_item.ident,
                     &ty,
-                    Some(expr),
+                    expr.as_deref(),
                     impl_id,
                     impl_item.vis.clone(),
                     &impl_item.attrs,
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 964acfa92b9..17a57387da7 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1635,8 +1635,8 @@ pub struct ImplItem<K = ImplItemKind> {
 
 /// Represents various kinds of content within an `impl`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub enum ImplItemKind {
-    Const(P<Ty>, P<Expr>),
+pub enum ImplItemKind  {
+    Const(P<Ty>, Option<P<Expr>>),
     Method(FnSig, P<Block>),
     TyAlias(P<Ty>),
     Macro(Mac),
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 9d0a29f2951..14701455013 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -981,7 +981,7 @@ pub fn noop_flat_map_impl_item<T: MutVisitor>(mut item: ImplItem, visitor: &mut
     match kind  {
         ImplItemKind::Const(ty, expr) => {
             visitor.visit_ty(ty);
-            visitor.visit_expr(expr);
+            visit_opt(expr, |expr| visitor.visit_expr(expr));
         }
         ImplItemKind::Method(sig, body) => {
             visit_fn_sig(sig, visitor);
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 2e3ea5e2444..c1405e15819 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1599,7 +1599,7 @@ impl<'a> State<'a> {
         self.print_defaultness(ii.defaultness);
         match ii.kind {
             ast::ImplItemKind::Const(ref ty, ref expr) => {
-                self.print_associated_const(ii.ident, ty, Some(expr), &ii.vis);
+                self.print_associated_const(ii.ident, ty, expr.as_deref(), &ii.vis);
             }
             ast::ImplItemKind::Method(ref sig, ref body) => {
                 self.head("");
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 4ee09b4b87a..0b7a7d993aa 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -617,7 +617,7 @@ pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplIt
     match impl_item.kind {
         ImplItemKind::Const(ref ty, ref expr) => {
             visitor.visit_ty(ty);
-            visitor.visit_expr(expr);
+            walk_list!(visitor, visit_expr, expr);
         }
         ImplItemKind::Method(ref sig, ref body) => {
             visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), body),
diff --git a/src/test/ui/parser/impl-item-const-pass.rs b/src/test/ui/parser/impl-item-const-pass.rs
new file mode 100644
index 00000000000..d1124561374
--- /dev/null
+++ b/src/test/ui/parser/impl-item-const-pass.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+impl X {
+    const Y: u8;
+}
diff --git a/src/test/ui/parser/impl-item-const-semantic-fail.rs b/src/test/ui/parser/impl-item-const-semantic-fail.rs
new file mode 100644
index 00000000000..5d4692f9f14
--- /dev/null
+++ b/src/test/ui/parser/impl-item-const-semantic-fail.rs
@@ -0,0 +1,7 @@
+fn main() {}
+
+struct X;
+
+impl X {
+    const Y: u8; //~ ERROR associated constant in `impl` without body
+}
diff --git a/src/test/ui/parser/impl-item-const-semantic-fail.stderr b/src/test/ui/parser/impl-item-const-semantic-fail.stderr
new file mode 100644
index 00000000000..31a15f8e80e
--- /dev/null
+++ b/src/test/ui/parser/impl-item-const-semantic-fail.stderr
@@ -0,0 +1,8 @@
+error: associated constant in `impl` without body
+  --> $DIR/impl-item-const-semantic-fail.rs:6:5
+   |
+LL |     const Y: u8;
+   |     ^^^^^^^^^^^^ help: provide a definition for the constant: `const Y: u8 = <expr>;`
+
+error: aborting due to previous error
+