Skip to content

Item used in (unused) item named _name is still deemed dead #142075

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
DoubleHyphen opened this issue Jun 5, 2025 · 5 comments
Open

Item used in (unused) item named _name is still deemed dead #142075

DoubleHyphen opened this issue Jun 5, 2025 · 5 comments
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 L-false-positive Lint: False positive (should not have fired). T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@DoubleHyphen
Copy link

Code

const _MY_CODE_IS_CORRECT: bool = true;

const fn sanity_check() {
    let true = _MY_CODE_IS_CORRECT else {
        panic!();
    };
}

const _SANITY_CHECK: () = sanity_check();

Current output

warning: function `sanity_check` is never used
 --> src/lib.rs:3:10
  |
3 | const fn sanity_check() {
  |          ^^^^^^^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default

Desired output

Compiling with no warnings.

Rationale and extra context

I have created some modules. I want each of them to fail to compile if it is not correct. To that end, I instituted a sanity_check in the crate, which is called within each module as const _SANITY_CHECK: () = crate::sanity_check();

The problem is that, because the _SANITY_CHECK consts are obviously not used anywhere, the entire sanity_check function is considered unused too. As one can tell, it is in fact very much used, and serves a very important purpose.

I guess this could be worked around by renaming it to _sanity_check, but in this case leaving the function actually unused would return no warnings, which is less than ideal.

Other cases

Rust Version

I tried it in the play-ground. I tried to find the version there but failed—that said, it's always the most recent one, isn't it?

Anything else?

No response

@DoubleHyphen DoubleHyphen added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 5, 2025
@hanna-kruppe
Copy link
Contributor

I would expect const _: () = …; to remove the warning but it doesn’t. Curiously, pub const _ doesn’t get the warning even though there’s no name to make public so the pub shouldn’t make a difference. That definitely feels like a bug to me.

@fmease fmease added L-dead_code Lint: dead_code L-false-positive Lint: False positive (should not have fired). C-bug Category: This is a bug. 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 Jun 5, 2025
@fmease fmease changed the title False positive: used function is deemed “never used” Function used in (unused) const item named _ NAME is incorrectly deemed dead Jun 5, 2025
@fmease fmease changed the title Function used in (unused) const item named _ NAME is incorrectly deemed dead Function used in (unused) const item named _NAME is incorrectly deemed dead Jun 5, 2025
@fmease
Copy link
Member

fmease commented Jun 5, 2025

To recap this reduces to

const fn f() {} //~ WARN function `f` is never used
const _X: () = f();

However, we apparently don't do this for any other cases either (namely, propagating liveness via _ident):

fn f() {} //~ WARN function `f` is never used
fn _g() { f() }

@fmease fmease changed the title Function used in (unused) const item named _NAME is incorrectly deemed dead Item used in (unused) item named _name is still deemed dead Jun 5, 2025
@fmease
Copy link
Member

fmease commented Jun 5, 2025

Also CC #118424

@hanna-kruppe
Copy link
Contributor

hanna-kruppe commented Jun 5, 2025

I think it’s a consistent, defensible choice to treat an underscore prefix as only suppressing the dead code lint for that one item, without counting as a “root” for the purpose of computing which things are reachable from exports/entry points. It could be done differently but there’s arguments for it as well.

However, const _ not counting as “root” seems wrong because that syntax exists only for the side effects of type checking and evaluating the constant expression. It’s the best solution for “I only want a compile time assertion, not define a value” (at the module level; within functions a const block is more flexible) and was specifically added after const _FOO already existed. So it should work for @DoubleHyphen’s use case and for #118424 — even and especially if we stick with the current behavior for const _FOO for consistency with other items.

@DoubleHyphen
Copy link
Author

DoubleHyphen commented Jun 5, 2025

Curiously, pub const _ doesn’t get the warning

…it does when it's inside a module, though!

const fn foo() {} // warning: function `foo` is never used

mod whatever {
    pub const _: () = crate::foo();
}

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 L-false-positive Lint: False positive (should not have fired). 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

3 participants