From dc0068cf75b7bb51a3b0957052523f6823e7a4b1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 16 Jun 2025 13:35:18 -0700 Subject: [PATCH 1/9] Unwrap must_use --- src/attributes/diagnostics.md | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index b294ec5fc7..37c2a191cc 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -349,23 +349,16 @@ r[attributes.diagnostics.must_use] ## The `must_use` attribute r[attributes.diagnostics.must_use.intro] -The *`must_use` attribute* is used to issue a diagnostic warning when a value -is not "used". +The *`must_use` attribute* is used to issue a diagnostic warning when a value is not "used". r[attributes.diagnostics.must_use.allowed-positions] -The `must_use` attribute can be applied to user-defined composite types -([`struct`s][struct], [`enum`s][enum], and [`union`s][union]), [functions], -and [traits]. +The `must_use` attribute can be applied to user-defined composite types ([`struct`s][struct], [`enum`s][enum], and [`union`s][union]), [functions], and [traits]. r[attributes.diagnostics.must_use.message] -The `must_use` attribute may include a message by using the -[MetaNameValueStr] syntax such as `#[must_use = "example message"]`. The -message will be given alongside the warning. +The `must_use` attribute may include a message by using the [MetaNameValueStr] syntax such as `#[must_use = "example message"]`. The message will be given alongside the warning. r[attributes.diagnostics.must_use.type] -When used on user-defined composite types, if the [expression] of an -[expression statement] has that type, then the `unused_must_use` lint is -violated. +When used on user-defined composite types, if the [expression] of an [expression statement] has that type, then the `unused_must_use` lint is violated. ```rust #[must_use] @@ -382,9 +375,7 @@ MustUse::new(); ``` r[attributes.diagnostics.must_use.fn] -When used on a function, if the [expression] of an [expression statement] is a -[call expression] to that function, then the `unused_must_use` lint is -violated. +When used on a function, if the [expression] of an [expression statement] is a [call expression] to that function, then the `unused_must_use` lint is violated. ```rust #[must_use] @@ -395,9 +386,7 @@ five(); ``` r[attributes.diagnostics.must_use.trait] -When used on a [trait declaration], a [call expression] of an [expression -statement] to a function that returns an [impl trait] or a [dyn trait] of that trait violates -the `unused_must_use` lint. +When used on a [trait declaration], a [call expression] of an [expression statement] to a function that returns an [impl trait] or a [dyn trait] of that trait violates the `unused_must_use` lint. ```rust #[must_use] @@ -413,8 +402,7 @@ get_critical(); ``` r[attributes.diagnostics.must_use.trait-function] -When used on a function in a trait declaration, then the behavior also applies -when the call expression is a function from an implementation of the trait. +When used on a function in a trait declaration, then the behavior also applies when the call expression is a function from an implementation of the trait. ```rust trait Trait { From a52d649534477d29816a73e049cff9b404a1ea45 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 16 Jun 2025 13:49:32 -0700 Subject: [PATCH 2/9] Move examples into example blocks --- src/attributes/diagnostics.md | 94 ++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 37c2a191cc..f3333ab313 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -360,63 +360,67 @@ The `must_use` attribute may include a message by using the [MetaNameValueStr] s r[attributes.diagnostics.must_use.type] When used on user-defined composite types, if the [expression] of an [expression statement] has that type, then the `unused_must_use` lint is violated. -```rust -#[must_use] -struct MustUse { - // some fields -} - -# impl MustUse { -# fn new() -> MustUse { MustUse {} } -# } -# -// Violates the `unused_must_use` lint. -MustUse::new(); -``` +> [!EXAMPLE] +> ```rust +> #[must_use] +> struct MustUse { +> // some fields +> } +> +> # impl MustUse { +> # fn new() -> MustUse { MustUse {} } +> # } +> # +> // Violates the `unused_must_use` lint. +> MustUse::new(); +> ``` r[attributes.diagnostics.must_use.fn] When used on a function, if the [expression] of an [expression statement] is a [call expression] to that function, then the `unused_must_use` lint is violated. -```rust -#[must_use] -fn five() -> i32 { 5i32 } - -// Violates the unused_must_use lint. -five(); -``` +> [!EXAMPLE] +> ```rust +> #[must_use] +> fn five() -> i32 { 5i32 } +> +> // Violates the unused_must_use lint. +> five(); +> ``` r[attributes.diagnostics.must_use.trait] When used on a [trait declaration], a [call expression] of an [expression statement] to a function that returns an [impl trait] or a [dyn trait] of that trait violates the `unused_must_use` lint. -```rust -#[must_use] -trait Critical {} -impl Critical for i32 {} - -fn get_critical() -> impl Critical { - 4i32 -} - -// Violates the `unused_must_use` lint. -get_critical(); -``` +> [!EXAMPLE] +> ```rust +> #[must_use] +> trait Critical {} +> impl Critical for i32 {} +> +> fn get_critical() -> impl Critical { +> 4i32 +> } +> +> // Violates the `unused_must_use` lint. +> get_critical(); +> ``` r[attributes.diagnostics.must_use.trait-function] When used on a function in a trait declaration, then the behavior also applies when the call expression is a function from an implementation of the trait. -```rust -trait Trait { - #[must_use] - fn use_me(&self) -> i32; -} - -impl Trait for i32 { - fn use_me(&self) -> i32 { 0i32 } -} - -// Violates the `unused_must_use` lint. -5i32.use_me(); -``` +> [!EXAMPLE] +> ```rust +> trait Trait { +> #[must_use] +> fn use_me(&self) -> i32; +> } +> +> impl Trait for i32 { +> fn use_me(&self) -> i32 { 0i32 } +> } +> +> // Violates the `unused_must_use` lint. +> 5i32.use_me(); +> ``` r[attributes.diagnostics.must_use.trait-impl-function] When used on a function in a trait implementation, the attribute does nothing. From c9becb484cfe64837d6ac72f57a18d18b93b6acf Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 16 Jun 2025 13:49:57 -0700 Subject: [PATCH 3/9] Update diagnostic to use the attribute template --- src/attributes/diagnostics.md | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index f3333ab313..5339082fe0 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -349,10 +349,37 @@ r[attributes.diagnostics.must_use] ## The `must_use` attribute r[attributes.diagnostics.must_use.intro] -The *`must_use` attribute* is used to issue a diagnostic warning when a value is not "used". +The *`must_use` [attribute][attributes]* is used to issue a diagnostic warning when a value is not used. + +r[attributes.diagnostics.must_use.syntax] +The `must_use` attribute uses either the [MetaWord] syntax or the [MetaNameValueStr] syntax to be able to [specify a message][attributes.diagnostics.must_use.message]. + +> [!EXAMPLE] +> ```rust +> #[must_use] +> fn use_me() -> u8 { 0 } +> +> #[must_use = "explanation of why it must be used"] +> fn use_me2() -> u8 { 0 } +> ``` r[attributes.diagnostics.must_use.allowed-positions] -The `must_use` attribute can be applied to user-defined composite types ([`struct`s][struct], [`enum`s][enum], and [`union`s][union]), [functions], and [traits]. +The `must_use` attribute may be applied to a: + +- [Struct] +- [Enumeration] +- [Union] +- [Function] +- [Trait] + +> [!NOTE] +> `rustc` currently warns in other positions, but this may be rejected in the future. + +r[attributes.diagnostics.must_use.duplicates] +The `must_use` attribute may only be specified once on an item. + +> [!NOTE] +> `rustc` currently warns on subsequent duplicate `must_use` attributes. This may become an error in the future. r[attributes.diagnostics.must_use.message] The `must_use` attribute may include a message by using the [MetaNameValueStr] syntax such as `#[must_use = "example message"]`. The message will be given alongside the warning. @@ -661,7 +688,7 @@ The first error message includes a somewhat confusing error message about the re [call expression]: ../expressions/call-expr.md [dyn trait]: ../types/trait-object.md [enum variant]: ../items/enumerations.md -[enum]: ../items/enumerations.md +[enumeration]: ../items/enumerations.md [expression statement]: ../statements.md#expression-statements [expression]: ../expressions.md [external block item]: ../items/external-blocks.md From 106a4a1513851892e9b3029037dab7becffcfc3a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 22 Sep 2025 12:51:13 -0700 Subject: [PATCH 4/9] Minor update of must_use More closely align with the template, and some minor word tweaks. --- src/attributes/diagnostics.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 5339082fe0..26faf3b262 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -345,6 +345,7 @@ The [RFC][1270-deprecation.md] contains motivations and more details. [1270-deprecation.md]: https://github.com/rust-lang/rfcs/blob/master/text/1270-deprecation.md + r[attributes.diagnostics.must_use] ## The `must_use` attribute @@ -373,13 +374,13 @@ The `must_use` attribute may be applied to a: - [Trait] > [!NOTE] -> `rustc` currently warns in other positions, but this may be rejected in the future. +> `rustc` ignores use in other positions but lints against it. This may become an error in the future. r[attributes.diagnostics.must_use.duplicates] -The `must_use` attribute may only be specified once on an item. +The `must_use` attribute may be used only once on an item. > [!NOTE] -> `rustc` currently warns on subsequent duplicate `must_use` attributes. This may become an error in the future. +> `rustc` lints against any use following the first. This may become an error in the future. r[attributes.diagnostics.must_use.message] The `must_use` attribute may include a message by using the [MetaNameValueStr] syntax such as `#[must_use = "example message"]`. The message will be given alongside the warning. From 93fe20dcb30518204619bcc98ab75df393d6e1c5 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 1 Mar 2026 02:39:13 +0000 Subject: [PATCH 5/9] Revise `must_use` attribute text Let's adjust the section on `must_use` to follow the editorial direction we've been taking. --- src/attributes/diagnostics.md | 161 +++++++++++++++++++--------------- 1 file changed, 90 insertions(+), 71 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 26faf3b262..d9e326bd01 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -350,17 +350,17 @@ r[attributes.diagnostics.must_use] ## The `must_use` attribute r[attributes.diagnostics.must_use.intro] -The *`must_use` [attribute][attributes]* is used to issue a diagnostic warning when a value is not used. +The *`must_use` [attribute]* marks a value that should be used. r[attributes.diagnostics.must_use.syntax] -The `must_use` attribute uses either the [MetaWord] syntax or the [MetaNameValueStr] syntax to be able to [specify a message][attributes.diagnostics.must_use.message]. +The `must_use` attribute uses the [MetaWord] and [MetaNameValueStr] syntaxes. > [!EXAMPLE] > ```rust > #[must_use] -> fn use_me() -> u8 { 0 } +> fn use_me1() -> u8 { 0 } > -> #[must_use = "explanation of why it must be used"] +> #[must_use = "explanation of why it should be used"] > fn use_me2() -> u8 { 0 } > ``` @@ -383,102 +383,118 @@ The `must_use` attribute may be used only once on an item. > `rustc` lints against any use following the first. This may become an error in the future. r[attributes.diagnostics.must_use.message] -The `must_use` attribute may include a message by using the [MetaNameValueStr] syntax such as `#[must_use = "example message"]`. The message will be given alongside the warning. +The `must_use` attribute may include a message by using the [MetaNameValueStr] syntax, e.g., `#[must_use = "example message"]`. The message may be emitted as part of the lint. r[attributes.diagnostics.must_use.type] -When used on user-defined composite types, if the [expression] of an [expression statement] has that type, then the `unused_must_use` lint is violated. +When the attribute is applied to a [struct], [enumeration], or [union], if the [expression] of an [expression statement] has that type, the use triggers the `unused_must_use` lint. -> [!EXAMPLE] -> ```rust -> #[must_use] -> struct MustUse { -> // some fields -> } -> -> # impl MustUse { -> # fn new() -> MustUse { MustUse {} } -> # } -> # -> // Violates the `unused_must_use` lint. -> MustUse::new(); -> ``` +```rust,compile_fail +#![deny(unused_must_use)] +#[must_use] +struct MustUse(); +MustUse(); // ERROR: Unused value that must be used. +``` r[attributes.diagnostics.must_use.fn] -When used on a function, if the [expression] of an [expression statement] is a [call expression] to that function, then the `unused_must_use` lint is violated. +If the [expression] of an [expression statement] is a [call expression] or [method call expression] whose function operand is a function to which the attribute is applied, the use triggers the `unused_must_use` lint. -> [!EXAMPLE] -> ```rust -> #[must_use] -> fn five() -> i32 { 5i32 } -> -> // Violates the unused_must_use lint. -> five(); -> ``` +```rust,compile_fail +#![deny(unused_must_use)] +#[must_use] +fn f() {} +f(); // ERROR: Unused return value that must be used. +``` r[attributes.diagnostics.must_use.trait] -When used on a [trait declaration], a [call expression] of an [expression statement] to a function that returns an [impl trait] or a [dyn trait] of that trait violates the `unused_must_use` lint. +If the [expression] of an [expression statement] is a [call expression] or [method call expression] whose function operand is a function that returns an [impl trait] or a [dyn trait] type where one or more traits in the bound are marked with the attribute, the use triggers the `unused_must_use` lint. -> [!EXAMPLE] -> ```rust -> #[must_use] -> trait Critical {} -> impl Critical for i32 {} -> -> fn get_critical() -> impl Critical { -> 4i32 -> } -> -> // Violates the `unused_must_use` lint. -> get_critical(); -> ``` +```rust,compile_fail +#![deny(unused_must_use)] +#[must_use] +trait Tr {} +impl Tr for () {} +fn f() -> impl Tr {} +f(); // ERROR: Unused implementor that must be used. +``` r[attributes.diagnostics.must_use.trait-function] -When used on a function in a trait declaration, then the behavior also applies when the call expression is a function from an implementation of the trait. +When the attribute is applied to a function in a trait declaration, the rules described in [attributes.diagnostics.must_use.fn] also apply when the function operand of the [call expression] or [method call expression] is an implementation of that function. -> [!EXAMPLE] -> ```rust -> trait Trait { -> #[must_use] -> fn use_me(&self) -> i32; -> } -> -> impl Trait for i32 { -> fn use_me(&self) -> i32 { 0i32 } -> } -> -> // Violates the `unused_must_use` lint. -> 5i32.use_me(); -> ``` +```rust,compile_fail +#![deny(unused_must_use)] +trait Tr { + #[must_use] + fn use_me(&self); +} + +impl Tr for () { + fn use_me(&self) {} +} + +().use_me(); // ERROR: Unused return value that must be used. +``` + +```rust,compile_fail +# #![deny(unused_must_use)] +# trait Tr { +# #[must_use] +# fn use_me(&self); +# } +# +# impl Tr for () { +# fn use_me(&self) {} +# } +# +<() as Tr>::use_me(&()); +// ^^^^^^^^^^^ ERROR: Unused return value that must be used. +``` r[attributes.diagnostics.must_use.trait-impl-function] When used on a function in a trait implementation, the attribute does nothing. +```rust +#![deny(unused_must_use)] +trait Tr { + fn f(&self); +} + +impl Tr for () { + #[must_use] // This has no effect. + fn f(&self) {} +} + +().f(); // OK. +``` + > [!NOTE] -> Trivial no-op expressions containing the value will not violate the lint. Examples include wrapping the value in a type that does not implement [`Drop`] and then not using that type and being the final expression of a [block expression] that is not used. +> `rustc` lints against use on functions in trait implementations. This may become an error in the future. + +> [!NOTE] +> Wrapping the value, even trivially, will suppress the lint. > > ```rust +> #![deny(unused_must_use)] > #[must_use] -> fn five() -> i32 { 5i32 } +> fn f() {} > -> // None of these violate the unused_must_use lint. -> (five(),); -> Some(five()); -> { five() }; -> if true { five() } else { 0i32 }; +> // None of these trigger the `unused_must_use` lint. +> (f(),); +> Some(f()); +> { f() }; +> if true { f() } else {}; > match true { -> _ => five() +> _ => f() > }; > ``` > [!NOTE] -> It is idiomatic to use a [let statement] with a pattern of `_` when a must-used value is purposely discarded. +> Using a [let statement] with a pattern of `_` when a must-used value is purposely discarded is idiomatic. > > ```rust +> #![deny(unused_must_use)] > #[must_use] -> fn five() -> i32 { 5i32 } -> -> // Does not violate the unused_must_use lint. -> let _ = five(); +> fn f() {} +> let _ = f(); // OK. > ``` r[attributes.diagnostic.namespace] @@ -684,9 +700,11 @@ The first error message includes a somewhat confusing error message about the re [Clippy]: https://github.com/rust-lang/rust-clippy [`Drop`]: ../special-types-and-traits.md#drop +[attribute]: ../attributes.md [attributes]: ../attributes.md [block expression]: ../expressions/block-expr.md [call expression]: ../expressions/call-expr.md +[method call expression]: ../expressions/method-call-expr.md [dyn trait]: ../types/trait-object.md [enum variant]: ../items/enumerations.md [enumeration]: ../items/enumerations.md @@ -706,6 +724,7 @@ The first error message includes a somewhat confusing error message about the re [rustdoc]: ../../rustdoc/lints.html [struct field]: ../items/structs.md [struct]: ../items/structs.md +[external block]: ../items/external-blocks.md [trait declaration]: ../items/traits.md [trait item]: ../items/traits.md [trait-impl]: ../items/implementations.md#trait-implementations From 0775ef39ef4adc7d494aa22ec96f3a3e98f73489 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 1 Mar 2026 09:41:42 +0000 Subject: [PATCH 6/9] Fix `must_use` lint behavior for block expressions The admonition for `must_use` claimed that wrapping a value in a block expression, as in `{ f() };`, suppresses the `unused_must_use` lint. Testing against rustc shows this isn't true -- the lint explicitly looks through block expressions (including `unsafe` and labeled blocks) to their trailing expression before checking. Let's fix that. --- src/attributes/diagnostics.md | 42 +++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index d9e326bd01..de1c8fe53f 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -449,6 +449,19 @@ impl Tr for () { // ^^^^^^^^^^^ ERROR: Unused return value that must be used. ``` +r[attributes.diagnostics.must_use.block-expr] +When checking the [expression] of an [expression statement] for [attributes.diagnostics.must_use.type], [attributes.diagnostics.must_use.fn], [attributes.diagnostics.must_use.trait], and [attributes.diagnostics.must_use.trait-function], the lint looks through [block expressions][block expression] (including [`unsafe` blocks] and [labeled block expressions]) to the trailing expression of each. This applies recursively for nested block expressions. + +```rust,compile_fail +#![deny(unused_must_use)] +#[must_use] +fn f() {} + +{ f() }; // ERROR: The lint looks through block expressions. +unsafe { f() }; // ERROR: The lint looks through `unsafe` blocks. +{ { f() } }; // ERROR: The lint looks through nested blocks. +``` + r[attributes.diagnostics.must_use.trait-impl-function] When used on a function in a trait implementation, the attribute does nothing. @@ -470,22 +483,35 @@ impl Tr for () { > `rustc` lints against use on functions in trait implementations. This may become an error in the future. > [!NOTE] -> Wrapping the value, even trivially, will suppress the lint. +> Wrapping the result of a `#[must_use]` function in certain expressions can suppress the [fn-based check][attributes.diagnostics.must_use.fn], because the [expression] of the [expression statement] is not a [call expression] or [method call expression] to a `#[must_use]` function. The [type-based check][attributes.diagnostics.must_use.type] still applies if the type of the overall expression is `#[must_use]`. > > ```rust > #![deny(unused_must_use)] > #[must_use] > fn f() {} > -> // None of these trigger the `unused_must_use` lint. -> (f(),); -> Some(f()); -> { f() }; -> if true { f() } else {}; -> match true { +> // The fn-based check does not fire for any of these, because the +> // expression of the expression statement is not a call to a +> // `#[must_use]` function. +> (f(),); // Expression is a tuple, not a call. +> Some(f()); // Callee `Some` is not `#[must_use]`. +> if true { f() } else {}; // Expression is an `if`, not a call. +> match true { // Expression is a `match`, not a call. > _ => f() > }; > ``` +> +> ```rust,compile_fail +> #![deny(unused_must_use)] +> #[must_use] +> struct MustUse; +> fn g() -> MustUse { MustUse } +> +> // Despite the `if` expression not being a call, the type-based check +> // fires because the type of the expression is `MustUse`, which has +> // the `#[must_use]` attribute. +> if true { g() } else { MustUse }; // ERROR: Must be used. +> ``` > [!NOTE] > Using a [let statement] with a pattern of `_` when a must-used value is purposely discarded is idiomatic. @@ -700,6 +726,7 @@ The first error message includes a somewhat confusing error message about the re [Clippy]: https://github.com/rust-lang/rust-clippy [`Drop`]: ../special-types-and-traits.md#drop +[`unsafe` blocks]: ../expressions/block-expr.md#unsafe-blocks [attribute]: ../attributes.md [attributes]: ../attributes.md [block expression]: ../expressions/block-expr.md @@ -715,6 +742,7 @@ The first error message includes a somewhat confusing error message about the re [impl trait]: ../types/impl-trait.md [implementation]: ../items/implementations.md [item]: ../items.md +[labeled block expressions]: ../expressions/block-expr.md#labeled-block-expressions [let statement]: ../statements.md#let-statements [macro definition]: ../macros-by-example.md [module]: ../items/modules.md From f9b0c775b7607f8d7957474acb5e8a7bab8df77b Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 1 Mar 2026 09:55:54 +0000 Subject: [PATCH 7/9] Add `must_use` exception for infallible results On lang, we recently decided (in rust-lang/rust#147382) that `Result<(), E>` and `ControlFlow` should not trigger the `unused_must_use` lint when the error or break type is uninhabited. The rationale is that an infallible result carries nothing the caller needs to handle. Let's document this. --- src/attributes/diagnostics.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index de1c8fe53f..691f2e02ba 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -395,6 +395,19 @@ struct MustUse(); MustUse(); // ERROR: Unused value that must be used. ``` +r[attributes.diagnostics.must_use.type.uninhabited] +As an exception to [attributes.diagnostics.must_use.type], the lint does not fire for `Result<(), E>` when `E` is [uninhabited] or for `ControlFlow` when `B` is [uninhabited]. A `#[non_exhaustive]` type from an external crate is not considered uninhabited for this purpose, because it may gain constructors in the future. + +```rust +#![deny(unused_must_use)] +# use core::ops::ControlFlow; +enum Empty {} +fn f1() -> Result<(), Empty> { Ok(()) } +f1(); // OK: `Empty` is uninhabited. +fn f2() -> ControlFlow { ControlFlow::Continue(()) } +f2(); // OK: `Empty` is uninhabited. +``` + r[attributes.diagnostics.must_use.fn] If the [expression] of an [expression statement] is a [call expression] or [method call expression] whose function operand is a function to which the attribute is applied, the use triggers the `unused_must_use` lint. @@ -757,4 +770,5 @@ The first error message includes a somewhat confusing error message about the re [trait item]: ../items/traits.md [trait-impl]: ../items/implementations.md#trait-implementations [traits]: ../items/traits.md +[uninhabited]: glossary.uninhabited [union]: ../items/unions.md From 887affdbc09af5ea64212a324d4cef47c63377be Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 18 Mar 2026 01:05:50 +0000 Subject: [PATCH 8/9] Mention `_` destructuring assignment idiom Now that we support destructuring assignment, using `_ = f()` to suppress a `must_use` lint is also probably idiomatic. Let's mention it. --- src/attributes/diagnostics.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 691f2e02ba..2d7176cb80 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -527,13 +527,14 @@ impl Tr for () { > ``` > [!NOTE] -> Using a [let statement] with a pattern of `_` when a must-used value is purposely discarded is idiomatic. +> Using a [let statement] or [destructuring assignment] with a pattern of `_` when a must-used value is purposely discarded is idiomatic. > > ```rust > #![deny(unused_must_use)] > #[must_use] > fn f() {} > let _ = f(); // OK. +> _ = f(); // OK. > ``` r[attributes.diagnostic.namespace] @@ -744,6 +745,7 @@ The first error message includes a somewhat confusing error message about the re [attributes]: ../attributes.md [block expression]: ../expressions/block-expr.md [call expression]: ../expressions/call-expr.md +[destructuring assignment]: expr.assign.destructure [method call expression]: ../expressions/method-call-expr.md [dyn trait]: ../types/trait-object.md [enum variant]: ../items/enumerations.md From a30f26eb412665a3e3a814a9bf417b6064fa9cca Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 18 Mar 2026 01:32:03 +0000 Subject: [PATCH 9/9] Add rule identifiers for unassociated `must_use` notes We have two note admonitions at the bottom of the `must_use` section that weren't associated with any particular rule but, by falling below the final rule without identifiers of their own, appeared to be associated with it. Let's give each of these a rule identifier to make this more clear. --- src/attributes/diagnostics.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 2d7176cb80..561d381070 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -495,6 +495,7 @@ impl Tr for () { > [!NOTE] > `rustc` lints against use on functions in trait implementations. This may become an error in the future. +r[attributes.diagnostics.must_use.wrapping-suppression] > [!NOTE] > Wrapping the result of a `#[must_use]` function in certain expressions can suppress the [fn-based check][attributes.diagnostics.must_use.fn], because the [expression] of the [expression statement] is not a [call expression] or [method call expression] to a `#[must_use]` function. The [type-based check][attributes.diagnostics.must_use.type] still applies if the type of the overall expression is `#[must_use]`. > @@ -526,6 +527,7 @@ impl Tr for () { > if true { g() } else { MustUse }; // ERROR: Must be used. > ``` +r[attributes.diagnostics.must_use.underscore-idiom] > [!NOTE] > Using a [let statement] or [destructuring assignment] with a pattern of `_` when a must-used value is purposely discarded is idiomatic. >