Incorrect warning about unused const

e4c5be8
Opened by robz at 2024-12-21 04:50:13

In the following program:

const SIZE: usize = 4;

fn _f(arr: [i32; SIZE]) {
    for x in arr.iter() {
      println!("{}", x);
    }
}

fn main() {}

I get a warning about SIZE being unused:

warning: constant item is never used: `SIZE`
 --> src/main.rs:1:1
  |
1 | const SIZE: usize = 4;
  | ^^^^^^^^^^^^^^^^^^^^^^
  |

It seems to me that this warning isn't correct, since SIZE is used in the signature of _f

  1. This is because _f is not used; the unused lint applies transitively.

    The most I've managed to dig up thus far on the reasoning behind this is this ancient post.

    Michael Lamparski at 2018-01-02 18:12:53

  2. Interesting, thanks for the background! I can see how the behavior here is consistent with the reasoning there, but I don't think the decision on that was the right one. Warnings like these have to be ignored, which reduces the signal/noise ratio of warnings in general.

    robz at 2018-01-02 19:09:04

  3. Maybe an unused lint should have a note pointing to the "use site" in order to reduce said confusion

    Oli Scherer at 2018-01-03 09:41:38

  4. Edit (2019-10-16): I now firmly believe that the current design is inferior in all use cases, and have yet to see any description of a viable workflow for the use case of deleting all dead code given the current design.


    I very much agree with @robz's sentiment. IMO, there are two use cases that an "unused" lint can be optimized for:

    • The case where the correct resolution is to outright delete the code. This is the existing lint, though I'd rather call it a lint on unnecessary code rather than "unused" code. It indicates everything that is unnecessary all at once so that it can all be torn out in one fell swoop, which is useful for cleaning up code after e.g. replacing a dependency.

    • The case where the correct resolution is to consider using the code (that is, you either need to add a use or silence the warning... or perhaps you're missing a pub or #[cfg(test)] or etc.). Each linted item is something independent that can be removed from the source code without any impact on compilation. I'll call this the truly unused lint.

    Go figure, the latter always seems to be the one I actually need, but that might just be cognitive bias due to the "grass is greener" effect. Basically, it helps catch various classes of mistakes that otherwise elude the type system.


    If we're stuck with having a single one of these two lints, then we have different issues:

    • When trying to use the "unnecessary" lint to locate code that is truly unused, the issue is noise. Basically, the useful warnings are overwhelmed by many useless ones. I feel that @oli-obk's suggestion unfortunately would only help marginally here, by making the useless ones easier to spot. (Too bad it does this by making them occupy more space, when they are already greater in number!)

    • When trying to use a "truly unused" lint to prune unnecessary code, the issue is that it's slow. Finding all of the unnecessary code may take many recompilation cycles as you slowly remove things as they are revealed.

    Michael Lamparski at 2018-01-03 13:26:56

  5. Strawman idea:

    #![allow(unused)]        // disable all unused warnings...
    #![warn(truly_unused)]   // ...then reenable warnings for a subset of them
    

    Michael Lamparski at 2018-01-03 13:36:51

  6. We could collect all unused things in a graph and report it starting with the items that have no incoming edges ( truly unused)

    That way the important things show up first

    Oli Scherer at 2018-01-03 14:05:34

  7. Triage: the error message is the same today, and I'm not aware of anyone working on the "point to the 'use' site" idea either.

    Steve Klabnik at 2019-09-16 13:29:53

  8. There is already another issue open on this: https://github.com/rust-lang/rust/issues/39531

    Tom Kaitchuck at 2019-10-15 22:32:50

  9. I have the same problem when the crate have lib that define pub type and function ( actually extern "stdcall" pub fn ) and a bin that use the lib in the same crate. #[test] in the lib do not complains, but binary complains about all imports that is not used type alias is never used, associated const is never used and foreign function is never used.

    JLalu at 2019-10-24 10:21:44

  10. Hello writing from 2020. Update: Test usage of a function that contains const item can't pass the lint IFOF function isn't also used in lib.

    Theo M. Bulut at 2020-04-07 08:42:46

  11. Can you show an example? Normally problems like that can be solved by making the function #[cfg(test)].

    Michael Lamparski at 2020-04-08 04:02:02