Putting #[must_use] on a trait is currently a no-op (it doesn't seem to do anything, but it is allowed). See example on playground.
One important use-case for this would be to have #[must_use] on std::Future. When returning impl Future<…> or Box<dyn Future<…>> from a function, it should lead to a warning if that future is not used, as that is almost certainly a bug.
cc @varkor
(Also see previous discussion on #51560.)
This is now possible. It should be easy to make a pull request adding #[must_use] to Future (with a test).
We probably want to also consider what other traits would benefit from being #[must_use]. Iterator is a fairly obvious choice, for one.
Fn FnMut FnOnce are good candidates as well.
@F001 Can you elaborate? If Output = () then I probably don't want the warning...?
@Centril Well, I think this warning means this:
let c : impl Fn(i32) = ... ;
c(); // `c` must be used. If `c` is discarded, it probably indicates something wrong.
let r = c(); // I think this attribute does not care `r` is used or not
@F001 Yeah that makes sense.
Has this issue been taken?
@FrankSD: this appears to have been completed in https://github.com/rust-lang/rust/pull/56677. However, at least one of the traits could do with a more informative #[must_use] message as highlighted in https://github.com/rust-lang/rust/pull/56677/files#r241236020 (and perhaps the others could be improved too). So you're welcome to open a PR with that improvement!
I'm going to close this issue, though, as I think it's been completed satisfactorily.
The OP mentions both impl Future and Box<dyn Future>. It appears the former has been implemented, but the latter doesn't warn still.
#[must_use]
trait Foo {}
impl Foo for () {}
fn foo() -> impl Foo {
()
}
fn bar() -> Box<dyn Foo> {
Box::new(())
}
fn main() {
foo();
bar();
}
only gives (playground)
Compiling playground v0.0.1 (/playground)
warning: unused implementer of `Foo` that must be used
--> src/main.rs:16:5
|
16 | foo();
| ^^^^^^
|
= note: #[warn(unused_must_use)] on by default
Finished dev [unoptimized + debuginfo] target(s) in 0.68s
Running `target/debug/playground`
This was an oversight on my part; I'll open up a PR soon to fix this.
It does apply to let x: dyn Future.
As for Box<dyn Trait> and #[must_use] it doesn't seem trivial to me unless you make it a special case for Box. We should think of a general solution for type constructors.
This is related to (or is maybe just a subissue of) https://github.com/rust-lang/rust/issues/39524. It seems reasonable to special-case Box as a stop-gap and try to fix the whole issue at some point.
@varkor If you're going for a hack, an attribute based hack seems better, e.g.
pub struct Box<#[rustc_propagate_must_use] T: ?Sized>(Unique<T>);
@Centril: I'm not really going for a hack — Box is already a special-cased type and I'm simply going to add explicit handling for it into unused.rs. I think we'd want to special case it even if we had general support for unused components of structs, to give better error messages.
@varkor is this going to propagate #[must_use] for Pin<Box<Future>>? Or just Box<Future>?
@andll: I don't think this will propagate for Pin<Box<Future>>, but I imagine https://github.com/rust-lang/rust/pull/62262 would do.
I'd like to bring this back up a bit.
I've been doing some introductory async work, and I've been bitten by the lack of hints to use a boxed future (futures::future::BoxFuture<'a, T> / Pin<Box<dyn Future<Output = T> + 'a + Send>>) multiple times. This is exacerbated because we cannot use async fn in traits, so boxing is a common workaround — the compiler error messages even suggest using a crate that automatically performs this rewriting!
@shepmaster new issue for that appears to be https://github.com/rust-lang/rust/issues/67387
Most helpful comment
This is now possible. It should be easy to make a pull request adding
#[must_use]toFuture(with a test).We probably want to also consider what other traits would benefit from being
#[must_use].Iteratoris a fairly obvious choice, for one.