Skip to content

Commit 0e5924a

Browse files
committed
Auto merge of #149509 - mu001999-contrib:flag/pub-as-pub-crate, r=jdonszelmann
Lint unused pub items in binary crates ~~This PR adds a new unstable flag -Ztreat-pub-as-pub-crate as [@Kobzol](https://github.com/Kobzol) suggested.~~ ~~When compiling binary crates with this flag, the seed worklist will only contain the entry fn and won't contain other reachable items. Then we can do the dead code analysis for pub items just like they are pub(crate).~~ Related zulip thread [#general > pub/pub(crate) within a binary is a footgun](https://rust-lang.zulipchat.com/#narrow/channel/122651-general/topic/pub.2Fpub.28crate.29.20within.20a.20binary.20is.20a.20footgun/with/558931034). --- Updated: Adds a new lint `unused_pub_items_in_binary` (crate-level, default allow for now) instead of the previous unstable flag to lint unused `pub` items for binary crates. See more details of implementation in #149509 (comment). This lint is allowed by default, but I believe this has been better than the unstable flag. Making it warn-by-default will lead to a lot of noise for this PR (like bless many tests). So I'd like to make it warn-by-default in a separate PR in the future.
2 parents 4ddd453 + 26bfcf3 commit 0e5924a

25 files changed

Lines changed: 452 additions & 56 deletions

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ declare_lint_pass! {
3434
CONST_EVALUATABLE_UNCHECKED,
3535
CONST_ITEM_MUTATION,
3636
DEAD_CODE,
37+
DEAD_CODE_PUB_IN_BINARY,
3738
DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
3839
DEPRECATED,
3940
DEPRECATED_IN_FUTURE,
@@ -789,6 +790,37 @@ declare_lint! {
789790
"detect unused, unexported items"
790791
}
791792

793+
declare_lint! {
794+
/// The `dead_code_pub_in_binary` lint detects unused `pub` items in
795+
/// executable crates.
796+
///
797+
/// ### Example
798+
///
799+
/// ```rust
800+
/// #![deny(dead_code_pub_in_binary)]
801+
///
802+
/// pub fn unused_pub_fn() {}
803+
///
804+
/// fn main() {}
805+
/// ```
806+
///
807+
/// {{produces}}
808+
///
809+
/// ### Explanation
810+
///
811+
/// In executable crates, `pub` items are often implementation details
812+
/// rather than part of an external API. This lint helps find those items
813+
/// when they are never used.
814+
///
815+
/// This lint only applies to executable crates. In library crates, public
816+
/// items are considered part of the crate's API and are not reported by
817+
/// this lint.
818+
pub DEAD_CODE_PUB_IN_BINARY,
819+
Allow,
820+
"detect public items in executable crates that are never used",
821+
crate_level_only
822+
}
823+
792824
declare_lint! {
793825
/// The `unused_attributes` lint detects attributes that were not used by
794826
/// the compiler.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use rustc_data_structures::fx::FxIndexSet;
2+
use rustc_hir::def_id::{DefId, LocalDefIdMap, LocalDefIdSet};
3+
use rustc_macros::StableHash;
4+
5+
/// A single snapshot of dead-code liveness analysis state.
6+
#[derive(Clone, Debug, StableHash)]
7+
pub struct DeadCodeLivenessSnapshot {
8+
pub live_symbols: LocalDefIdSet,
9+
/// Maps each ADT to derived traits (for example `Debug` and `Clone`) that should be ignored
10+
/// when checking for dead code diagnostics.
11+
pub ignored_derived_traits: LocalDefIdMap<FxIndexSet<DefId>>,
12+
}
13+
14+
/// Dead-code liveness data for both analysis phases.
15+
///
16+
/// `pre_deferred_seeding` is computed before reachable-public and `#[allow(dead_code)]` seeding,
17+
/// and is used for lint `dead_code_pub_in_binary`.
18+
/// `final_result` is the final liveness snapshot used for lint `dead_code`.
19+
#[derive(Clone, Debug, StableHash)]
20+
pub struct DeadCodeLivenessSummary {
21+
pub pre_deferred_seeding: DeadCodeLivenessSnapshot,
22+
pub final_result: DeadCodeLivenessSnapshot,
23+
}

compiler/rustc_middle/src/middle/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod codegen_fn_attrs;
2+
pub mod dead_code;
23
pub mod debugger_visualizer;
34
pub mod deduced_param_attrs;
45
pub mod dependency_format;

compiler/rustc_middle/src/queries.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,7 @@ use rustc_errors::{ErrorGuaranteed, catch_fatal_errors};
6464
use rustc_hir as hir;
6565
use rustc_hir::attrs::{EiiDecl, EiiImpl, StrippedCfgItem};
6666
use rustc_hir::def::{DefKind, DocLinkResMap};
67-
use rustc_hir::def_id::{
68-
CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId,
69-
};
67+
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdSet, LocalModDefId};
7068
use rustc_hir::lang_items::{LangItem, LanguageItems};
7169
use rustc_hir::{ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate};
7270
use rustc_index::IndexVec;
@@ -87,6 +85,7 @@ use crate::infer::canonical::{self, Canonical};
8785
use crate::lint::LintExpectation;
8886
use crate::metadata::ModChild;
8987
use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs};
88+
use crate::middle::dead_code::DeadCodeLivenessSummary;
9089
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
9190
use crate::middle::deduced_param_attrs::DeducedParamAttrs;
9291
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
@@ -1203,13 +1202,8 @@ rustc_queries! {
12031202
desc { "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) }
12041203
}
12051204

1206-
/// Return the live symbols in the crate for dead code check.
1207-
///
1208-
/// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone).
1209-
query live_symbols_and_ignored_derived_traits(_: ()) -> Result<&'tcx (
1210-
LocalDefIdSet,
1211-
LocalDefIdMap<FxIndexSet<DefId>>,
1212-
), ErrorGuaranteed> {
1205+
/// Return dead-code liveness summary for the crate.
1206+
query live_symbols_and_ignored_derived_traits(_: ()) -> Result<&'tcx DeadCodeLivenessSummary, ErrorGuaranteed> {
12131207
arena_cache
12141208
desc { "finding live symbols in crate" }
12151209
}

compiler/rustc_passes/src/check_attr.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,6 +1526,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
15261526
return;
15271527
}
15281528
}
1529+
} else if hir_id == CRATE_HIR_ID
1530+
&& attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
1531+
&& let Some(meta) = attr.meta_item_list()
1532+
&& meta.iter().any(|meta| {
1533+
meta.meta_item().is_some_and(|item| item.path == sym::dead_code_pub_in_binary)
1534+
})
1535+
&& !self.tcx.crate_types().contains(&CrateType::Executable)
1536+
{
1537+
errors::UnusedNote::NoEffectDeadCodePubInBinary
15291538
} else if attr.has_name(sym::default_method_body_is_const) {
15301539
errors::UnusedNote::DefaultMethodBodyConst
15311540
} else {

0 commit comments

Comments
 (0)