Skip to content

Block expression "swallows" unused_must_use warning #104253

Closed
@seritools

Description

@seritools

Given the following code: Playground

#[must_use]
fn foo() -> i32 {
    42
}

fn warns() {
    {
        bar();
    }
}

fn does_not_warn() {
    {
        bar()
    };
}

fn main() {
    warns();
    does_not_warn();
}

The current output is:

warning: unused return value of `foo` that must be used
 --> src/main.rs:8:9
  |
8 |         foo();
  |         ^^^^^^
  |
  = note: `#[warn(unused_must_use)]` on by default

Ideally the output should look something like:

warning: unused return value of `foo` that must be used
 --> src/main.rs:8:9
  |
8 |         foo();
  |         ^^^^^^
  |
  = note: `#[warn(unused_must_use)]` on by default

warning: unused return value of `foo` that must be used
  --> src/main.rs:14:9
   |
14 |         foo()
   |         ^^^^^
  = note: the containing block is unused

I've stumbled upon this with code that uses unsafe. Sometimes you see

unsafe { some_fn_call() };

instead of

unsafe { some_fn_call(); }

// or rather after rustfmt:
unsafe {
    some_fn_call();
}

which swallows the warning, as the block counts as a usage, even if the block itself is unused.
It would be nice if the block eval expression could "taint" the block itself, making it effectively #[must_use] as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions