@@ -173,3 +173,126 @@ pub fn spin_loop() {
173173pub const fn black_box < T > ( dummy : T ) -> T {
174174 crate :: intrinsics:: black_box ( dummy)
175175}
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