Auto merge of #98402 - cjgillot:undead, r=michaelwoerister
Rewrite dead-code pass to avoid fetching HIR. This allows to get a more uniform handling of spans, and to simplify the grouping of diagnostics for variants and fields.
This commit is contained in:
commit
5b9775fe17
@ -5,7 +5,6 @@
|
|||||||
use crate::thir::pattern::pat_from_hir;
|
use crate::thir::pattern::pat_from_hir;
|
||||||
use crate::thir::util::UserAnnotatedTyHelpers;
|
use crate::thir::util::UserAnnotatedTyHelpers;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
|
||||||
use rustc_data_structures::steal::Steal;
|
use rustc_data_structures::steal::Steal;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
@ -13,10 +12,8 @@
|
|||||||
use rustc_hir::HirId;
|
use rustc_hir::HirId;
|
||||||
use rustc_hir::Node;
|
use rustc_hir::Node;
|
||||||
use rustc_middle::middle::region;
|
use rustc_middle::middle::region;
|
||||||
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
|
|
||||||
use rustc_middle::mir::ConstantKind;
|
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt};
|
use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
pub(crate) fn thir_body<'tcx>(
|
pub(crate) fn thir_body<'tcx>(
|
||||||
@ -80,24 +77,6 @@ fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> Cx<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
|
||||||
pub(crate) fn const_eval_literal(
|
|
||||||
&mut self,
|
|
||||||
lit: &'tcx ast::LitKind,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
sp: Span,
|
|
||||||
neg: bool,
|
|
||||||
) -> ConstantKind<'tcx> {
|
|
||||||
match self.tcx.at(sp).lit_to_mir_constant(LitToConstInput { lit, ty, neg }) {
|
|
||||||
Ok(c) => c,
|
|
||||||
Err(LitToConstError::Reported) => {
|
|
||||||
// create a dummy value and continue compiling
|
|
||||||
ConstantKind::Ty(self.tcx.const_error(ty))
|
|
||||||
}
|
|
||||||
Err(LitToConstError::TypeError) => bug!("const_eval_literal: had type error"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self))]
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
|
pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
|
||||||
let p = match self.tcx.hir().get(p.hir_id) {
|
let p = match self.tcx.hir().get(p.hir_id) {
|
||||||
|
@ -10,14 +10,12 @@
|
|||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::{Node, PatKind, TyKind};
|
use rustc_hir::{Node, PatKind, TyKind};
|
||||||
use rustc_middle::hir::nested_filter;
|
|
||||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||||
use rustc_middle::middle::privacy;
|
use rustc_middle::middle::privacy;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
|
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use rustc_span::Span;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
// Any local node that may call something in its body block should be
|
// Any local node that may call something in its body block should be
|
||||||
@ -82,8 +80,8 @@ fn insert_def_id(&mut self, def_id: DefId) {
|
|||||||
|
|
||||||
fn handle_res(&mut self, res: Res) {
|
fn handle_res(&mut self, res: Res) {
|
||||||
match res {
|
match res {
|
||||||
Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, _) => {
|
Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => {
|
||||||
self.check_def_id(res.def_id());
|
self.check_def_id(def_id);
|
||||||
}
|
}
|
||||||
_ if self.in_pat => {}
|
_ if self.in_pat => {}
|
||||||
Res::PrimTy(..) | Res::SelfCtor(..) | Res::Local(..) => {}
|
Res::PrimTy(..) | Res::SelfCtor(..) | Res::Local(..) => {}
|
||||||
@ -102,6 +100,7 @@ fn handle_res(&mut self, res: Res) {
|
|||||||
self.check_def_id(variant_id);
|
self.check_def_id(variant_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Res::Def(_, def_id) => self.check_def_id(def_id),
|
||||||
Res::SelfTy { trait_: t, alias_to: i } => {
|
Res::SelfTy { trait_: t, alias_to: i } => {
|
||||||
if let Some(t) = t {
|
if let Some(t) = t {
|
||||||
self.check_def_id(t);
|
self.check_def_id(t);
|
||||||
@ -111,9 +110,6 @@ fn handle_res(&mut self, res: Res) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {}
|
Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {}
|
||||||
_ => {
|
|
||||||
self.check_def_id(res.def_id());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,20 +281,33 @@ fn visit_node(&mut self, node: Node<'tcx>) {
|
|||||||
let def = self.tcx.adt_def(item.def_id);
|
let def = self.tcx.adt_def(item.def_id);
|
||||||
self.repr_has_repr_c = def.repr().c();
|
self.repr_has_repr_c = def.repr().c();
|
||||||
|
|
||||||
intravisit::walk_item(self, &item);
|
intravisit::walk_item(self, &item)
|
||||||
}
|
|
||||||
hir::ItemKind::Enum(..) => {
|
|
||||||
intravisit::walk_item(self, &item);
|
|
||||||
}
|
}
|
||||||
hir::ItemKind::ForeignMod { .. } => {}
|
hir::ItemKind::ForeignMod { .. } => {}
|
||||||
_ => {
|
_ => intravisit::walk_item(self, &item),
|
||||||
intravisit::walk_item(self, &item);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Node::TraitItem(trait_item) => {
|
Node::TraitItem(trait_item) => {
|
||||||
intravisit::walk_trait_item(self, trait_item);
|
intravisit::walk_trait_item(self, trait_item);
|
||||||
}
|
}
|
||||||
Node::ImplItem(impl_item) => {
|
Node::ImplItem(impl_item) => {
|
||||||
|
let item = self.tcx.local_parent(impl_item.def_id);
|
||||||
|
if self.tcx.impl_trait_ref(item).is_none() {
|
||||||
|
//// If it's a type whose items are live, then it's live, too.
|
||||||
|
//// This is done to handle the case where, for example, the static
|
||||||
|
//// method of a private type is used, but the type itself is never
|
||||||
|
//// called directly.
|
||||||
|
let self_ty = self.tcx.type_of(item);
|
||||||
|
match *self_ty.kind() {
|
||||||
|
ty::Adt(def, _) => self.check_def_id(def.did()),
|
||||||
|
ty::Foreign(did) => self.check_def_id(did),
|
||||||
|
ty::Dynamic(data, ..) => {
|
||||||
|
if let Some(def_id) = data.principal_def_id() {
|
||||||
|
self.check_def_id(def_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
intravisit::walk_impl_item(self, impl_item);
|
intravisit::walk_impl_item(self, impl_item);
|
||||||
}
|
}
|
||||||
Node::ForeignItem(foreign_item) => {
|
Node::ForeignItem(foreign_item) => {
|
||||||
@ -624,8 +633,7 @@ fn live_symbols_and_ignored_derived_traits<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct DeadVariant {
|
struct DeadVariant {
|
||||||
hir_id: hir::HirId,
|
def_id: LocalDefId,
|
||||||
span: Span,
|
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
level: lint::Level,
|
level: lint::Level,
|
||||||
}
|
}
|
||||||
@ -637,85 +645,53 @@ struct DeadVisitor<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> DeadVisitor<'tcx> {
|
impl<'tcx> DeadVisitor<'tcx> {
|
||||||
fn should_warn_about_item(&mut self, item: &hir::Item<'_>) -> bool {
|
fn should_warn_about_field(&mut self, field: &ty::FieldDef) -> bool {
|
||||||
let should_warn = matches!(
|
if self.live_symbols.contains(&field.did.expect_local()) {
|
||||||
item.kind,
|
return false;
|
||||||
hir::ItemKind::Static(..)
|
|
||||||
| hir::ItemKind::Const(..)
|
|
||||||
| hir::ItemKind::Fn(..)
|
|
||||||
| hir::ItemKind::TyAlias(..)
|
|
||||||
| hir::ItemKind::Enum(..)
|
|
||||||
| hir::ItemKind::Struct(..)
|
|
||||||
| hir::ItemKind::Union(..)
|
|
||||||
);
|
|
||||||
should_warn && !self.symbol_is_live(item.def_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn should_warn_about_field(&mut self, field: &hir::FieldDef<'_>) -> bool {
|
|
||||||
let def_id = self.tcx.hir().local_def_id(field.hir_id);
|
|
||||||
let field_type = self.tcx.type_of(def_id);
|
|
||||||
!field.is_positional()
|
|
||||||
&& !self.symbol_is_live(def_id)
|
|
||||||
&& !field_type.is_phantom_data()
|
|
||||||
&& !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn should_warn_about_variant(&mut self, variant: &hir::Variant<'_>) -> bool {
|
|
||||||
let def_id = self.tcx.hir().local_def_id(variant.id);
|
|
||||||
!self.symbol_is_live(def_id) && !has_allow_dead_code_or_lang_attr(self.tcx, variant.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem<'_>) -> bool {
|
|
||||||
!self.symbol_is_live(fi.def_id) && !has_allow_dead_code_or_lang_attr(self.tcx, fi.hir_id())
|
|
||||||
}
|
|
||||||
|
|
||||||
// id := HIR id of an item's definition.
|
|
||||||
fn symbol_is_live(&mut self, def_id: LocalDefId) -> bool {
|
|
||||||
if self.live_symbols.contains(&def_id) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
// If it's a type whose items are live, then it's live, too.
|
let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit());
|
||||||
// This is done to handle the case where, for example, the static
|
if is_positional {
|
||||||
// method of a private type is used, but the type itself is never
|
return false;
|
||||||
// called directly.
|
|
||||||
let inherent_impls = self.tcx.inherent_impls(def_id);
|
|
||||||
for &impl_did in inherent_impls.iter() {
|
|
||||||
for item_did in self.tcx.associated_item_def_ids(impl_did) {
|
|
||||||
if let Some(def_id) = item_did.as_local()
|
|
||||||
&& self.live_symbols.contains(&def_id)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
false
|
let field_type = self.tcx.type_of(field.did);
|
||||||
|
!field_type.is_phantom_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn warn_multiple_dead_codes(
|
fn warn_multiple_dead_codes(
|
||||||
&self,
|
&self,
|
||||||
dead_codes: &[(hir::HirId, Span, Symbol)],
|
dead_codes: &[LocalDefId],
|
||||||
participle: &str,
|
participle: &str,
|
||||||
parent_hir_id: Option<hir::HirId>,
|
parent_item: Option<LocalDefId>,
|
||||||
) {
|
) {
|
||||||
if let Some((id, _, name)) = dead_codes.first()
|
if let Some(&first_id) = dead_codes.first() {
|
||||||
&& !name.as_str().starts_with('_')
|
let tcx = self.tcx;
|
||||||
{
|
let names: Vec<_> = dead_codes
|
||||||
self.tcx.struct_span_lint_hir(
|
.iter()
|
||||||
|
.map(|&def_id| tcx.item_name(def_id.to_def_id()).to_string())
|
||||||
|
.collect();
|
||||||
|
let spans = dead_codes
|
||||||
|
.iter()
|
||||||
|
.map(|&def_id| match tcx.def_ident_span(def_id) {
|
||||||
|
Some(s) => s.with_ctxt(tcx.def_span(def_id).ctxt()),
|
||||||
|
None => tcx.def_span(def_id),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
tcx.struct_span_lint_hir(
|
||||||
lint::builtin::DEAD_CODE,
|
lint::builtin::DEAD_CODE,
|
||||||
*id,
|
tcx.hir().local_def_id_to_hir_id(first_id),
|
||||||
MultiSpan::from_spans(
|
MultiSpan::from_spans(spans),
|
||||||
dead_codes.iter().map(|(_, span, _)| *span).collect(),
|
|
||||||
),
|
|
||||||
|lint| {
|
|lint| {
|
||||||
let def_id = self.tcx.hir().local_def_id(*id);
|
let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
|
||||||
let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
|
|
||||||
let span_len = dead_codes.len();
|
let span_len = dead_codes.len();
|
||||||
let names = match &dead_codes.iter().map(|(_, _, n)| n.to_string()).collect::<Vec<_>>()[..]
|
let names = match &names[..] {
|
||||||
{
|
|
||||||
_ if span_len > 6 => String::new(),
|
_ if span_len > 6 => String::new(),
|
||||||
[name] => format!("`{name}` "),
|
[name] => format!("`{name}` "),
|
||||||
[names @ .., last] => {
|
[names @ .., last] => {
|
||||||
format!("{} and `{last}` ", names.iter().map(|name| format!("`{name}`")).join(", "))
|
format!(
|
||||||
|
"{} and `{last}` ",
|
||||||
|
names.iter().map(|name| format!("`{name}`")).join(", ")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
[] => unreachable!(),
|
[] => unreachable!(),
|
||||||
};
|
};
|
||||||
@ -725,25 +701,17 @@ fn warn_multiple_dead_codes(
|
|||||||
s = pluralize!(span_len),
|
s = pluralize!(span_len),
|
||||||
are = pluralize!("is", span_len),
|
are = pluralize!("is", span_len),
|
||||||
));
|
));
|
||||||
let hir = self.tcx.hir();
|
|
||||||
if let Some(parent_hir_id) = parent_hir_id
|
if let Some(parent_item) = parent_item {
|
||||||
&& let Some(parent_node) = hir.find(parent_hir_id)
|
let parent_descr = tcx.def_kind(parent_item).descr(parent_item.to_def_id());
|
||||||
&& let Node::Item(item) = parent_node
|
|
||||||
{
|
|
||||||
let def_id = self.tcx.hir().local_def_id(parent_hir_id);
|
|
||||||
let parent_descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
|
|
||||||
err.span_label(
|
err.span_label(
|
||||||
item.ident.span,
|
tcx.def_ident_span(parent_item).unwrap(),
|
||||||
format!(
|
format!("{descr}{s} in this {parent_descr}", s = pluralize!(span_len)),
|
||||||
"{descr}{s} in this {parent_descr}",
|
|
||||||
s = pluralize!(span_len)
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if let Some(encl_scope) = hir.get_enclosing_scope(*id)
|
|
||||||
&& let Some(encl_def_id) = hir.opt_local_def_id(encl_scope)
|
let encl_def_id = parent_item.unwrap_or(first_id);
|
||||||
&& let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id)
|
if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) {
|
||||||
{
|
|
||||||
let traits_str = ign_traits
|
let traits_str = ign_traits
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(trait_id, _)| format!("`{}`", self.tcx.item_name(*trait_id)))
|
.map(|(trait_id, _)| format!("`{}`", self.tcx.item_name(*trait_id)))
|
||||||
@ -764,15 +732,15 @@ fn warn_multiple_dead_codes(
|
|||||||
);
|
);
|
||||||
err.note(&msg);
|
err.note(&msg);
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn warn_dead_fields_and_variants(
|
fn warn_dead_fields_and_variants(
|
||||||
&self,
|
&self,
|
||||||
hir_id: hir::HirId,
|
def_id: LocalDefId,
|
||||||
participle: &str,
|
participle: &str,
|
||||||
dead_codes: Vec<DeadVariant>,
|
dead_codes: Vec<DeadVariant>,
|
||||||
) {
|
) {
|
||||||
@ -787,196 +755,44 @@ fn warn_dead_fields_and_variants(
|
|||||||
dead_codes.sort_by_key(|v| v.level);
|
dead_codes.sort_by_key(|v| v.level);
|
||||||
for (_, group) in &dead_codes.into_iter().group_by(|v| v.level) {
|
for (_, group) in &dead_codes.into_iter().group_by(|v| v.level) {
|
||||||
self.warn_multiple_dead_codes(
|
self.warn_multiple_dead_codes(
|
||||||
&group
|
&group.map(|v| v.def_id).collect::<Vec<_>>(),
|
||||||
.map(|v| (v.hir_id, v.span, v.name))
|
|
||||||
.collect::<Vec<(hir::HirId, Span, Symbol)>>(),
|
|
||||||
participle,
|
participle,
|
||||||
Some(hir_id),
|
Some(def_id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn warn_dead_code(
|
fn warn_dead_code(&mut self, id: LocalDefId, participle: &str) {
|
||||||
&mut self,
|
self.warn_multiple_dead_codes(&[id], participle, None);
|
||||||
id: hir::HirId,
|
|
||||||
span: rustc_span::Span,
|
|
||||||
name: Symbol,
|
|
||||||
participle: &str,
|
|
||||||
) {
|
|
||||||
self.warn_multiple_dead_codes(&[(id, span, name)], participle, None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for DeadVisitor<'tcx> {
|
|
||||||
type NestedFilter = nested_filter::All;
|
|
||||||
|
|
||||||
/// Walk nested items in place so that we don't report dead-code
|
|
||||||
/// on inner functions when the outer function is already getting
|
|
||||||
/// an error. We could do this also by checking the parents, but
|
|
||||||
/// this is how the code is setup and it seems harmless enough.
|
|
||||||
fn nested_visit_map(&mut self) -> Self::Map {
|
|
||||||
self.tcx.hir()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
fn check_definition(&mut self, def_id: LocalDefId) {
|
||||||
if self.should_warn_about_item(item) {
|
if self.live_symbols.contains(&def_id) {
|
||||||
// For most items, we want to highlight its identifier
|
return;
|
||||||
let span = match item.kind {
|
|
||||||
hir::ItemKind::Fn(..)
|
|
||||||
| hir::ItemKind::Mod(..)
|
|
||||||
| hir::ItemKind::Enum(..)
|
|
||||||
| hir::ItemKind::Struct(..)
|
|
||||||
| hir::ItemKind::Union(..)
|
|
||||||
| hir::ItemKind::Trait(..)
|
|
||||||
| hir::ItemKind::Impl { .. } => {
|
|
||||||
// FIXME(66095): Because item.span is annotated with things
|
|
||||||
// like expansion data, and ident.span isn't, we use the
|
|
||||||
// def_span method if it's part of a macro invocation
|
|
||||||
// (and thus has a source_callee set).
|
|
||||||
// We should probably annotate ident.span with the macro
|
|
||||||
// context, but that's a larger change.
|
|
||||||
if item.span.source_callee().is_some() {
|
|
||||||
self.tcx.sess.source_map().guess_head_span(item.span)
|
|
||||||
} else {
|
|
||||||
item.ident.span
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => item.span,
|
|
||||||
};
|
|
||||||
let participle = match item.kind {
|
|
||||||
hir::ItemKind::Struct(..) => "constructed", // Issue #52325
|
|
||||||
_ => "used",
|
|
||||||
};
|
|
||||||
self.warn_dead_code(item.hir_id(), span, item.ident.name, participle);
|
|
||||||
} else {
|
|
||||||
// Only continue if we didn't warn
|
|
||||||
intravisit::walk_item(self, item);
|
|
||||||
}
|
}
|
||||||
}
|
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
|
||||||
|
if has_allow_dead_code_or_lang_attr(self.tcx, hir_id) {
|
||||||
// This visitor should only visit a single module at a time.
|
return;
|
||||||
fn visit_mod(&mut self, _: &'tcx hir::Mod<'tcx>, _: Span, _: hir::HirId) {}
|
|
||||||
|
|
||||||
fn visit_enum_def(
|
|
||||||
&mut self,
|
|
||||||
enum_definition: &'tcx hir::EnumDef<'tcx>,
|
|
||||||
generics: &'tcx hir::Generics<'tcx>,
|
|
||||||
item_id: hir::HirId,
|
|
||||||
_: Span,
|
|
||||||
) {
|
|
||||||
intravisit::walk_enum_def(self, enum_definition, generics, item_id);
|
|
||||||
let dead_variants = enum_definition
|
|
||||||
.variants
|
|
||||||
.iter()
|
|
||||||
.filter_map(|variant| {
|
|
||||||
if self.should_warn_about_variant(&variant) {
|
|
||||||
Some(DeadVariant {
|
|
||||||
hir_id: variant.id,
|
|
||||||
span: variant.span,
|
|
||||||
name: variant.ident.name,
|
|
||||||
level: self.tcx.lint_level_at_node(lint::builtin::DEAD_CODE, variant.id).0,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
self.warn_dead_fields_and_variants(item_id, "constructed", dead_variants)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_variant(
|
|
||||||
&mut self,
|
|
||||||
variant: &'tcx hir::Variant<'tcx>,
|
|
||||||
g: &'tcx hir::Generics<'tcx>,
|
|
||||||
id: hir::HirId,
|
|
||||||
) {
|
|
||||||
if !self.should_warn_about_variant(&variant) {
|
|
||||||
intravisit::walk_variant(self, variant, g, id);
|
|
||||||
}
|
}
|
||||||
}
|
let Some(name) = self.tcx.opt_item_name(def_id.to_def_id()) else {
|
||||||
|
return
|
||||||
fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem<'tcx>) {
|
};
|
||||||
if self.should_warn_about_foreign_item(fi) {
|
if name.as_str().starts_with('_') {
|
||||||
self.warn_dead_code(fi.hir_id(), fi.span, fi.ident.name, "used");
|
return;
|
||||||
}
|
}
|
||||||
intravisit::walk_foreign_item(self, fi);
|
match self.tcx.def_kind(def_id) {
|
||||||
}
|
DefKind::AssocConst
|
||||||
|
| DefKind::AssocFn
|
||||||
fn visit_variant_data(
|
| DefKind::Fn
|
||||||
&mut self,
|
| DefKind::Static(_)
|
||||||
def: &'tcx hir::VariantData<'tcx>,
|
| DefKind::Const
|
||||||
_: Symbol,
|
| DefKind::TyAlias
|
||||||
_: &hir::Generics<'_>,
|
| DefKind::Enum
|
||||||
id: hir::HirId,
|
| DefKind::Union
|
||||||
_: rustc_span::Span,
|
| DefKind::ForeignTy => self.warn_dead_code(def_id, "used"),
|
||||||
) {
|
DefKind::Struct => self.warn_dead_code(def_id, "constructed"),
|
||||||
intravisit::walk_struct_def(self, def);
|
DefKind::Variant | DefKind::Field => bug!("should be handled specially"),
|
||||||
let dead_fields = def
|
_ => {}
|
||||||
.fields()
|
|
||||||
.iter()
|
|
||||||
.filter_map(|field| {
|
|
||||||
if self.should_warn_about_field(&field) {
|
|
||||||
Some(DeadVariant {
|
|
||||||
hir_id: field.hir_id,
|
|
||||||
span: field.span,
|
|
||||||
name: field.ident.name,
|
|
||||||
level: self
|
|
||||||
.tcx
|
|
||||||
.lint_level_at_node(lint::builtin::DEAD_CODE, field.hir_id)
|
|
||||||
.0,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
self.warn_dead_fields_and_variants(id, "read", dead_fields)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
|
||||||
match impl_item.kind {
|
|
||||||
hir::ImplItemKind::Const(_, body_id) => {
|
|
||||||
if !self.symbol_is_live(impl_item.def_id) {
|
|
||||||
self.warn_dead_code(
|
|
||||||
impl_item.hir_id(),
|
|
||||||
impl_item.span,
|
|
||||||
impl_item.ident.name,
|
|
||||||
"used",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
self.visit_nested_body(body_id)
|
|
||||||
}
|
|
||||||
hir::ImplItemKind::Fn(_, body_id) => {
|
|
||||||
if !self.symbol_is_live(impl_item.def_id) {
|
|
||||||
// FIXME(66095): Because impl_item.span is annotated with things
|
|
||||||
// like expansion data, and ident.span isn't, we use the
|
|
||||||
// def_span method if it's part of a macro invocation
|
|
||||||
// (and thus has a source_callee set).
|
|
||||||
// We should probably annotate ident.span with the macro
|
|
||||||
// context, but that's a larger change.
|
|
||||||
let span = if impl_item.span.source_callee().is_some() {
|
|
||||||
self.tcx.sess.source_map().guess_head_span(impl_item.span)
|
|
||||||
} else {
|
|
||||||
impl_item.ident.span
|
|
||||||
};
|
|
||||||
self.warn_dead_code(impl_item.hir_id(), span, impl_item.ident.name, "used");
|
|
||||||
}
|
|
||||||
self.visit_nested_body(body_id)
|
|
||||||
}
|
|
||||||
hir::ImplItemKind::TyAlias(..) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overwrite so that we don't warn the trait item itself.
|
|
||||||
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
|
|
||||||
match trait_item.kind {
|
|
||||||
hir::TraitItemKind::Const(_, Some(body_id))
|
|
||||||
| hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => {
|
|
||||||
self.visit_nested_body(body_id)
|
|
||||||
}
|
|
||||||
hir::TraitItemKind::Const(_, None)
|
|
||||||
| hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_))
|
|
||||||
| hir::TraitItemKind::Type(..) => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -984,10 +800,65 @@ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
|
|||||||
fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
|
fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
|
||||||
let (live_symbols, ignored_derived_traits) = tcx.live_symbols_and_ignored_derived_traits(());
|
let (live_symbols, ignored_derived_traits) = tcx.live_symbols_and_ignored_derived_traits(());
|
||||||
let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits };
|
let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits };
|
||||||
let (module, _, module_id) = tcx.hir().get_module(module);
|
|
||||||
// Do not use an ItemLikeVisitor since we may want to skip visiting some items
|
let module_items = tcx.hir_module_items(module);
|
||||||
// when a surrounding one is warned against or `_`.
|
|
||||||
intravisit::walk_mod(&mut visitor, module, module_id);
|
for item in module_items.items() {
|
||||||
|
if !live_symbols.contains(&item.def_id) {
|
||||||
|
let parent = tcx.local_parent(item.def_id);
|
||||||
|
if parent != module && !live_symbols.contains(&parent) {
|
||||||
|
// We already have diagnosed something.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
visitor.check_definition(item.def_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let def_kind = tcx.def_kind(item.def_id);
|
||||||
|
if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind {
|
||||||
|
let adt = tcx.adt_def(item.def_id);
|
||||||
|
let mut dead_variants = Vec::new();
|
||||||
|
|
||||||
|
for variant in adt.variants() {
|
||||||
|
let def_id = variant.def_id.expect_local();
|
||||||
|
if !live_symbols.contains(&def_id) {
|
||||||
|
// Record to group diagnostics.
|
||||||
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||||
|
let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
|
||||||
|
dead_variants.push(DeadVariant { def_id, name: variant.name, level });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dead_fields = variant
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.filter_map(|field| {
|
||||||
|
let def_id = field.did.expect_local();
|
||||||
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||||
|
if visitor.should_warn_about_field(&field) {
|
||||||
|
let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
|
||||||
|
Some(DeadVariant { def_id, name: field.name, level })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
visitor.warn_dead_fields_and_variants(def_id, "read", dead_fields)
|
||||||
|
}
|
||||||
|
|
||||||
|
visitor.warn_dead_fields_and_variants(item.def_id, "constructed", dead_variants);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for impl_item in module_items.impl_items() {
|
||||||
|
visitor.check_definition(impl_item.def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for foreign_item in module_items.foreign_items() {
|
||||||
|
visitor.check_definition(foreign_item.def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We do not warn trait items.
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn provide(providers: &mut Providers) {
|
pub(crate) fn provide(providers: &mut Providers) {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error: associated constant `BAR` is never used
|
error: associated constant `BAR` is never used
|
||||||
--> $DIR/associated-const-dead-code.rs:6:5
|
--> $DIR/associated-const-dead-code.rs:6:11
|
||||||
|
|
|
|
||||||
LL | const BAR: u32 = 1;
|
LL | const BAR: u32 = 1;
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/associated-const-dead-code.rs:1:9
|
--> $DIR/associated-const-dead-code.rs:1:9
|
||||||
|
@ -4,9 +4,9 @@ warning: fields `field_1` and `field_2` are never read
|
|||||||
LL | struct Props {
|
LL | struct Props {
|
||||||
| ----- fields in this struct
|
| ----- fields in this struct
|
||||||
LL | field_1: u32,
|
LL | field_1: u32,
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^
|
||||||
LL | field_2: u32,
|
LL | field_2: u32,
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `#[warn(dead_code)]` on by default
|
= note: `#[warn(dead_code)]` on by default
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ LL | enum Foo {
|
|||||||
| --- variant in this enum
|
| --- variant in this enum
|
||||||
LL | Bar(u8),
|
LL | Bar(u8),
|
||||||
LL | Void(Void),
|
LL | Void(Void),
|
||||||
| ^^^^^^^^^^
|
| ^^^^
|
||||||
|
|
|
|
||||||
= note: `-W dead-code` implied by `-W unused`
|
= note: `-W dead-code` implied by `-W unused`
|
||||||
= note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
|
= note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
|
||||||
|
@ -5,13 +5,13 @@ LL | pub struct Whatever {
|
|||||||
| -------- fields in this struct
|
| -------- fields in this struct
|
||||||
LL | pub field0: (),
|
LL | pub field0: (),
|
||||||
LL | field1: (),
|
LL | field1: (),
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^
|
||||||
LL | field2: (),
|
LL | field2: (),
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^
|
||||||
LL | field3: (),
|
LL | field3: (),
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^
|
||||||
LL | field4: (),
|
LL | field4: (),
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11
|
--> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11
|
||||||
|
@ -2,7 +2,7 @@ error: field `f` is never read
|
|||||||
--> $DIR/clone-debug-dead-code.rs:6:12
|
--> $DIR/clone-debug-dead-code.rs:6:12
|
||||||
|
|
|
|
||||||
LL | struct A { f: () }
|
LL | struct A { f: () }
|
||||||
| - ^^^^^
|
| - ^
|
||||||
| |
|
| |
|
||||||
| field in this struct
|
| field in this struct
|
||||||
|
|
|
|
||||||
@ -16,7 +16,7 @@ error: field `f` is never read
|
|||||||
--> $DIR/clone-debug-dead-code.rs:10:12
|
--> $DIR/clone-debug-dead-code.rs:10:12
|
||||||
|
|
|
|
||||||
LL | struct B { f: () }
|
LL | struct B { f: () }
|
||||||
| - ^^^^^
|
| - ^
|
||||||
| |
|
| |
|
||||||
| field in this struct
|
| field in this struct
|
||||||
|
|
|
|
||||||
@ -26,7 +26,7 @@ error: field `f` is never read
|
|||||||
--> $DIR/clone-debug-dead-code.rs:14:12
|
--> $DIR/clone-debug-dead-code.rs:14:12
|
||||||
|
|
|
|
||||||
LL | struct C { f: () }
|
LL | struct C { f: () }
|
||||||
| - ^^^^^
|
| - ^
|
||||||
| |
|
| |
|
||||||
| field in this struct
|
| field in this struct
|
||||||
|
|
|
|
||||||
@ -36,7 +36,7 @@ error: field `f` is never read
|
|||||||
--> $DIR/clone-debug-dead-code.rs:18:12
|
--> $DIR/clone-debug-dead-code.rs:18:12
|
||||||
|
|
|
|
||||||
LL | struct D { f: () }
|
LL | struct D { f: () }
|
||||||
| - ^^^^^
|
| - ^
|
||||||
| |
|
| |
|
||||||
| field in this struct
|
| field in this struct
|
||||||
|
|
|
|
||||||
@ -46,7 +46,7 @@ error: field `f` is never read
|
|||||||
--> $DIR/clone-debug-dead-code.rs:21:12
|
--> $DIR/clone-debug-dead-code.rs:21:12
|
||||||
|
|
|
|
||||||
LL | struct E { f: () }
|
LL | struct E { f: () }
|
||||||
| - ^^^^^
|
| - ^
|
||||||
| |
|
| |
|
||||||
| field in this struct
|
| field in this struct
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
warning: type alias `Z` is never used
|
warning: type alias `Z` is never used
|
||||||
--> $DIR/issue-37515.rs:5:1
|
--> $DIR/issue-37515.rs:5:6
|
||||||
|
|
|
|
||||||
LL | type Z = dyn for<'x> Send;
|
LL | type Z = dyn for<'x> Send;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/issue-37515.rs:3:9
|
--> $DIR/issue-37515.rs:3:9
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error: type alias `Unused` is never used
|
error: type alias `Unused` is never used
|
||||||
--> $DIR/impl-trait.rs:12:1
|
--> $DIR/impl-trait.rs:12:6
|
||||||
|
|
|
|
||||||
LL | type Unused = ();
|
LL | type Unused = ();
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/impl-trait.rs:1:9
|
--> $DIR/impl-trait.rs:1:9
|
||||||
|
@ -4,9 +4,9 @@ warning: fields `a` and `b` are never read
|
|||||||
LL | struct Foo {
|
LL | struct Foo {
|
||||||
| --- fields in this struct
|
| --- fields in this struct
|
||||||
LL | a: i32,
|
LL | a: i32,
|
||||||
| ^^^^^^
|
| ^
|
||||||
LL | pub b: i32,
|
LL | pub b: i32,
|
||||||
| ^^^^^^^^^^
|
| ^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/issue-85255.rs:4:9
|
--> $DIR/issue-85255.rs:4:9
|
||||||
@ -14,6 +14,26 @@ note: the lint level is defined here
|
|||||||
LL | #![warn(dead_code)]
|
LL | #![warn(dead_code)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
warning: fields `a` and `b` are never read
|
||||||
|
--> $DIR/issue-85255.rs:19:5
|
||||||
|
|
|
||||||
|
LL | pub(crate) struct Foo1 {
|
||||||
|
| ---- fields in this struct
|
||||||
|
LL | a: i32,
|
||||||
|
| ^
|
||||||
|
LL | pub b: i32,
|
||||||
|
| ^
|
||||||
|
|
||||||
|
warning: fields `a` and `b` are never read
|
||||||
|
--> $DIR/issue-85255.rs:31:5
|
||||||
|
|
|
||||||
|
LL | pub(crate) struct Foo2 {
|
||||||
|
| ---- fields in this struct
|
||||||
|
LL | a: i32,
|
||||||
|
| ^
|
||||||
|
LL | pub b: i32,
|
||||||
|
| ^
|
||||||
|
|
||||||
warning: associated function `a` is never used
|
warning: associated function `a` is never used
|
||||||
--> $DIR/issue-85255.rs:14:8
|
--> $DIR/issue-85255.rs:14:8
|
||||||
|
|
|
|
||||||
@ -26,16 +46,6 @@ warning: associated function `b` is never used
|
|||||||
LL | pub fn b(&self) -> i32 { 6 }
|
LL | pub fn b(&self) -> i32 { 6 }
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
warning: fields `a` and `b` are never read
|
|
||||||
--> $DIR/issue-85255.rs:19:5
|
|
||||||
|
|
|
||||||
LL | pub(crate) struct Foo1 {
|
|
||||||
| ---- fields in this struct
|
|
||||||
LL | a: i32,
|
|
||||||
| ^^^^^^
|
|
||||||
LL | pub b: i32,
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
|
|
||||||
warning: associated function `a` is never used
|
warning: associated function `a` is never used
|
||||||
--> $DIR/issue-85255.rs:26:8
|
--> $DIR/issue-85255.rs:26:8
|
||||||
|
|
|
|
||||||
@ -48,16 +58,6 @@ warning: associated function `b` is never used
|
|||||||
LL | pub fn b(&self) -> i32 { 6 }
|
LL | pub fn b(&self) -> i32 { 6 }
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
warning: fields `a` and `b` are never read
|
|
||||||
--> $DIR/issue-85255.rs:31:5
|
|
||||||
|
|
|
||||||
LL | pub(crate) struct Foo2 {
|
|
||||||
| ---- fields in this struct
|
|
||||||
LL | a: i32,
|
|
||||||
| ^^^^^^
|
|
||||||
LL | pub b: i32,
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
|
|
||||||
warning: associated function `a` is never used
|
warning: associated function `a` is never used
|
||||||
--> $DIR/issue-85255.rs:38:8
|
--> $DIR/issue-85255.rs:38:8
|
||||||
|
|
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error: static `priv_static` is never used
|
error: static `priv_static` is never used
|
||||||
--> $DIR/lint-dead-code-1.rs:20:1
|
--> $DIR/lint-dead-code-1.rs:20:8
|
||||||
|
|
|
|
||||||
LL | static priv_static: isize = 0;
|
LL | static priv_static: isize = 0;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/lint-dead-code-1.rs:5:9
|
--> $DIR/lint-dead-code-1.rs:5:9
|
||||||
@ -11,10 +11,10 @@ LL | #![deny(dead_code)]
|
|||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: constant `priv_const` is never used
|
error: constant `priv_const` is never used
|
||||||
--> $DIR/lint-dead-code-1.rs:27:1
|
--> $DIR/lint-dead-code-1.rs:27:7
|
||||||
|
|
|
|
||||||
LL | const priv_const: isize = 0;
|
LL | const priv_const: isize = 0;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: struct `PrivStruct` is never constructed
|
error: struct `PrivStruct` is never constructed
|
||||||
--> $DIR/lint-dead-code-1.rs:35:8
|
--> $DIR/lint-dead-code-1.rs:35:8
|
||||||
|
@ -73,7 +73,18 @@ impl Trait for isize {}
|
|||||||
fn f() {}
|
fn f() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn anon_const() -> [(); {
|
||||||
|
fn blah() {} //~ ERROR: function `blah` is never used
|
||||||
|
1
|
||||||
|
}] {
|
||||||
|
[(); {
|
||||||
|
fn blah() {} //~ ERROR: function `blah` is never used
|
||||||
|
1
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
pub fn foo() {
|
pub fn foo() {
|
||||||
let a: &dyn inner::Trait = &1_isize;
|
let a: &dyn inner::Trait = &1_isize;
|
||||||
a.f();
|
a.f();
|
||||||
|
anon_const();
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,6 @@ note: the lint level is defined here
|
|||||||
LL | #![deny(dead_code)]
|
LL | #![deny(dead_code)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: associated function `foo` is never used
|
|
||||||
--> $DIR/lint-dead-code-3.rs:16:8
|
|
||||||
|
|
|
||||||
LL | fn foo(&self) {
|
|
||||||
| ^^^
|
|
||||||
|
|
||||||
error: function `bar` is never used
|
error: function `bar` is never used
|
||||||
--> $DIR/lint-dead-code-3.rs:21:4
|
--> $DIR/lint-dead-code-3.rs:21:4
|
||||||
|
|
|
|
||||||
@ -28,11 +22,29 @@ error: enum `c_void` is never used
|
|||||||
LL | enum c_void {}
|
LL | enum c_void {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: function `blah` is never used
|
||||||
|
--> $DIR/lint-dead-code-3.rs:77:8
|
||||||
|
|
|
||||||
|
LL | fn blah() {}
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error: function `blah` is never used
|
||||||
|
--> $DIR/lint-dead-code-3.rs:81:12
|
||||||
|
|
|
||||||
|
LL | fn blah() {}
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error: associated function `foo` is never used
|
||||||
|
--> $DIR/lint-dead-code-3.rs:16:8
|
||||||
|
|
|
||||||
|
LL | fn foo(&self) {
|
||||||
|
| ^^^
|
||||||
|
|
||||||
error: function `free` is never used
|
error: function `free` is never used
|
||||||
--> $DIR/lint-dead-code-3.rs:62:5
|
--> $DIR/lint-dead-code-3.rs:62:8
|
||||||
|
|
|
|
||||||
LL | fn free(p: *const c_void);
|
LL | fn free(p: *const c_void);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ LL | struct Foo {
|
|||||||
| --- field in this struct
|
| --- field in this struct
|
||||||
LL | x: usize,
|
LL | x: usize,
|
||||||
LL | b: bool,
|
LL | b: bool,
|
||||||
| ^^^^^^^
|
| ^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/lint-dead-code-4.rs:3:9
|
--> $DIR/lint-dead-code-4.rs:3:9
|
||||||
@ -16,16 +16,12 @@ LL | #![deny(dead_code)]
|
|||||||
error: variants `X` and `Y` are never constructed
|
error: variants `X` and `Y` are never constructed
|
||||||
--> $DIR/lint-dead-code-4.rs:15:5
|
--> $DIR/lint-dead-code-4.rs:15:5
|
||||||
|
|
|
|
||||||
LL | enum XYZ {
|
LL | enum XYZ {
|
||||||
| --- variants in this enum
|
| --- variants in this enum
|
||||||
LL | X,
|
LL | X,
|
||||||
| ^
|
| ^
|
||||||
LL | / Y {
|
LL | Y {
|
||||||
LL | | a: String,
|
| ^
|
||||||
LL | | b: i32,
|
|
||||||
LL | | c: i32,
|
|
||||||
LL | | },
|
|
||||||
| |_____^
|
|
||||||
|
|
||||||
error: enum `ABC` is never used
|
error: enum `ABC` is never used
|
||||||
--> $DIR/lint-dead-code-4.rs:24:6
|
--> $DIR/lint-dead-code-4.rs:24:6
|
||||||
@ -36,13 +32,13 @@ LL | enum ABC {
|
|||||||
error: fields `b` and `c` are never read
|
error: fields `b` and `c` are never read
|
||||||
--> $DIR/lint-dead-code-4.rs:39:9
|
--> $DIR/lint-dead-code-4.rs:39:9
|
||||||
|
|
|
|
||||||
LL | enum IJK {
|
LL | J {
|
||||||
| --- fields in this enum
|
| - fields in this variant
|
||||||
...
|
LL | a: String,
|
||||||
LL | b: i32,
|
LL | b: i32,
|
||||||
| ^^^^^^
|
| ^
|
||||||
LL | c: i32,
|
LL | c: i32,
|
||||||
| ^^^^^^
|
| ^
|
||||||
|
|
||||||
error: variants `I` and `K` are never constructed
|
error: variants `I` and `K` are never constructed
|
||||||
--> $DIR/lint-dead-code-4.rs:36:5
|
--> $DIR/lint-dead-code-4.rs:36:5
|
||||||
@ -61,10 +57,10 @@ error: fields `x` and `c` are never read
|
|||||||
LL | struct Bar {
|
LL | struct Bar {
|
||||||
| --- fields in this struct
|
| --- fields in this struct
|
||||||
LL | x: usize,
|
LL | x: usize,
|
||||||
| ^^^^^^^^
|
| ^
|
||||||
LL | b: bool,
|
LL | b: bool,
|
||||||
LL | c: bool,
|
LL | c: bool,
|
||||||
| ^^^^^^^
|
| ^
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@ LL | enum Enum2 {
|
|||||||
| ----- variants in this enum
|
| ----- variants in this enum
|
||||||
...
|
...
|
||||||
LL | Variant5 { _x: isize },
|
LL | Variant5 { _x: isize },
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^
|
||||||
LL | Variant6(isize),
|
LL | Variant6(isize),
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: enum `Enum3` is never used
|
error: enum `Enum3` is never used
|
||||||
--> $DIR/lint-dead-code-5.rs:35:6
|
--> $DIR/lint-dead-code-5.rs:35:6
|
||||||
|
@ -5,12 +5,12 @@ LL | struct Bar {
|
|||||||
| --- fields in this struct
|
| --- fields in this struct
|
||||||
...
|
...
|
||||||
LL | d: usize,
|
LL | d: usize,
|
||||||
| ^^^^^^^^
|
| ^
|
||||||
...
|
...
|
||||||
LL | f: usize,
|
LL | f: usize,
|
||||||
| ^^^^^^^^
|
| ^
|
||||||
LL | g: usize,
|
LL | g: usize,
|
||||||
| ^^^^^^^^
|
| ^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/multiple-dead-codes-in-the-same-struct.rs:1:9
|
--> $DIR/multiple-dead-codes-in-the-same-struct.rs:1:9
|
||||||
@ -25,10 +25,10 @@ LL | struct Bar {
|
|||||||
| --- fields in this struct
|
| --- fields in this struct
|
||||||
...
|
...
|
||||||
LL | c: usize,
|
LL | c: usize,
|
||||||
| ^^^^^^^^
|
| ^
|
||||||
...
|
...
|
||||||
LL | e: usize,
|
LL | e: usize,
|
||||||
| ^^^^^^^^
|
| ^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/multiple-dead-codes-in-the-same-struct.rs:8:12
|
--> $DIR/multiple-dead-codes-in-the-same-struct.rs:8:12
|
||||||
@ -43,7 +43,7 @@ LL | struct Bar {
|
|||||||
| --- field in this struct
|
| --- field in this struct
|
||||||
...
|
...
|
||||||
LL | b: usize,
|
LL | b: usize,
|
||||||
| ^^^^^^^^
|
| ^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/multiple-dead-codes-in-the-same-struct.rs:6:14
|
--> $DIR/multiple-dead-codes-in-the-same-struct.rs:6:14
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error: type alias `Unused` is never used
|
error: type alias `Unused` is never used
|
||||||
--> $DIR/type-alias.rs:4:1
|
--> $DIR/type-alias.rs:4:6
|
||||||
|
|
|
|
||||||
LL | type Unused = u8;
|
LL | type Unused = u8;
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/type-alias.rs:1:9
|
--> $DIR/type-alias.rs:1:9
|
||||||
|
@ -5,7 +5,7 @@ LL | enum E {
|
|||||||
| - variant in this enum
|
| - variant in this enum
|
||||||
LL | Foo(F),
|
LL | Foo(F),
|
||||||
LL | Bar(B),
|
LL | Bar(B),
|
||||||
| ^^^^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/unused-struct-variant.rs:1:9
|
--> $DIR/unused-struct-variant.rs:1:9
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error: constant `foo` is never used
|
error: constant `foo` is never used
|
||||||
--> $DIR/issue-17718-const-naming.rs:4:1
|
--> $DIR/issue-17718-const-naming.rs:4:7
|
||||||
|
|
|
|
||||||
LL | const foo: isize = 3;
|
LL | const foo: isize = 3;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/issue-17718-const-naming.rs:2:9
|
--> $DIR/issue-17718-const-naming.rs:2:9
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
warning: struct `S` is never constructed
|
warning: struct `S` is never constructed
|
||||||
--> $DIR/macro-span-replacement.rs:7:14
|
--> $DIR/macro-span-replacement.rs:7:12
|
||||||
|
|
|
|
||||||
LL | $b $a;
|
LL | $b $a;
|
||||||
| ^
|
| ^^
|
||||||
...
|
...
|
||||||
LL | m!(S struct);
|
LL | m!(S struct);
|
||||||
| ------------ in this macro invocation
|
| ------------ in this macro invocation
|
||||||
|
@ -5,7 +5,7 @@ LL | union U1 {
|
|||||||
| -- field in this union
|
| -- field in this union
|
||||||
...
|
...
|
||||||
LL | c: u8,
|
LL | c: u8,
|
||||||
| ^^^^^
|
| ^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/union-fields-1.rs:4:9
|
--> $DIR/union-fields-1.rs:4:9
|
||||||
@ -19,13 +19,13 @@ error: field `a` is never read
|
|||||||
LL | union U2 {
|
LL | union U2 {
|
||||||
| -- field in this union
|
| -- field in this union
|
||||||
LL | a: u8,
|
LL | a: u8,
|
||||||
| ^^^^^
|
| ^
|
||||||
|
|
||||||
error: field `a` is never read
|
error: field `a` is never read
|
||||||
--> $DIR/union-fields-1.rs:16:20
|
--> $DIR/union-fields-1.rs:16:20
|
||||||
|
|
|
|
||||||
LL | union NoDropLike { a: u8 }
|
LL | union NoDropLike { a: u8 }
|
||||||
| ---------- ^^^^^
|
| ---------- ^
|
||||||
| |
|
| |
|
||||||
| field in this union
|
| field in this union
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ LL | union U {
|
|||||||
| - field in this union
|
| - field in this union
|
||||||
...
|
...
|
||||||
LL | c: u8,
|
LL | c: u8,
|
||||||
| ^^^^^
|
| ^
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ LL | union U1 {
|
|||||||
| -- field in this union
|
| -- field in this union
|
||||||
...
|
...
|
||||||
LL | c: u8,
|
LL | c: u8,
|
||||||
| ^^^^^
|
| ^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/union-fields-1.rs:4:9
|
--> $DIR/union-fields-1.rs:4:9
|
||||||
@ -19,13 +19,13 @@ error: field `a` is never read
|
|||||||
LL | union U2 {
|
LL | union U2 {
|
||||||
| -- field in this union
|
| -- field in this union
|
||||||
LL | a: u8,
|
LL | a: u8,
|
||||||
| ^^^^^
|
| ^
|
||||||
|
|
||||||
error: field `a` is never read
|
error: field `a` is never read
|
||||||
--> $DIR/union-fields-1.rs:16:20
|
--> $DIR/union-fields-1.rs:16:20
|
||||||
|
|
|
|
||||||
LL | union NoDropLike { a: u8 }
|
LL | union NoDropLike { a: u8 }
|
||||||
| ---------- ^^^^^
|
| ---------- ^
|
||||||
| |
|
| |
|
||||||
| field in this union
|
| field in this union
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ LL | union U {
|
|||||||
| - field in this union
|
| - field in this union
|
||||||
...
|
...
|
||||||
LL | c: u8,
|
LL | c: u8,
|
||||||
| ^^^^^
|
| ^
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ LL | union Foo {
|
|||||||
| --- field in this union
|
| --- field in this union
|
||||||
LL | x: usize,
|
LL | x: usize,
|
||||||
LL | b: bool,
|
LL | b: bool,
|
||||||
| ^^^^^^^
|
| ^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/union-lint-dead-code.rs:4:9
|
--> $DIR/union-lint-dead-code.rs:4:9
|
||||||
|
@ -5,7 +5,7 @@ LL | union Foo {
|
|||||||
| --- field in this union
|
| --- field in this union
|
||||||
LL | x: usize,
|
LL | x: usize,
|
||||||
LL | b: bool,
|
LL | b: bool,
|
||||||
| ^^^^^^^
|
| ^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/union-lint-dead-code.rs:4:9
|
--> $DIR/union-lint-dead-code.rs:4:9
|
||||||
|
Loading…
Reference in New Issue
Block a user