Auto merge of #10589 - blyxyas:fix-double_must_use, r=giraffate
Mini-fix `double_must_use` for async functions From Rust 1.67 onwards, the `#[must_use]` attribute also applies to the `Future::Output` (rust-lang/rust#100633). So the lint `double_must_use` was linting all async functions. This PR changes the `double_must_use` lint so it ignores `async` functions. --- Closes #10486 changelog: [`double_must_use`]: Fix false positive in async function
This commit is contained in:
commit
85d9f176b7
@ -1,7 +1,9 @@
|
||||
use hir::FnSig;
|
||||
use rustc_ast::ast::Attribute;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def_id::DefIdSet;
|
||||
use rustc_hir::{self as hir, def::Res, QPath};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::{
|
||||
lint::in_external_macro,
|
||||
@ -27,7 +29,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>
|
||||
let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
||||
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
|
||||
if let Some(attr) = attr {
|
||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
|
||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, sig);
|
||||
} else if is_public && !is_proc_macro(attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
|
||||
check_must_use_candidate(
|
||||
cx,
|
||||
@ -49,7 +51,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
|
||||
if let Some(attr) = attr {
|
||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
|
||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, sig);
|
||||
} else if is_public && !is_proc_macro(attrs) && trait_ref_of_method(cx, item.owner_id.def_id).is_none() {
|
||||
check_must_use_candidate(
|
||||
cx,
|
||||
@ -72,7 +74,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
|
||||
if let Some(attr) = attr {
|
||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
|
||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, sig);
|
||||
} else if let hir::TraitFn::Provided(eid) = *eid {
|
||||
let body = cx.tcx.hir().body(eid);
|
||||
if attr.is_none() && is_public && !is_proc_macro(attrs) {
|
||||
@ -97,6 +99,7 @@ fn check_needless_must_use(
|
||||
item_span: Span,
|
||||
fn_header_span: Span,
|
||||
attr: &Attribute,
|
||||
sig: &FnSig<'_>,
|
||||
) {
|
||||
if in_external_macro(cx.sess(), item_span) {
|
||||
return;
|
||||
@ -112,6 +115,15 @@ fn check_needless_must_use(
|
||||
},
|
||||
);
|
||||
} else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) {
|
||||
// Ignore async functions unless Future::Output type is a must_use type
|
||||
if sig.header.is_async() {
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
if let Some(future_ty) = infcx.get_impl_future_output_ty(return_ty(cx, item_id))
|
||||
&& !is_must_use_ty(cx, future_ty) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
DOUBLE_MUST_USE,
|
||||
|
@ -21,6 +21,17 @@ pub fn must_use_with_note() -> Result<(), ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
// vvvv Should not lint (#10486)
|
||||
#[must_use]
|
||||
async fn async_must_use() -> usize {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
async fn async_must_use_result() -> Result<(), ()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
must_use_result();
|
||||
must_use_tuple();
|
||||
|
@ -23,5 +23,13 @@ LL | pub fn must_use_array() -> [Result<(), ()>; 1] {
|
||||
|
|
||||
= help: either add some descriptive text or remove the attribute
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`
|
||||
--> $DIR/double_must_use.rs:31:1
|
||||
|
|
||||
LL | async fn async_must_use_result() -> Result<(), ()> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: either add some descriptive text or remove the attribute
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user