Prohibit #[default] in invalid places

This commit is contained in:
Jacob Pratt 2021-07-17 01:05:57 -04:00
parent 5ae2371ceb
commit 72465b0a32
No known key found for this signature in database
GPG key ID: B80E19E4662B5AA4
3 changed files with 131 additions and 29 deletions

View file

@ -2,6 +2,7 @@ use crate::deriving::generic::ty::*;
use crate::deriving::generic::*;
use rustc_ast::ptr::P;
use rustc_ast::walk_list;
use rustc_ast::EnumDef;
use rustc_ast::VariantData;
use rustc_ast::{Expr, MetaItem};
@ -19,6 +20,8 @@ pub fn expand_deriving_default(
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
) {
item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
let inline = cx.meta_word(span, sym::inline);
let attrs = vec![cx.attribute(inline)];
let trait_def = TraitDef {
@ -184,9 +187,12 @@ fn extract_default_variant<'a>(
};
if !matches!(variant.data, VariantData::Unit(..)) {
cx.struct_span_err(variant.ident.span, "`#[default]` may only be used on unit variants")
.help("consider a manual implementation of `Default`")
.emit();
cx.struct_span_err(
variant.ident.span,
"the `#[default]` attribute may only be used on unit enum variants",
)
.help("consider a manual implementation of `Default`")
.emit();
return Err(());
}
@ -253,3 +259,31 @@ fn validate_default_attribute(
}
Ok(())
}
struct DetectNonVariantDefaultAttr<'a, 'b> {
cx: &'a ExtCtxt<'b>,
}
impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {
fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {
if attr.has_name(kw::Default) {
self.cx
.struct_span_err(
attr.span,
"the `#[default]` attribute may only be used on unit enum variants",
)
.emit();
}
rustc_ast::visit::walk_attribute(self, attr);
}
fn visit_variant(&mut self, v: &'a rustc_ast::Variant) {
self.visit_ident(v.ident);
self.visit_vis(&v.vis);
self.visit_variant_data(&v.data);
walk_list!(self, visit_anon_const, &v.disr_expr);
for attr in &v.attrs {
rustc_ast::visit::walk_attribute(self, attr);
}
}
}