Skip to content
Draft
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
33 changes: 18 additions & 15 deletions compiler/rustc_passes/src/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ 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::config::CrateType;
use rustc_session::lint::builtin::DEAD_CODE;
use rustc_session::lint::{self, LintExpectationId};
use rustc_span::{Symbol, kw, sym};
Expand Down Expand Up @@ -813,22 +814,24 @@ fn maybe_record_as_seed<'tcx>(
fn create_and_seed_worklist(
tcx: TyCtxt<'_>,
) -> (Vec<(LocalDefId, ComesFromAllowExpect)>, 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| (id, ComesFromAllowExpect::No))
})
// Seed entry point
.chain(
tcx.entry_fn(())
.and_then(|(def_id, _)| def_id.as_local().map(|id| (id, ComesFromAllowExpect::No))),
)
.collect::<Vec<_>>();
let mut worklist = Vec::new();

if let Some((def_id, _)) = tcx.entry_fn(())
&& let Some(local_def_id) = def_id.as_local()
{
worklist.push((local_def_id, ComesFromAllowExpect::No));
}

if !tcx.sess.opts.unstable_opts.treat_pub_as_pub_crate
|| !tcx.crate_types().contains(&CrateType::Executable)
{
for (id, effective_vis) in tcx.effective_visibilities(()).iter() {
if effective_vis.is_public_at_level(Level::Reachable) {
worklist.push((*id, ComesFromAllowExpect::No));
}
}
}

let crate_items = tcx.hir_crate_items(());
for id in crate_items.owners() {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2727,6 +2727,8 @@ written to standard error output)"),
treat_err_as_bug: Option<NonZero<usize>> = (None, parse_treat_err_as_bug, [TRACKED],
"treat the `val`th error that occurs as bug (default if not specified: 0 - don't treat errors as bugs. \
default if specified without a value: 1 - treat the first error as bug)"),
treat_pub_as_pub_crate: bool = (false, parse_bool, [UNTRACKED],
"treat `pub` items as `pub(crate)` items for binary crates (default: no)"),
trim_diagnostic_paths: bool = (true, parse_bool, [UNTRACKED],
"in diagnostics, use heuristics to shorten paths referring to items"),
tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
Expand Down
31 changes: 31 additions & 0 deletions src/doc/unstable-book/src/compiler-flags/treat-pub-as-pub-crate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# `treat-pub-as-pub-crate`

The `-Ztreat-pub-as-pub-crate` flag causes the compiler to treat all `pub` items in the crate as if they were `pub(crate)`. This is useful for finding dead code in binary crates where public items are not intended to be exported to other crates.

When this flag is enabled, the dead code lint will warn about public items that are not used within the crate (unless they are the entry point, like `main`).

## Example

Consider the following code in a binary crate:

```rust
pub fn unused_pub_fn() {}

fn main() {
println!("Hello, world!");
}
```

By default, `rustc` assumes that `unused_pub_fn` might be used by other crates linking to this binary, so it does not warn about it being unused.

With `-Ztreat-pub-as-pub-crate`, `rustc` will emit a warning:

```text
warning: function `unused_pub_fn` is never used
--> src/main.rs:1:8
|
1 | pub fn unused_pub_fn() {}
| ^^^^^^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
```
8 changes: 8 additions & 0 deletions tests/ui/lint/dead-code/treat-pub-as-pub-crate-lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//@ compile-flags: -Ztreat-pub-as-pub-crate
#![feature(rustc_attrs)]
#![deny(dead_code)]
#![crate_type = "lib"]

pub fn unused_pub_fn() {} // Should NOT error because it's a library crate

fn unused_priv_fn() {} //~ ERROR function `unused_priv_fn` is never used
14 changes: 14 additions & 0 deletions tests/ui/lint/dead-code/treat-pub-as-pub-crate-lib.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: function `unused_priv_fn` is never used
--> $DIR/treat-pub-as-pub-crate-lib.rs:8:4
|
LL | fn unused_priv_fn() {}
| ^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/treat-pub-as-pub-crate-lib.rs:3:9
|
LL | #![deny(dead_code)]
| ^^^^^^^^^

error: aborting due to 1 previous error

11 changes: 11 additions & 0 deletions tests/ui/lint/dead-code/treat-pub-as-pub-crate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//@ compile-flags: -Ztreat-pub-as-pub-crate
#![feature(rustc_attrs)]
#![deny(dead_code)]

pub fn unused_pub_fn() {} //~ ERROR function `unused_pub_fn` is never used

pub fn used_pub_fn() {}

fn main() {
used_pub_fn();
}
14 changes: 14 additions & 0 deletions tests/ui/lint/dead-code/treat-pub-as-pub-crate.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: function `unused_pub_fn` is never used
--> $DIR/treat-pub-as-pub-crate.rs:5:8
|
LL | pub fn unused_pub_fn() {}
| ^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/treat-pub-as-pub-crate.rs:3:9
|
LL | #![deny(dead_code)]
| ^^^^^^^^^

error: aborting due to 1 previous error

Loading