Skip to content

#[must_use] on traits should apply to all types that implement the trait, not just for impl Trait placeholders #102238

Open
@KarelPeeters

Description

@KarelPeeters

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!
}

(playground)

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:

#[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:

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions