@@ -173,3 +173,126 @@ pub fn spin_loop() {
173
173
pub const fn black_box < T > ( dummy : T ) -> T {
174
174
crate :: intrinsics:: black_box ( dummy)
175
175
}
176
+
177
+ /// An identity function that causes an `unused_must_use` warning to be
178
+ /// triggered if the given value is not used (returned, stored in a variable,
179
+ /// etc) by the caller.
180
+ ///
181
+ /// This is primarily intended for use in macro-generated code, in which a
182
+ /// [`#[must_use]` attribute][must_use] either on a type or a function would not
183
+ /// be convenient.
184
+ ///
185
+ /// [must_use]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
186
+ ///
187
+ /// # Example
188
+ ///
189
+ /// ```
190
+ /// #![feature(hint_must_use)]
191
+ ///
192
+ /// use core::fmt;
193
+ ///
194
+ /// pub struct Error(/* ... */);
195
+ ///
196
+ /// #[macro_export]
197
+ /// macro_rules! make_error {
198
+ /// ($($args:expr),*) => {
199
+ /// core::hint::must_use({
200
+ /// let error = $crate::make_error(core::format_args!($($args),*));
201
+ /// error
202
+ /// })
203
+ /// };
204
+ /// }
205
+ ///
206
+ /// // Implementation detail of make_error! macro.
207
+ /// #[doc(hidden)]
208
+ /// pub fn make_error(args: fmt::Arguments<'_>) -> Error {
209
+ /// Error(/* ... */)
210
+ /// }
211
+ ///
212
+ /// fn demo() -> Option<Error> {
213
+ /// if true {
214
+ /// // Oops, meant to write `return Some(make_error!("..."));`
215
+ /// Some(make_error!("..."));
216
+ /// }
217
+ /// None
218
+ /// }
219
+ /// #
220
+ /// # // Make rustdoc not wrap the whole snippet in fn main, so that $crate::make_error works
221
+ /// # fn main() {}
222
+ /// ```
223
+ ///
224
+ /// In the above example, we'd like an `unused_must_use` lint to apply to the
225
+ /// value created by `make_error!`. However, neither `#[must_use]` on a struct
226
+ /// nor `#[must_use]` on a function is appropriate here, so the macro expands
227
+ /// using `core::hint::must_use` instead.
228
+ ///
229
+ /// - We wouldn't want `#[must_use]` on the `struct Error` because that would
230
+ /// make the following unproblematic code trigger a warning:
231
+ ///
232
+ /// ```
233
+ /// # struct Error;
234
+ /// #
235
+ /// fn f(arg: &str) -> Result<(), Error>
236
+ /// # { Ok(()) }
237
+ ///
238
+ /// #[test]
239
+ /// fn t() {
240
+ /// // Assert that `f` returns error if passed an empty string.
241
+ /// // A value of type `Error` is unused here but that's not a problem.
242
+ /// f("").unwrap_err();
243
+ /// }
244
+ /// ```
245
+ ///
246
+ /// - Using `#[must_use]` on `fn make_error` can't help because the return value
247
+ /// *is* used, as the right-hand side of a `let` statement. The `let`
248
+ /// statement looks useless but is in fact necessary for ensuring that
249
+ /// temporaries within the `format_args` expansion are not kept alive past the
250
+ /// creation of the `Error`, as keeping them alive past that point can cause
251
+ /// autotrait issues in async code:
252
+ ///
253
+ /// ```
254
+ /// # #![feature(hint_must_use)]
255
+ /// #
256
+ /// # struct Error;
257
+ /// #
258
+ /// # macro_rules! make_error {
259
+ /// # ($($args:expr),*) => {
260
+ /// # core::hint::must_use({
261
+ /// # // If `let` isn't used, then `f()` produces a non-Send future.
262
+ /// # let error = make_error(core::format_args!($($args),*));
263
+ /// # error
264
+ /// # })
265
+ /// # };
266
+ /// # }
267
+ /// #
268
+ /// # fn make_error(args: core::fmt::Arguments<'_>) -> Error {
269
+ /// # Error
270
+ /// # }
271
+ /// #
272
+ /// async fn f() {
273
+ /// // Using `let` inside the make_error expansion causes temporaries like
274
+ /// // `unsync()` to drop at the semicolon of that `let` statement, which
275
+ /// // is prior to the await point. They would otherwise stay around until
276
+ /// // the semicolon on *this* statement, which is after the await point,
277
+ /// // and the enclosing Future would not implement Send.
278
+ /// log(make_error!("look: {:p}", unsync())).await;
279
+ /// }
280
+ ///
281
+ /// async fn log(error: Error) {/* ... */}
282
+ ///
283
+ /// // Returns something without a Sync impl.
284
+ /// fn unsync() -> *const () {
285
+ /// 0 as *const ()
286
+ /// }
287
+ /// #
288
+ /// # fn test() {
289
+ /// # fn assert_send(_: impl Send) {}
290
+ /// # assert_send(f());
291
+ /// # }
292
+ /// ```
293
+ #[ unstable( feature = "hint_must_use" , issue = "94745" ) ]
294
+ #[ rustc_const_unstable( feature = "hint_must_use" , issue = "94745" ) ]
295
+ #[ must_use] // <-- :)
296
+ pub const fn must_use < T > ( value : T ) -> T {
297
+ value
298
+ }
0 commit comments