Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ declare_lint_pass! {
UNUSED_MACROS,
UNUSED_MACRO_RULES,
UNUSED_MUT,
UNUSED_PUB_ITEMS_IN_BINARY,
UNUSED_QUALIFICATIONS,
UNUSED_UNSAFE,
UNUSED_VARIABLES,
Expand Down Expand Up @@ -782,6 +783,37 @@ declare_lint! {
"detect unused, unexported items"
}

declare_lint! {
/// The `unused_pub_items_in_binary` lint detects unused `pub` items in
/// executable crates.
///
/// ### Example
///
/// ```rust
/// #![deny(unused_pub_items_in_binary)]
Comment thread
mu001999 marked this conversation as resolved.
///
/// 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 UNUSED_PUB_ITEMS_IN_BINARY,
Copy link
Copy Markdown
Contributor

@traviscross traviscross Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub UNUSED_PUB_ITEMS_IN_BINARY,
pub UNUSED_PUB_IN_BINARY,

In keeping with the RFC 0344 guidance, I might call this unused_pub_in_binary.

  • Lints that apply to arbitrary items (like the stability lints) should just mention what they check for: use deprecated rather than deprecated_items. This keeps lint names short. (Again, think "allow lint-name items".)

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming this is something like “dead_code but marking pub doesn’t count as usage”, I wonder if the name should be related to the name of the dead_code lint, like… public_dead_code_in_binary or something 🤔

Copy link
Copy Markdown

@GrantGryczan GrantGryczan Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name "unused pub" makes me think the pub keyword is unused, not the item it's on.

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.
Expand Down
23 changes: 23 additions & 0 deletions compiler/rustc_middle/src/middle/dead_code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir::def_id::{DefId, LocalDefIdMap, LocalDefIdSet};
use rustc_macros::HashStable;

/// A single snapshot of dead-code liveness analysis state.
#[derive(Clone, Debug, HashStable)]
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 `unused_pub_items_in_binary`.
/// `final_result` is the final liveness snapshot used for lint `dead_code`.
#[derive(Clone, Debug, HashStable)]
pub struct DeadCodeLivenessSummary {
pub pre_deferred_seeding: DeadCodeLivenessSnapshot,
pub final_result: DeadCodeLivenessSnapshot,
}
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/middle/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
14 changes: 4 additions & 10 deletions compiler/rustc_middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ use rustc_errors::{ErrorGuaranteed, catch_fatal_errors};
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;
Expand All @@ -87,6 +85,7 @@ use crate::infer::canonical::{self, Canonical};
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};
Expand Down Expand Up @@ -1199,13 +1198,8 @@ rustc_queries! {
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" }
}
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1682,6 +1682,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
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::unused_pub_items_in_binary)
})
&& !self.tcx.crate_types().contains(&CrateType::Executable)
{
errors::UnusedNote::NoEffectUnusedPubItemsInBinary
} else if attr.has_name(sym::default_method_body_is_const) {
errors::UnusedNote::DefaultMethodBodyConst
} else {
Expand Down
Loading
Loading