From 407d7140b8f404f1643619623d0f6b04d375ca37 Mon Sep 17 00:00:00 2001 From: Havvy Date: Sun, 18 Feb 2018 23:12:00 -0800 Subject: [PATCH 1/4] Document RFC 1940 (must_use on fns) --- src/attributes.md | 95 +++++++++++++++++++++++++++++++++++++++++++--- src/type-layout.md | 2 +- 2 files changed, 90 insertions(+), 7 deletions(-) diff --git a/src/attributes.md b/src/attributes.md index 92a7784eb..a56f75994 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -166,9 +166,6 @@ macro scope. object file that this item's contents will be placed into. - `no_mangle` - on any item, do not apply the standard name mangling. Set the symbol for this item to its identifier. -- `must_use` - on structs and enums, will warn if a value of this type isn't used or - assigned to a variable. You may also include an optional message by using - `#[must_use = "message"]` which will be given alongside the warning. ### Deprecation @@ -325,7 +322,7 @@ The lint checks supported by the compiler can be found via `rustc -W help`, along with their default settings. [Compiler plugins][unstable book plugin] can provide additional lint checks. -```rust,ignore +```rust pub mod m1 { // Missing documentation is ignored here #[allow(missing_docs)] @@ -366,7 +363,7 @@ pub mod m2{ This example shows how one can use `forbid` to disallow uses of `allow` for that lint check: -```rust,ignore +```rust,compile_fail #[forbid(missing_docs)] pub mod m3 { // Attempting to toggle warning signals an error here @@ -376,6 +373,82 @@ pub mod m3 { } ``` +#### Must Use Attribute + +The `must_use` attribute can be used on user-defined composite types +([`struct`s][struct], [`enum`s][enum], and [`union`s][union]) and [functions]. + +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 {} } +# } + +fn main() { + // Violates the `unused_must_use` lint. + MustUse::new(); +} +``` + +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 } + +fn main() { + // Violates the unused_must_use lint. + five(); +} +``` + +> 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. +> +> ```rust +> #[must_use] +> fn five() -> i32 { 5i32 } +> +> fn main() { +> // None of these violate the unused_must_use lint. +> (five(),); +> Some(five()); +> { five() }; +> if true { five() } else { 0i32 }; +> match true { +> _ => five() +> }; +> } +> ``` + +> Note: It is idiomatic to use a [let statement] with a pattern of `_` +> when a must-used value is purposely discarded. +> +> ```rust +> #[must_use] +> fn five() -> i32 { 5i32 } +> +> fn main() { +> // Does not violate the unused_must_use lint. +> let _ = five(); +> } +> ``` + +The `must_use` attribute may also include a message by using +`#[must_use = "message"]`. The message will be given alongside the warning. + ### Inline attribute The inline attribute suggests that the compiler should place a copy of @@ -430,4 +503,14 @@ You can implement `derive` for your own type through [procedural macros]. [Doc comments]: comments.html#doc-comments [The Rustdoc Book]: ../rustdoc/the-doc-attribute.html [procedural macros]: procedural-macros.html -[unstable book plugin]: ../unstable-book/language-features/plugin.html#lint-plugins +[struct]: items/structs.html +[enum]: items/enumerations.html +[union]: items/unions.html +[functions]: items/functions.html +[expression]: expressions.html +[expression statement]: statements.html#expression-statements +[call expression]: expressions/call-expr.html +[block expression]: expressions/block-expr.html +[`Drop`]: special-types-and-traits.html#drop +[let statement]: statements.html#let-statements +[unstable book plugin]: ../unstable-book/language-features/plugin.html#lint-plugins \ No newline at end of file diff --git a/src/type-layout.md b/src/type-layout.md index 029899864..0c64f6763 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -106,7 +106,7 @@ Closures have no layout guarantees. ## Representations -All user-defined composite types (`struct`s, `enum`, and `union`s) have a +All user-defined composite types (`struct`s, `enum`s, and `union`s) have a *representation* that specifies what the layout is for the type. The possible representations for a type are the default representation, `C`, the From a64b477eba0f4195dda7a1951aabc4f190957cad Mon Sep 17 00:00:00 2001 From: Havvy Date: Mon, 19 Feb 2018 00:23:53 -0800 Subject: [PATCH 2/4] Edge cases of fn must-use --- src/attributes.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/attributes.md b/src/attributes.md index a56f75994..f8e828610 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -400,7 +400,9 @@ fn main() { 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. +`unused_must_use` lint is violated. The exceptions to this is if the return type +of the function is `()`, `!`, or a [zero-variant enum], in which case the +attribute does nothing. ```rust #[must_use] @@ -513,4 +515,5 @@ You can implement `derive` for your own type through [procedural macros]. [block expression]: expressions/block-expr.html [`Drop`]: special-types-and-traits.html#drop [let statement]: statements.html#let-statements -[unstable book plugin]: ../unstable-book/language-features/plugin.html#lint-plugins \ No newline at end of file +[unstable book plugin]: ../unstable-book/language-features/plugin.html#lint-plugins +[zero-variant enum]: enumerations.html#zero-variant-enums From 0ee01afd76538767c65172e77aad891ce458103c Mon Sep 17 00:00:00 2001 From: Havvy Date: Tue, 20 Feb 2018 12:52:33 -0800 Subject: [PATCH 3/4] Address alercah's feedback --- src/attributes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/attributes.md b/src/attributes.md index f8e828610..0d7e7327d 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -373,7 +373,7 @@ pub mod m3 { } ``` -#### Must Use Attribute +#### `must_use` Attribute The `must_use` attribute can be used on user-defined composite types ([`struct`s][struct], [`enum`s][enum], and [`union`s][union]) and [functions]. @@ -391,7 +391,7 @@ struct MustUse { # impl MustUse { # fn new() -> MustUse { MustUse {} } # } - +# fn main() { // Violates the `unused_must_use` lint. MustUse::new(); From f376333aa791674386e3de5722d5908c42d17c81 Mon Sep 17 00:00:00 2001 From: Havvy Date: Tue, 3 Apr 2018 13:13:42 -0700 Subject: [PATCH 4/4] #[must_use] on trait fns and impl fns docs --- src/attributes.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/attributes.md b/src/attributes.md index 0d7e7327d..49de6f854 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -414,6 +414,27 @@ fn main() { } ``` +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 } +} + +fn main() { + // Violates the `unused_must_use` lint. + 5i32.use_me(); +} +``` + +When used on a function in an implementation, the attribute does nothing. + > 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