Use Option in ImplItemKind::Const.

This commit is contained in:
Mazdak Farrokhzad 2019-12-01 04:12:28 +01:00
parent c4bbe9cbbe
commit 73557faed2
11 changed files with 66 additions and 20 deletions

View File

@ -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) => {

View File

@ -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:

View File

@ -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);
}

View File

@ -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,

View File

@ -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),

View File

@ -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);

View File

@ -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("");

View File

@ -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),

View File

@ -0,0 +1,8 @@
// check-pass
fn main() {}
#[cfg(FALSE)]
impl X {
const Y: u8;
}

View File

@ -0,0 +1,7 @@
fn main() {}
struct X;
impl X {
const Y: u8; //~ ERROR associated constant in `impl` without body
}

View File

@ -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