From 73557faed23678fc443f3fa52727b5f200f597d2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 04:12:28 +0100 Subject: [PATCH] Use `Option` in `ImplItemKind::Const`. --- src/librustc/hir/lowering/item.rs | 8 +++++- src/librustc_parse/parser/item.rs | 17 +++++++----- src/librustc_passes/ast_validation.rs | 26 ++++++++++++++----- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/libsyntax/ast.rs | 4 +-- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 2 +- src/test/ui/parser/impl-item-const-pass.rs | 8 ++++++ .../parser/impl-item-const-semantic-fail.rs | 7 +++++ .../impl-item-const-semantic-fail.stderr | 8 ++++++ 11 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/parser/impl-item-const-pass.rs create mode 100644 src/test/ui/parser/impl-item-const-semantic-fail.rs create mode 100644 src/test/ui/parser/impl-item-const-semantic-fail.stderr 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 {}: {} = ;", 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 { /// Represents various kinds of content within an `impl`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ImplItemKind { - Const(P, P), +pub enum ImplItemKind { + Const(P, Option>), Method(FnSig, P), TyAlias(P), 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(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 = ;` + +error: aborting due to previous error +