Skip to content

Most dead code warnings don't work inside const _ #101532

@RReverser

Description

@RReverser

Given the following code:

const _: () = {
    let a: ();

    struct B {}

    enum C {}

    fn d() {}

    const E: () = {};
};

The current output is:

warning: unused variable: `a`
 --> <source>:2:9
  |
2 |     let a: ();
  |         ^ help: if this is intentional, prefix it with an underscore: `_a`
  |
  = note: `#[warn(unused_variables)]` on by default

Ideally the output should look like:

warning: unused variable: `a`
 --> <source>:2:9
  |
2 |     let a: ();
  |         ^ help: if this is intentional, prefix it with an underscore: `_a`
  |
  = note: `#[warn(unused_variables)]` on by default

warning: struct `B` is never constructed
 --> <source>:4:12
  |
4 |     struct B {}
  |            ^
  |
  = note: `#[warn(dead_code)]` on by default

warning: enum `C` is never used
 --> <source>:6:10
  |
6 |     enum C {}
  |          ^

warning: function `d` is never used
 --> <source>:8:8
  |
8 |     fn d() {}
  |        ^

warning: constant `E` is never used
  --> <source>:10:5
   |
10 |     const E: () = {};
   |     ^^^^^^^^^^^^^^^^^

warning: 5 warnings emitted

What's surprising is that adding pub changes the output to the expected one, even though pub doesn't make any meaning on const _: ():

pub const _: () = {
    let a: ();

    struct B {}

    enum C {}

    fn d() {}

    const E: () = {};
};

It's also interesting that the logic matches what happens with functions. For example, in:

fn foo() {
    let a: ();

    struct B {}

    enum C {}

    fn d() {}

    const E: () = {};
}

the function foo itself and also only the variable a are reported as unused, while the rest of the items don't get a warning:

warning: unused variable: `a`
 --> <source>:2:9
  |
2 |     let a: ();
  |         ^ help: if this is intentional, prefix it with an underscore: `_a`
  |
  = note: `#[warn(unused_variables)]` on by default

warning: function `foo` is never used
 --> <source>:1:4
  |
1 | fn foo() {
  |    ^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: 2 warnings emitted

However, once foo is made public, all the items get warnings:

warning: unused variable: `a`
 --> <source>:2:9
  |
2 |     let a: ();
  |         ^ help: if this is intentional, prefix it with an underscore: `_a`
  |
  = note: `#[warn(unused_variables)]` on by default

warning: struct `B` is never constructed
 --> <source>:4:12
  |
4 |     struct B {}
  |            ^
  |
  = note: `#[warn(dead_code)]` on by default

warning: enum `C` is never used
 --> <source>:6:10
  |
6 |     enum C {}
  |          ^

warning: function `d` is never used
 --> <source>:8:8
  |
8 |     fn d() {}
  |        ^

warning: constant `E` is never used
  --> <source>:10:5
   |
10 |     const E: () = {};
   |     ^^^^^^^^^^^^^^^^^

warning: 5 warnings emitted

Either way, const _ should have different treatment due to being anonymous, but it's still a bit surprising that only let variables get inside both const _ and fn foo.

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsA-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.E-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.L-dead_codeLint: dead_codeL-false-negativeLint: False negative (should have fired but didn't).L-unused_variablesLint: unused_variablesT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions