Commit ff54e34
authored
Rollup merge of rust-lang#94723 - dtolnay:mustuse, r=Mark-Simulacrum
Add core::hint::must_use
The example code in this documentation is minimized from a real-world situation in the `anyhow` crate where this function would have been valuable.
Having this provided by the standard library is especially useful for proc macros, even more than for macro_rules. That's because proc macro crates aren't allowed to export anything other than macros, so they couldn't make their own `must_use` function for their macro-generated code to call.
<br>
## Rendered documentation
> An identity function that causes an `unused_must_use` warning to be triggered if the given value is not used (returned, stored in a variable, etc) by the caller.
>
> This is primarily intended for use in macro-generated code, in which a [`#[must_use]` attribute][must_use] either on a type or a function would not be convenient.
>
> [must_use]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
>
> ### Example
>
> ```rust
> #![feature(hint_must_use)]
>
> use core::fmt;
>
> pub struct Error(/* ... */);
>
> #[macro_export]
> macro_rules! make_error {
> ($($args:expr),*) => {
> core::hint::must_use({
> let error = $crate::make_error(core::format_args!($($args),*));
> error
> })
> };
> }
>
> // Implementation detail of make_error! macro.
> #[doc(hidden)]
> pub fn make_error(args: fmt::Arguments<'_>) -> Error {
> Error(/* ... */)
> }
>
> fn demo() -> Option<Error> {
> if true {
> // Oops, meant to write `return Some(make_error!("..."));`
> Some(make_error!("..."));
> }
> None
> }
> ```
>
> In the above example, we'd like an `unused_must_use` lint to apply to the value created by `make_error!`. However, neither `#[must_use]` on a struct nor `#[must_use]` on a function is appropriate here, so the macro expands using `core::hint::must_use` instead.
>
> - We wouldn't want `#[must_use]` on the `struct Error` because that would make the following unproblematic code trigger a warning:
>
> ```rust
> fn f(arg: &str) -> Result<(), Error>
>
> #[test]
> fn t() {
> // Assert that `f` returns error if passed an empty string.
> // A value of type `Error` is unused here but that's not a problem.
> f("").unwrap_err();
> }
> ```
>
> - Using `#[must_use]` on `fn make_error` can't help because the return value *is* used, as the right-hand side of a `let` statement. The `let` statement looks useless but is in fact necessary for ensuring that temporaries within the `format_args` expansion are not kept alive past the creation of the `Error`, as keeping them alive past that point can cause autotrait issues in async code:
>
> ```rust
> async fn f() {
> // Using `let` inside the make_error expansion causes temporaries like
> // `unsync()` to drop at the semicolon of that `let` statement, which
> // is prior to the await point. They would otherwise stay around until
> // the semicolon on *this* statement, which is after the await point,
> // and the enclosing Future would not implement Send.
> log(make_error!("look: {:p}", unsync())).await;
> }
>
> async fn log(error: Error) {/* ... */}
>
> // Returns something without a Sync impl.
> fn unsync() -> *const () {
> 0 as *const ()
> }
> ```1 file changed
+123
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
173 | 173 | | |
174 | 174 | | |
175 | 175 | | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
0 commit comments