Skip to content

Dead code lint emits unused code warning for code that is clearly used. #39034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
quadrupleslap opened this issue Jan 13, 2017 · 2 comments
Open
Labels
A-lints Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug. L-dead_code Lint: dead_code T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@quadrupleslap
Copy link

It looks like the dead code lint is too eager, and doesn't consider two signs that the variants are used:

  • The enum is passed to an extern function, which could do just about anything to the data.
  • The variants are used, in the match statement!

Playground

use helpers::Animal;

#[forbid(dead_code)]
mod helpers {
    #[repr(u32)]
    pub enum Animal {
        Cat = 0,
        Dog = 1,
        Frog = 2
    }

    extern "C" {
        pub fn transmute_the_animal(animal: &mut Animal);
    }
}

fn main() {
    let mut animal = Animal::Cat;

    unsafe {
        helpers::transmute_the_animal(&mut animal);
    }

    match animal {
        Animal::Cat => println!("My cat didn't change! :("),
        Animal::Dog => println!("Yay. my cat became a dog!"),
        Animal::Frog => println!("Eww, my cat turned into a frog!")
    }
}

Expected: A clean build (I think.)

What I got:

rustc 1.16.0-nightly (2782e8f8f 2017-01-12)
error: variant is never used: `Dog`
  --> <anon>:13:9
   |
13 |         Dog = 1,
   |         ^^^^^^^
   |
note: lint level defined here
  --> <anon>:3:10
   |
3  | #[forbid(dead_code)]
   |          ^^^^^^^^^

error: variant is never used: `Frog`
  --> <anon>:14:9
   |
14 |         Frog = 2
   |         ^^^^^^^^

error: aborting due to 2 previous errors
@Mark-Simulacrum
Copy link
Member

I think the underlying problem here is that we continue to reason about the enum variant after passing to external code (e.g., C code).

@sfackler sfackler added the A-diagnostics Area: Messages for errors, warnings, and lints label Jan 14, 2017
@steveklabnik steveklabnik added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 9, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 26, 2017
@molenzwiebel
Copy link

molenzwiebel commented Aug 3, 2020

Hey there! I've been wanting to get my feet wet with rustc, figured I'd start to see if I can fix this issue.

From what I can see, there's several options that would mitigate this issue:

  • Mark all variants of a mutable reference to an enum passed to foreign functions as constructed while visiting the foreign def. This would work, but extra care would need to be taken to ensure that this only happens if the actual def is called from user code (otherwise we're flagging the enum as used even though the only function using it is not called). Since we cannot rely on the visit order to see whether the foreign def is live, this would require an extra data structure keeping track of the variant <-> foreign def relations.
  • Mark all variants of a mutable reference to an enum passed to foreign functions as constructed while visiting the call to the foreign def. This would work and mitigate the issues in the previous option, but it sounds like a bit of a spaghetti special case where the cost of the implementation may not warrant the admittedly slim benefits. Additionally this would only work in cases where we could statically determine the call target to be the foreign function.
  • Mark variants used as (match) patterns as constructed. This does not fix this actual issue, but its an easier compromise that requires very little code changes and would be beneficial even outside of this example. Doing so would still mark variants as unconstructed that may potentially appear during runtime, but it would correctly notice cases where the user does handle a value of a specific type, but doesn't construct it.

For the last option, this'd mean the following:

use helpers::Animal;

#[forbid(dead_code)]
mod helpers {
    #[repr(u32)]
    pub enum Animal {
        Cat = 0, // Used: constructed
        Dog = 1, // Used: as pattern
        Frog = 2 // Error: variant is never used
    }
}

fn main() {
    let animal = Animal::Cat;

    match animal {
		Animal::Dog => println!("Woof!"),
		_ => println!("Something else.")
	}
}

For the last option, we would additionally need to figure out whether we want this to apply to just enums or also ADTs with associated data.

Edit: The last option would also solve #56750.

@jieyouxu jieyouxu added L-dead_code Lint: dead_code A-lints Area: Lints (warnings about flaws in source code) such as unused_mut. and removed A-diagnostics Area: Messages for errors, warnings, and lints labels Mar 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lints Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug. L-dead_code Lint: dead_code T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants