Skip to content

Dead code refactor - #164913

Draft
tehforsch wants to merge 2 commits into
rust-lang:mainfrom
tehforsch:dead-code-refactor
Draft

tehforsch wants to merge 2 commits into
rust-lang:mainfrom
tehforsch:dead-code-refactor

Conversation

@tehforsch

@tehforsch tehforsch commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

While working on #164217, I noticed a lot of complex interactions between allow(dead_code)/expect(dead_code), dead_code_pub_in_binary and the newly introduced trivial usages. In particular, the logic for deciding when to explore an impl item based on the lint level and liveness of its trait and type became very complicated.

This is an attempt to reduce the whole problem to a simpler structure in which the exact rules become a bit clearer.

This introduces is a Liveness type which defines whether we currently consider an item "live" because it is 1. used from a live seed, such as main, 2. publically reachable 3. at allow/expect lint level:

pub enum Liveness {
    AllowExpect,
    Public,
    Live,
}

This introduces a strict hierarchy. When an item is used in main, we don't care anymore if it is also public in the binary. If a type is public, we don't care if it is also annotated with #[allow(dead_code)] (we do care for expect, but we can defer handling that to the actual lint emission).

The live symbols map then effectively becomes LocalDefIdMap<Liveness> with "monotonically increasing" entries, i.e. we never change an entry from Live to Public, for example.

Doing so has a few implications:

  1. WorkItem now gets rid of own and propagated ComesFromAllowExpect status. Instead it carries only a Liveness.
  2. Deferred seeding can be completely removed. The whole code structure changes to
    1. Seed work items and unsolved impl items with their maximally known Liveness.
    2. Visit all work items / unsolved items until we can't make progress.
    3. Emit lints
  3. The scanned map is removed entirely. We only insert new work items if the new Liveness is greater than the already known one for that item.
  4. The complex trait resolution logic is now a local decision (see get_impl_or_impl_item_liveness). The rules and edge cases are explicit and contained in a single function.

This PR is purely refactoring. Allowing #[rustc_trivial_field_reads] annotations can then be done in a separate PR, but is a lot simpler now since its mainly a matter of introducing a Liveness level below AllowExpect and tracing the usage sites properly.

There is a difference in behavior between main and this PR:

#![deny(unfulfilled_lint_expectations)]

trait Trait {
    fn method();
}

struct S;

impl Trait for S {
    #[expect(dead_code)]
    fn method() {
        helper();
    }
}

#[expect(dead_code)]
fn helper() {}

fn call<T: Trait>() {
    T::method();
}

fn main() {
    call::<S>();
}

On main, only the unfulfilled expect for method() is reported, whereas this branch reports both. I wasn't sure whether this is a regression or a bugfix, so I haven't fixed this yet

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 25, 2026
@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job test-pr-check-2 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)

@mu001999

Copy link
Copy Markdown
Member

On main, only the unfulfilled expect for method() is reported, whereas this branch reports both. I wasn't sure whether this is a regression or a bugfix, so I haven't fixed this yet

I think this is a bugfix :)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants