-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Description
General issue
Currently, #[must_use] on a trait Foo does not extend to types that implement Foo, it only works on impl Foo return types, and Box<dyn Foo> as a special case:
#[must_use]
trait Foo {}
struct Bar;
impl Foo for Bar {}
fn build_foo() -> impl Foo { Bar }
fn build_box() -> Box<dyn Foo> { Box::new(Bar) }
fn build_bar() -> Bar { Bar }
fn main() {
build_foo(); // warning: unused implementer of `Foo` that must be used
build_box(); // warning: unused boxed `Foo` trait object that must be used
build_bar(); // no warning!
}This does not make much sense, presumably if a trait must always be used all types that implement that trait must also be used.
Application to Future
I came across this when dealing with futures. The Future trait has a #[must_use] annotation, with the useful reminder to .await or poll them:
rust/library/core/src/future/future.rs
Lines 28 to 37 in b8967b0
| #[doc(notable_trait)] | |
| #[must_use = "futures do nothing unless you `.await` or poll them"] | |
| #[stable(feature = "futures_api", since = "1.36.0")] | |
| #[lang = "future_trait"] | |
| #[rustc_on_unimplemented( | |
| label = "`{Self}` is not a future", | |
| message = "`{Self}` is not a future", | |
| note = "{Self} must be a future or must implement `IntoFuture` to be awaited" | |
| )] | |
| pub trait Future { |
I was specifically using specifically BoxFuture, a type alias for Pin<Box<dyn Future>>. This type implements Future, but there is no warning message when you forget to use it. This was also the original justification in #67387, where a very different solution is proposed (extending must_use to Pin and other wrapper types).
Another effect of this missing warning is that any struct that implements Future has to repeat the same must_use annotation. Some examples:
futures::future::Readytokio::time::Sleepasync_stddoesn't expose any public types that implementFuture, instead they almost always use animpl Futurereturn type. There is still the internalWriteFmtFuture.
If must_use on traits infected any type that implemented it, these duplicate annotations could be removed and there would be no risk of forgetting them for any future types.