mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-21 17:52:12 +03:00
Merge ref '32bd660612bf' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh. Upstream ref: rust-lang/rust@32bd660612 Filtered ref: rust-lang/miri@771a0a0d3a Upstream diff: https://github.com/rust-lang/rust/compare/4ddd4538a881317c622ed674b08300b8fc8dabdd...32bd660612bf1c61bdf290a3ec643c8538b8357d This merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
@@ -115,6 +115,11 @@ fn mir_borrowck(
|
||||
def: LocalDefId,
|
||||
) -> Result<&FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'_>>, ErrorGuaranteed> {
|
||||
assert!(!tcx.is_typeck_child(def.to_def_id()));
|
||||
if tcx.is_trivial_const(def) {
|
||||
debug!("Skipping borrowck because of trivial const");
|
||||
let opaque_types = Default::default();
|
||||
return Ok(tcx.arena.alloc(opaque_types));
|
||||
}
|
||||
let (input_body, _) = tcx.mir_promoted(def);
|
||||
debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
CONST_EVALUATABLE_UNCHECKED,
|
||||
CONST_ITEM_MUTATION,
|
||||
DEAD_CODE,
|
||||
DEAD_CODE_PUB_IN_BINARY,
|
||||
DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
|
||||
DEPRECATED,
|
||||
DEPRECATED_IN_FUTURE,
|
||||
@@ -789,6 +790,37 @@
|
||||
"detect unused, unexported items"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `dead_code_pub_in_binary` lint detects unused `pub` items in
|
||||
/// executable crates.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// #![deny(dead_code_pub_in_binary)]
|
||||
///
|
||||
/// pub fn unused_pub_fn() {}
|
||||
///
|
||||
/// fn main() {}
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// In executable crates, `pub` items are often implementation details
|
||||
/// rather than part of an external API. This lint helps find those items
|
||||
/// when they are never used.
|
||||
///
|
||||
/// This lint only applies to executable crates. In library crates, public
|
||||
/// items are considered part of the crate's API and are not reported by
|
||||
/// this lint.
|
||||
pub DEAD_CODE_PUB_IN_BINARY,
|
||||
Allow,
|
||||
"detect public items in executable crates that are never used",
|
||||
crate_level_only
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `unused_attributes` lint detects attributes that were not used by
|
||||
/// the compiler.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_hir::def_id::{DefId, LocalDefIdMap, LocalDefIdSet};
|
||||
use rustc_macros::StableHash;
|
||||
|
||||
/// A single snapshot of dead-code liveness analysis state.
|
||||
#[derive(Clone, Debug, StableHash)]
|
||||
pub struct DeadCodeLivenessSnapshot {
|
||||
pub live_symbols: LocalDefIdSet,
|
||||
/// Maps each ADT to derived traits (for example `Debug` and `Clone`) that should be ignored
|
||||
/// when checking for dead code diagnostics.
|
||||
pub ignored_derived_traits: LocalDefIdMap<FxIndexSet<DefId>>,
|
||||
}
|
||||
|
||||
/// Dead-code liveness data for both analysis phases.
|
||||
///
|
||||
/// `pre_deferred_seeding` is computed before reachable-public and `#[allow(dead_code)]` seeding,
|
||||
/// and is used for lint `dead_code_pub_in_binary`.
|
||||
/// `final_result` is the final liveness snapshot used for lint `dead_code`.
|
||||
#[derive(Clone, Debug, StableHash)]
|
||||
pub struct DeadCodeLivenessSummary {
|
||||
pub pre_deferred_seeding: DeadCodeLivenessSnapshot,
|
||||
pub final_result: DeadCodeLivenessSnapshot,
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
pub mod codegen_fn_attrs;
|
||||
pub mod dead_code;
|
||||
pub mod debugger_visualizer;
|
||||
pub mod deduced_param_attrs;
|
||||
pub mod dependency_format;
|
||||
|
||||
@@ -64,9 +64,7 @@
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::attrs::{EiiDecl, EiiImpl, StrippedCfgItem};
|
||||
use rustc_hir::def::{DefKind, DocLinkResMap};
|
||||
use rustc_hir::def_id::{
|
||||
CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId,
|
||||
};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdSet, LocalModDefId};
|
||||
use rustc_hir::lang_items::{LangItem, LanguageItems};
|
||||
use rustc_hir::{ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate};
|
||||
use rustc_index::IndexVec;
|
||||
@@ -87,6 +85,7 @@
|
||||
use crate::lint::LintExpectation;
|
||||
use crate::metadata::ModChild;
|
||||
use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs};
|
||||
use crate::middle::dead_code::DeadCodeLivenessSummary;
|
||||
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
|
||||
use crate::middle::deduced_param_attrs::DeducedParamAttrs;
|
||||
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
|
||||
@@ -1203,13 +1202,8 @@
|
||||
desc { "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) }
|
||||
}
|
||||
|
||||
/// Return the live symbols in the crate for dead code check.
|
||||
///
|
||||
/// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone).
|
||||
query live_symbols_and_ignored_derived_traits(_: ()) -> Result<&'tcx (
|
||||
LocalDefIdSet,
|
||||
LocalDefIdMap<FxIndexSet<DefId>>,
|
||||
), ErrorGuaranteed> {
|
||||
/// Return dead-code liveness summary for the crate.
|
||||
query live_symbols_and_ignored_derived_traits(_: ()) -> Result<&'tcx DeadCodeLivenessSummary, ErrorGuaranteed> {
|
||||
arena_cache
|
||||
desc { "finding live symbols in crate" }
|
||||
}
|
||||
|
||||
@@ -59,6 +59,10 @@ pub(crate) fn trivial_const<'a, 'tcx: 'a, F, B>(
|
||||
return None;
|
||||
}
|
||||
|
||||
if !tcx.opaque_types_defined_by(def).is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let body = body_provider();
|
||||
|
||||
if body.has_opaque_types() {
|
||||
|
||||
@@ -1526,6 +1526,15 @@ fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute, style: Option<
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if hir_id == CRATE_HIR_ID
|
||||
&& attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
|
||||
&& let Some(meta) = attr.meta_item_list()
|
||||
&& meta.iter().any(|meta| {
|
||||
meta.meta_item().is_some_and(|item| item.path == sym::dead_code_pub_in_binary)
|
||||
})
|
||||
&& !self.tcx.crate_types().contains(&CrateType::Executable)
|
||||
{
|
||||
errors::UnusedNote::NoEffectDeadCodePubInBinary
|
||||
} else if attr.has_name(sym::default_method_body_is_const) {
|
||||
errors::UnusedNote::DefaultMethodBodyConst
|
||||
} else {
|
||||
|
||||
@@ -13,18 +13,21 @@
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{self as hir, Node, PatKind, QPath, find_attr};
|
||||
use rustc_hir::{self as hir, ForeignItemId, ItemId, Node, PatKind, QPath, find_attr};
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::middle::dead_code::{DeadCodeLivenessSnapshot, DeadCodeLivenessSummary};
|
||||
use rustc_middle::middle::privacy::Level;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, AssocTag, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint::builtin::DEAD_CODE;
|
||||
use rustc_session::lint::{self, LintExpectationId};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_session::lint::builtin::{DEAD_CODE, DEAD_CODE_PUB_IN_BINARY};
|
||||
use rustc_session::lint::{self, Lint, LintExpectationId};
|
||||
use rustc_span::{Symbol, kw};
|
||||
|
||||
use crate::errors::{
|
||||
ChangeFields, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo, UselessAssignment,
|
||||
ChangeFields, DeadCodePubInBinaryNote, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo,
|
||||
UselessAssignment,
|
||||
};
|
||||
|
||||
/// Any local definition that may call something in its body block should be explored. For example,
|
||||
@@ -819,12 +822,12 @@ fn has_used_like_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||
fn maybe_record_as_seed<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
owner_id: hir::OwnerId,
|
||||
worklist: &mut Vec<WorkItem>,
|
||||
push_into_worklist: &mut impl FnMut(WorkItem),
|
||||
unsolved_items: &mut Vec<LocalDefId>,
|
||||
) {
|
||||
let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, owner_id.def_id);
|
||||
if let Some(comes_from_allow) = allow_dead_code {
|
||||
worklist.push(WorkItem {
|
||||
push_into_worklist(WorkItem {
|
||||
id: owner_id.def_id,
|
||||
propagated: comes_from_allow,
|
||||
own: comes_from_allow,
|
||||
@@ -835,11 +838,13 @@ fn maybe_record_as_seed<'tcx>(
|
||||
DefKind::Enum => {
|
||||
if let Some(comes_from_allow) = allow_dead_code {
|
||||
let adt = tcx.adt_def(owner_id);
|
||||
worklist.extend(adt.variants().iter().map(|variant| WorkItem {
|
||||
id: variant.def_id.expect_local(),
|
||||
propagated: comes_from_allow,
|
||||
own: comes_from_allow,
|
||||
}));
|
||||
for variant in adt.variants().iter() {
|
||||
push_into_worklist(WorkItem {
|
||||
id: variant.def_id.expect_local(),
|
||||
propagated: comes_from_allow,
|
||||
own: comes_from_allow,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
DefKind::AssocFn | DefKind::AssocConst { .. } | DefKind::AssocTy => {
|
||||
@@ -854,7 +859,7 @@ fn maybe_record_as_seed<'tcx>(
|
||||
&& let Some(comes_from_allow) =
|
||||
has_allow_dead_code_or_lang_attr(tcx, trait_item_local_def_id)
|
||||
{
|
||||
worklist.push(WorkItem {
|
||||
push_into_worklist(WorkItem {
|
||||
id: owner_id.def_id,
|
||||
propagated: comes_from_allow,
|
||||
own: comes_from_allow,
|
||||
@@ -879,7 +884,7 @@ fn maybe_record_as_seed<'tcx>(
|
||||
&& let Some(comes_from_allow) =
|
||||
has_allow_dead_code_or_lang_attr(tcx, trait_def_id)
|
||||
{
|
||||
worklist.push(WorkItem {
|
||||
push_into_worklist(WorkItem {
|
||||
id: owner_id.def_id,
|
||||
propagated: comes_from_allow,
|
||||
own: comes_from_allow,
|
||||
@@ -891,7 +896,7 @@ fn maybe_record_as_seed<'tcx>(
|
||||
}
|
||||
DefKind::GlobalAsm => {
|
||||
// global_asm! is always live.
|
||||
worklist.push(WorkItem {
|
||||
push_into_worklist(WorkItem {
|
||||
id: owner_id.def_id,
|
||||
propagated: ComesFromAllowExpect::No,
|
||||
own: ComesFromAllowExpect::No,
|
||||
@@ -902,7 +907,7 @@ fn maybe_record_as_seed<'tcx>(
|
||||
// `const _` is always live, as that syntax only exists for the side effects
|
||||
// of type checking and evaluating the constant expression, and marking them
|
||||
// as dead code would defeat that purpose.
|
||||
worklist.push(WorkItem {
|
||||
push_into_worklist(WorkItem {
|
||||
id: owner_id.def_id,
|
||||
propagated: ComesFromAllowExpect::No,
|
||||
own: ComesFromAllowExpect::No,
|
||||
@@ -913,41 +918,55 @@ fn maybe_record_as_seed<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
fn create_and_seed_worklist(tcx: TyCtxt<'_>) -> (Vec<WorkItem>, Vec<LocalDefId>) {
|
||||
let effective_visibilities = &tcx.effective_visibilities(());
|
||||
let mut unsolved_impl_item = Vec::new();
|
||||
let mut worklist = effective_visibilities
|
||||
.iter()
|
||||
.filter_map(|(&id, effective_vis)| {
|
||||
effective_vis.is_public_at_level(Level::Reachable).then_some(id).map(|id| WorkItem {
|
||||
id,
|
||||
propagated: ComesFromAllowExpect::No,
|
||||
own: ComesFromAllowExpect::No,
|
||||
})
|
||||
})
|
||||
// Seed entry point
|
||||
.chain(tcx.entry_fn(()).and_then(|(def_id, _)| {
|
||||
def_id.as_local().map(|id| WorkItem {
|
||||
id,
|
||||
propagated: ComesFromAllowExpect::No,
|
||||
own: ComesFromAllowExpect::No,
|
||||
})
|
||||
}))
|
||||
.collect::<Vec<_>>();
|
||||
struct SeedWorklists {
|
||||
worklist: Vec<WorkItem>,
|
||||
deferred_seeds: Vec<WorkItem>,
|
||||
unsolved_items: Vec<LocalDefId>,
|
||||
}
|
||||
|
||||
let crate_items = tcx.hir_crate_items(());
|
||||
for id in crate_items.owners() {
|
||||
maybe_record_as_seed(tcx, id, &mut worklist, &mut unsolved_impl_item);
|
||||
fn create_and_seed_worklist(tcx: TyCtxt<'_>) -> SeedWorklists {
|
||||
let mut unsolved_items = Vec::new();
|
||||
let mut deferred_seeds = Vec::new();
|
||||
let mut worklist = Vec::new();
|
||||
|
||||
if let Some((def_id, _)) = tcx.entry_fn(())
|
||||
&& let Some(local_def_id) = def_id.as_local()
|
||||
{
|
||||
worklist.push(WorkItem {
|
||||
id: local_def_id,
|
||||
propagated: ComesFromAllowExpect::No,
|
||||
own: ComesFromAllowExpect::No,
|
||||
});
|
||||
}
|
||||
|
||||
(worklist, unsolved_impl_item)
|
||||
for (id, effective_vis) in tcx.effective_visibilities(()).iter() {
|
||||
if effective_vis.is_public_at_level(Level::Reachable) {
|
||||
deferred_seeds.push(WorkItem {
|
||||
id: *id,
|
||||
propagated: ComesFromAllowExpect::No,
|
||||
own: ComesFromAllowExpect::No,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let mut push_into_worklist = |work_item: WorkItem| match work_item.own {
|
||||
ComesFromAllowExpect::Yes => deferred_seeds.push(work_item),
|
||||
ComesFromAllowExpect::No => worklist.push(work_item),
|
||||
};
|
||||
let crate_items = tcx.hir_crate_items(());
|
||||
for id in crate_items.owners() {
|
||||
maybe_record_as_seed(tcx, id, &mut push_into_worklist, &mut unsolved_items);
|
||||
}
|
||||
|
||||
SeedWorklists { worklist, deferred_seeds, unsolved_items }
|
||||
}
|
||||
|
||||
fn live_symbols_and_ignored_derived_traits(
|
||||
tcx: TyCtxt<'_>,
|
||||
(): (),
|
||||
) -> Result<(LocalDefIdSet, LocalDefIdMap<FxIndexSet<DefId>>), ErrorGuaranteed> {
|
||||
let (worklist, mut unsolved_items) = create_and_seed_worklist(tcx);
|
||||
) -> Result<DeadCodeLivenessSummary, ErrorGuaranteed> {
|
||||
let SeedWorklists { worklist, deferred_seeds, mut unsolved_items } =
|
||||
create_and_seed_worklist(tcx);
|
||||
let mut symbol_visitor = MarkSymbolVisitor {
|
||||
worklist,
|
||||
tcx,
|
||||
@@ -961,6 +980,28 @@ fn live_symbols_and_ignored_derived_traits(
|
||||
ignored_derived_traits: Default::default(),
|
||||
propagated_comes_from_allow_expect: ComesFromAllowExpect::No,
|
||||
};
|
||||
mark_live_symbols_and_ignored_derived_traits(&mut symbol_visitor, &mut unsolved_items)?;
|
||||
let pre_deferred_seeding = DeadCodeLivenessSnapshot {
|
||||
live_symbols: symbol_visitor.live_symbols.clone(),
|
||||
ignored_derived_traits: symbol_visitor.ignored_derived_traits.clone(),
|
||||
};
|
||||
|
||||
symbol_visitor.worklist.extend(deferred_seeds);
|
||||
mark_live_symbols_and_ignored_derived_traits(&mut symbol_visitor, &mut unsolved_items)?;
|
||||
|
||||
Ok(DeadCodeLivenessSummary {
|
||||
pre_deferred_seeding,
|
||||
final_result: DeadCodeLivenessSnapshot {
|
||||
live_symbols: symbol_visitor.live_symbols,
|
||||
ignored_derived_traits: symbol_visitor.ignored_derived_traits,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
fn mark_live_symbols_and_ignored_derived_traits(
|
||||
symbol_visitor: &mut MarkSymbolVisitor<'_>,
|
||||
unsolved_items: &mut Vec<LocalDefId>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if let ControlFlow::Break(guar) = symbol_visitor.mark_live_symbols() {
|
||||
return Err(guar);
|
||||
}
|
||||
@@ -988,7 +1029,7 @@ fn live_symbols_and_ignored_derived_traits(
|
||||
}));
|
||||
}
|
||||
|
||||
Ok((symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits))
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct DeadItem {
|
||||
@@ -999,6 +1040,7 @@ struct DeadItem {
|
||||
|
||||
struct DeadVisitor<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
target_lint: &'static Lint,
|
||||
live_symbols: &'tcx LocalDefIdSet,
|
||||
ignored_derived_traits: &'tcx LocalDefIdMap<FxIndexSet<DefId>>,
|
||||
}
|
||||
@@ -1042,10 +1084,14 @@ fn should_warn_about_field(&mut self, field: &ty::FieldDef) -> ShouldWarnAboutFi
|
||||
|
||||
fn def_lint_level(&self, id: LocalDefId) -> (lint::Level, Option<LintExpectationId>) {
|
||||
let hir_id = self.tcx.local_def_id_to_hir_id(id);
|
||||
let level = self.tcx.lint_level_at_node(DEAD_CODE, hir_id);
|
||||
let level = self.tcx.lint_level_at_node(self.target_lint, hir_id);
|
||||
(level.level, level.lint_id)
|
||||
}
|
||||
|
||||
fn dead_code_pub_in_binary_note(&self) -> Option<DeadCodePubInBinaryNote> {
|
||||
self.target_lint.name.eq(DEAD_CODE_PUB_IN_BINARY.name).then_some(DeadCodePubInBinaryNote)
|
||||
}
|
||||
|
||||
// # Panics
|
||||
// All `dead_codes` must have the same lint level, otherwise we will intentionally ICE.
|
||||
// This is because we emit a multi-spanned lint using the lint level of the `dead_codes`'s
|
||||
@@ -1157,6 +1203,7 @@ fn lint_at_single_level(
|
||||
descr,
|
||||
participle,
|
||||
name_list,
|
||||
dead_code_pub_in_binary_note: self.dead_code_pub_in_binary_note(),
|
||||
change_fields_suggestion: fields_suggestion,
|
||||
parent_info,
|
||||
ignored_derived_impls,
|
||||
@@ -1193,6 +1240,7 @@ fn lint_at_single_level(
|
||||
descr,
|
||||
participle,
|
||||
name_list,
|
||||
dead_code_pub_in_binary_note: self.dead_code_pub_in_binary_note(),
|
||||
parent_info,
|
||||
ignored_derived_impls,
|
||||
enum_variants_with_same_name,
|
||||
@@ -1201,7 +1249,7 @@ fn lint_at_single_level(
|
||||
};
|
||||
|
||||
let hir_id = tcx.local_def_id_to_hir_id(first_item.def_id);
|
||||
self.tcx.emit_node_span_lint(DEAD_CODE, hir_id, MultiSpan::from_spans(spans), diag);
|
||||
self.tcx.emit_node_span_lint(self.target_lint, hir_id, MultiSpan::from_spans(spans), diag);
|
||||
}
|
||||
|
||||
fn warn_multiple(
|
||||
@@ -1268,17 +1316,55 @@ fn is_live_code(&self, def_id: LocalDefId) -> bool {
|
||||
}
|
||||
|
||||
fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
|
||||
let Ok((live_symbols, ignored_derived_traits)) =
|
||||
let Ok(DeadCodeLivenessSummary { pre_deferred_seeding, final_result }) =
|
||||
tcx.live_symbols_and_ignored_derived_traits(()).as_ref()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits };
|
||||
|
||||
let module_items = tcx.hir_module_items(module);
|
||||
|
||||
for item in module_items.free_items() {
|
||||
if tcx.crate_types().contains(&CrateType::Executable) {
|
||||
let is_unused_pub = |def_id: LocalDefId| {
|
||||
tcx.effective_visibilities(()).is_public_at_level(def_id, Level::Reachable)
|
||||
&& !pre_deferred_seeding.live_symbols.contains(&def_id)
|
||||
};
|
||||
|
||||
lint_dead_codes(
|
||||
tcx,
|
||||
DEAD_CODE_PUB_IN_BINARY,
|
||||
module,
|
||||
&pre_deferred_seeding.live_symbols,
|
||||
&pre_deferred_seeding.ignored_derived_traits,
|
||||
module_items.free_items().filter(|free_item| is_unused_pub(free_item.owner_id.def_id)),
|
||||
module_items
|
||||
.foreign_items()
|
||||
.filter(|foreign_item| is_unused_pub(foreign_item.owner_id.def_id)),
|
||||
);
|
||||
}
|
||||
|
||||
lint_dead_codes(
|
||||
tcx,
|
||||
DEAD_CODE,
|
||||
module,
|
||||
&final_result.live_symbols,
|
||||
&final_result.ignored_derived_traits,
|
||||
module_items.free_items(),
|
||||
module_items.foreign_items(),
|
||||
);
|
||||
}
|
||||
|
||||
fn lint_dead_codes<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
target_lint: &'static Lint,
|
||||
module: LocalModDefId,
|
||||
live_symbols: &'tcx LocalDefIdSet,
|
||||
ignored_derived_traits: &'tcx LocalDefIdMap<FxIndexSet<DefId>>,
|
||||
free_items: impl Iterator<Item = ItemId>,
|
||||
foreign_items: impl Iterator<Item = ForeignItemId>,
|
||||
) {
|
||||
let mut visitor = DeadVisitor { tcx, target_lint, live_symbols, ignored_derived_traits };
|
||||
for item in free_items {
|
||||
let def_kind = tcx.def_kind(item.owner_id);
|
||||
|
||||
let mut dead_codes = Vec::new();
|
||||
@@ -1357,7 +1443,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
|
||||
}
|
||||
}
|
||||
|
||||
for foreign_item in module_items.foreign_items() {
|
||||
for foreign_item in foreign_items {
|
||||
visitor.check_definition(foreign_item.owner_id.def_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,6 +298,8 @@ pub(crate) enum UnusedNote {
|
||||
"the `linker_messages` and `linker_info` lints can only be controlled at the root of a crate that needs to be linked"
|
||||
)]
|
||||
LinkerMessagesBinaryCrateOnly,
|
||||
#[note("the `dead_code_pub_in_binary` lint has no effect in library crates")]
|
||||
NoEffectDeadCodePubInBinary,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@@ -920,6 +922,8 @@ pub(crate) enum MultipleDeadCodes<'tcx> {
|
||||
participle: &'tcx str,
|
||||
name_list: DiagSymbolList,
|
||||
#[subdiagnostic]
|
||||
dead_code_pub_in_binary_note: Option<DeadCodePubInBinaryNote>,
|
||||
#[subdiagnostic]
|
||||
// only on DeadCodes since it's never a problem for tuple struct fields
|
||||
enum_variants_with_same_name: Vec<EnumVariantSameName<'tcx>>,
|
||||
#[subdiagnostic]
|
||||
@@ -943,6 +947,8 @@ pub(crate) enum MultipleDeadCodes<'tcx> {
|
||||
participle: &'tcx str,
|
||||
name_list: DiagSymbolList,
|
||||
#[subdiagnostic]
|
||||
dead_code_pub_in_binary_note: Option<DeadCodePubInBinaryNote>,
|
||||
#[subdiagnostic]
|
||||
change_fields_suggestion: ChangeFields,
|
||||
#[subdiagnostic]
|
||||
parent_info: Option<ParentInfo<'tcx>>,
|
||||
@@ -951,6 +957,12 @@ pub(crate) enum MultipleDeadCodes<'tcx> {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[note(
|
||||
"in libraries, `pub` items can be used by dependent crates; in binaries, they cannot, so this `pub` item is unused"
|
||||
)]
|
||||
pub(crate) struct DeadCodePubInBinaryNote;
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[note(
|
||||
"it is impossible to refer to the {$dead_descr} `{$dead_name}` because it is shadowed by this enum variant with the same name"
|
||||
|
||||
@@ -753,6 +753,7 @@
|
||||
d32,
|
||||
dbg_macro,
|
||||
dead_code,
|
||||
dead_code_pub_in_binary,
|
||||
dealloc,
|
||||
debug,
|
||||
debug_assert_eq_macro,
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#![deny(dead_code)]
|
||||
#![deny(dead_code_pub_in_binary)]
|
||||
|
||||
pub fn g() {} //~ ERROR function `g` is never used
|
||||
|
||||
fn h() {}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn f() {
|
||||
g();
|
||||
h();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,15 @@
|
||||
error: function `g` is never used
|
||||
--> $DIR/allow-dead-code-transitive.rs:4:8
|
||||
|
|
||||
LL | pub fn g() {}
|
||||
| ^
|
||||
|
|
||||
= note: in libraries, `pub` items can be used by dependent crates; in binaries, they cannot, so this `pub` item is unused
|
||||
note: the lint level is defined here
|
||||
--> $DIR/allow-dead-code-transitive.rs:2:9
|
||||
|
|
||||
LL | #![deny(dead_code_pub_in_binary)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#![deny(dead_code)]
|
||||
#![allow(dead_code_pub_in_binary)]
|
||||
|
||||
pub fn unused_pub_fn() {
|
||||
helper();
|
||||
}
|
||||
|
||||
fn helper() {}
|
||||
|
||||
fn unused_priv_fn() {} //~ ERROR function `unused_priv_fn` is never used
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,14 @@
|
||||
error: function `unused_priv_fn` is never used
|
||||
--> $DIR/allow-lint.rs:10:4
|
||||
|
|
||||
LL | fn unused_priv_fn() {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/allow-lint.rs:1:9
|
||||
|
|
||||
LL | #![deny(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#![deny(dead_code)]
|
||||
#![deny(dead_code_pub_in_binary)]
|
||||
|
||||
pub fn unused_pub_fn() {} //~ ERROR function `unused_pub_fn` is never used
|
||||
|
||||
pub fn used_pub_fn() {}
|
||||
|
||||
fn unused_priv_fn() {} //~ ERROR function `unused_priv_fn` is never used
|
||||
|
||||
fn main() {
|
||||
used_pub_fn();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
error: function `unused_pub_fn` is never used
|
||||
--> $DIR/basic.rs:4:8
|
||||
|
|
||||
LL | pub fn unused_pub_fn() {}
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: in libraries, `pub` items can be used by dependent crates; in binaries, they cannot, so this `pub` item is unused
|
||||
note: the lint level is defined here
|
||||
--> $DIR/basic.rs:2:9
|
||||
|
|
||||
LL | #![deny(dead_code_pub_in_binary)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: function `unused_priv_fn` is never used
|
||||
--> $DIR/basic.rs:8:4
|
||||
|
|
||||
LL | fn unused_priv_fn() {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/basic.rs:1:9
|
||||
|
|
||||
LL | #![deny(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#![deny(dead_code_pub_in_binary)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub fn unused_pub_fn() {} //~ ERROR function `unused_pub_fn` is never used
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,15 @@
|
||||
error: function `unused_pub_fn` is never used
|
||||
--> $DIR/deny-lint.rs:4:8
|
||||
|
|
||||
LL | pub fn unused_pub_fn() {}
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: in libraries, `pub` items can be used by dependent crates; in binaries, they cannot, so this `pub` item is unused
|
||||
note: the lint level is defined here
|
||||
--> $DIR/deny-lint.rs:1:9
|
||||
|
|
||||
LL | #![deny(dead_code_pub_in_binary)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#![allow(dead_code)]
|
||||
#![deny(dead_code_pub_in_binary)]
|
||||
|
||||
pub fn unused_pub_fn() {} //~ ERROR function `unused_pub_fn` is never used
|
||||
fn unused_priv_fn() {}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,15 @@
|
||||
error: function `unused_pub_fn` is never used
|
||||
--> $DIR/interaction-allow-dead-code.rs:4:8
|
||||
|
|
||||
LL | pub fn unused_pub_fn() {}
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: in libraries, `pub` items can be used by dependent crates; in binaries, they cannot, so this `pub` item is unused
|
||||
note: the lint level is defined here
|
||||
--> $DIR/interaction-allow-dead-code.rs:2:9
|
||||
|
|
||||
LL | #![deny(dead_code_pub_in_binary)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#![allow(dead_code_pub_in_binary)]
|
||||
#![deny(dead_code)]
|
||||
|
||||
pub fn unused_pub_fn() {}
|
||||
fn unused_priv_fn() {} //~ ERROR function `unused_priv_fn` is never used
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,14 @@
|
||||
error: function `unused_priv_fn` is never used
|
||||
--> $DIR/interaction-allow-unused-pub.rs:5:4
|
||||
|
|
||||
LL | fn unused_priv_fn() {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/interaction-allow-unused-pub.rs:2:9
|
||||
|
|
||||
LL | #![deny(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
//@ check-pass
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
||||
pub fn unused_pub_fn() {}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,9 @@
|
||||
#![deny(dead_code)]
|
||||
#![deny(dead_code_pub_in_binary)]
|
||||
//~^ WARN unused attribute
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub fn unused_pub_fn() {} // Should NOT error because it's a library
|
||||
|
||||
fn unused_priv_fn() {} //~ ERROR function `unused_priv_fn` is never used
|
||||
@@ -0,0 +1,23 @@
|
||||
warning: unused attribute
|
||||
--> $DIR/library.rs:2:1
|
||||
|
|
||||
LL | #![deny(dead_code_pub_in_binary)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: the `dead_code_pub_in_binary` lint has no effect in library crates
|
||||
= note: requested on the command line with `-W unused-attributes`
|
||||
|
||||
error: function `unused_priv_fn` is never used
|
||||
--> $DIR/library.rs:9:4
|
||||
|
|
||||
LL | fn unused_priv_fn() {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/library.rs:1:9
|
||||
|
|
||||
LL | #![deny(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#![deny(dead_code)]
|
||||
#![deny(dead_code_pub_in_binary)]
|
||||
|
||||
#[no_mangle]
|
||||
pub fn pub_fn_no_mangle() {}
|
||||
|
||||
pub fn unused_pub_fn() {} //~ ERROR function `unused_pub_fn` is never used
|
||||
|
||||
#[no_mangle]
|
||||
pub fn unused_priv_fn_no_mangle() {}
|
||||
|
||||
fn unused_priv_fn() {} //~ ERROR function `unused_priv_fn` is never used
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,27 @@
|
||||
error: function `unused_pub_fn` is never used
|
||||
--> $DIR/no-mangle-items.rs:7:8
|
||||
|
|
||||
LL | pub fn unused_pub_fn() {}
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: in libraries, `pub` items can be used by dependent crates; in binaries, they cannot, so this `pub` item is unused
|
||||
note: the lint level is defined here
|
||||
--> $DIR/no-mangle-items.rs:2:9
|
||||
|
|
||||
LL | #![deny(dead_code_pub_in_binary)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: function `unused_priv_fn` is never used
|
||||
--> $DIR/no-mangle-items.rs:12:4
|
||||
|
|
||||
LL | fn unused_priv_fn() {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/no-mangle-items.rs:1:9
|
||||
|
|
||||
LL | #![deny(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
trait Trait2: Sized {}
|
||||
|
||||
impl Trait2 for () {
|
||||
const FOO: () = {
|
||||
//~^ ERROR const `FOO` is not a member of trait `Trait2`
|
||||
//~^^ ERROR item does not constrain `Assoc::{opaque#0}`
|
||||
type Assoc = impl Copy; //~ ERROR `impl Trait` in type aliases is unstable
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,37 @@
|
||||
error[E0438]: const `FOO` is not a member of trait `Trait2`
|
||||
--> $DIR/trivial-const-ice-149278.rs:4:5
|
||||
|
|
||||
LL | / const FOO: () = {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | type Assoc = impl Copy;
|
||||
LL | | };
|
||||
| |______^ not a member of trait `Trait2`
|
||||
|
||||
error[E0658]: `impl Trait` in type aliases is unstable
|
||||
--> $DIR/trivial-const-ice-149278.rs:7:22
|
||||
|
|
||||
LL | type Assoc = impl Copy;
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
|
||||
= help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: item does not constrain `Assoc::{opaque#0}`
|
||||
--> $DIR/trivial-const-ice-149278.rs:4:11
|
||||
|
|
||||
LL | const FOO: () = {
|
||||
| ^^^
|
||||
|
|
||||
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
|
||||
note: this opaque type is supposed to be constrained
|
||||
--> $DIR/trivial-const-ice-149278.rs:7:22
|
||||
|
|
||||
LL | type Assoc = impl Copy;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0438, E0658.
|
||||
For more information about an error, try `rustc --explain E0438`.
|
||||
@@ -0,0 +1,15 @@
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type Tait = impl Sized;
|
||||
|
||||
#[define_opaque(Tait)]
|
||||
const FOO: Tait = 1;
|
||||
|
||||
fn main() {
|
||||
let _: Tait = FOO;
|
||||
}
|
||||
Reference in New Issue
Block a user