From 49238ad1d20538c778b4b3a820f4e630ab8d2a1f Mon Sep 17 00:00:00 2001 From: Owen Sanchez Date: Sat, 4 Feb 2017 21:52:44 -0700 Subject: [PATCH] Implement empty_enum lint and add a test --- clippy_lints/src/empty_enum.rs | 50 +++++--------------------------- tests/compile-fail/empty_enum.rs | 10 +++++++ 2 files changed, 17 insertions(+), 43 deletions(-) create mode 100644 tests/compile-fail/empty_enum.rs diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 17be52d65..f930a8599 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -2,10 +2,7 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{span_lint_and_then, snippet_opt}; -use rustc::ty::layout::TargetDataLayout; -use rustc::ty::TypeFoldable; -use rustc::traits::Reveal; +use utils::span_lint_and_then; /// **What it does:** Checks for `enum`s with no variants. /// @@ -19,7 +16,7 @@ use rustc::traits::Reveal; /// ``` declare_lint! { pub EMPTY_ENUM, - Warn, + Allow, "enum with no variants" } @@ -35,46 +32,13 @@ impl LintPass for EmptyEnum { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum { fn check_item(&mut self, cx: &LateContext, item: &Item) { let did = cx.tcx.hir.local_def_id(item.id); - if let ItemEnum(ref def, _) = item.node { + if let ItemEnum(..) = item.node { let ty = cx.tcx.item_type(did); let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); - for (i, variant) in adt.variants.iter().enumerate() { - let data_layout = TargetDataLayout::parse(cx.sess()); - cx.tcx.infer_ctxt((), Reveal::All).enter(|infcx| { - let size: u64 = variant.fields - .iter() - .map(|f| { - let ty = cx.tcx.item_type(f.did); - if ty.needs_subst() { - 0 // we can't reason about generics, so we treat them as zero sized - } else { - ty.layout(&infcx) - .expect("layout should be computable for concrete type") - .size(&data_layout) - .bytes() - } - }) - .sum(); - if size > 0 { - span_lint_and_then(cx, EMPTY_ENUM, def.variants[i].span, "large enum variant found", |db| { - if variant.fields.len() == 1 { - let span = match def.variants[i].node.data { - VariantData::Struct(ref fields, _) | - VariantData::Tuple(ref fields, _) => fields[0].ty.span, - VariantData::Unit(_) => unreachable!(), - }; - if let Some(snip) = snippet_opt(cx, span) { - db.span_suggestion(span, - "consider boxing the large fields to reduce the total size of \ - the enum", - format!("Box<{}>", snip)); - return; - } - } - db.span_help(def.variants[i].span, - "consider boxing the large fields to reduce the total size of the enum"); - }); - } + if adt.variants.is_empty() { + span_lint_and_then(cx, EMPTY_ENUM, item.span, "enum with no variants", |db| { + db.span_help(item.span, + "consider using the uninhabited type `!` or a wrapper around it"); }); } } diff --git a/tests/compile-fail/empty_enum.rs b/tests/compile-fail/empty_enum.rs new file mode 100644 index 000000000..f6a9de3c7 --- /dev/null +++ b/tests/compile-fail/empty_enum.rs @@ -0,0 +1,10 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(empty_enum)] + +enum Empty {} //~ ERROR enum with no variants + //~^ HELP consider using the uninhabited type `!` or a wrapper around it + +fn main() { +}