Consider `#[must_use]` annotation on `async fn` as also affecting the `Future::O...
source link: https://github.com/rust-lang/rust/pull/100633
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Contributor
tmandry left a comment
I think this is a very good approach that gets us a useful lint without boiling the ocean. It doesn't solve all problems (like going through join!
or similar), but that's allowed ("Trivial no-op expressions containing the value will not violate the lint").
It might actually be possible to support more of those cases by examining any pattern match, not just from matches desugared awaits. But if that's not easy (or too slow) we should land this now and leave it as follow-up work.
@rustbot author
compiler/rustc_lint/src/unused.rs
Outdated Show resolved
compiler/rustc_passes/src/check_attr.rs
Show resolved
src/test/ui/lint/unused/unused-async.stderr
Show resolved
src/test/ui/lint/unused/unused-async.stderr
Outdated Show resolved
1 |
||
} |
||
#[must_use] |
||
fn bar() -> impl std::future::Future<Output=i32> { |
I actually think this might have bigger lang implications, like implying this should also work for functions returning Result
as mentioned by #78149 (comment) or on associated types of other traits.
Do you think we should restrict to only async fn
for now? (I don't really want to do that since it limits the usefulness of the PR, but we might want the lang team to weigh in otherwise.)
Contributor
guswynn 23 days ago
Yeah, I think we should limit this to just async fn's for now. Generalizing #[must_use]
to look through types like Result
and Future
is going to require, I think, a pretty significant change (I think niko and I talked about basically needing auto-trait semantics?), and we should probably hold off on any half-measures that may make that more difficult (unless we decide its too difficult)
Stopping this from working would require changing the FnDecl
representation of all functions with information about the asyncness. Right now that is only tracked up to the HIR. I could make the lint check the fn
item to see if it's async
or not, but that only works for functions of the local crate. The four options here are: what it does now, and always propagate must_use
from any fn
to the Future::Output
it might return, make must_use
on async fn
only work for local crates, make must_use
on fn
s always work for foreign crates but only for async fn
in local crates, or modify ty::FnDecl
to track more metadata. I'm leaning towards the first case, despite the incorrect mental model it might imply to users for Result
and Option
.
Did not realize the complexity here! In that case, its probably fine to leave it! The plus side is that future work could make things like
#[must_use]
fn thing() -> BoxFuture<Thing> { ... }
can apply to Thing
!
Contributor
tmandry 22 days ago
I tend to agree, but I also don't know if I should be approving decisions about where a lint applies. I started a Zulip thread to get some t-lang feedback first.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK