1
Fork 0

Add async_fn_in_trait lint

This commit is contained in:
Michael Goulet 2023-09-26 20:20:21 +00:00
parent 2e5a9dd6c9
commit ec79720c1e
7 changed files with 186 additions and 53 deletions

View file

@ -0,0 +1,58 @@
use crate::lints::AsyncFnInTraitDiag;
use crate::LateContext;
use crate::LateLintPass;
use rustc_hir as hir;
use rustc_trait_selection::traits::error_reporting::suggestions::suggest_desugaring_async_fn_to_impl_future_in_trait;
declare_lint! {
/// TODO
///
/// ### Example
///
/// ```rust
/// fn foo<T: Drop>() {}
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// TODO
pub ASYNC_FN_IN_TRAIT,
Warn,
"TODO"
}
declare_lint_pass!(
// TODO:
AsyncFnInTrait => [ASYNC_FN_IN_TRAIT]
);
impl<'tcx> LateLintPass<'tcx> for AsyncFnInTrait {
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'tcx>) {
if let hir::TraitItemKind::Fn(sig, body) = item.kind
&& let hir::IsAsync::Async(async_span) = sig.header.asyncness
{
if cx.tcx.features().return_type_notation {
return;
}
let hir::FnRetTy::Return(hir::Ty { kind: hir::TyKind::OpaqueDef(def, ..), .. }) =
sig.decl.output
else {
// This should never happen, but let's not ICE.
return;
};
let sugg = suggest_desugaring_async_fn_to_impl_future_in_trait(
cx.tcx,
sig,
body,
def.owner_id.def_id,
" + Send",
);
cx.tcx.emit_spanned_lint(ASYNC_FN_IN_TRAIT, item.hir_id(), async_span, AsyncFnInTraitDiag {
sugg
});
}
}
}

View file

@ -50,6 +50,7 @@ extern crate rustc_session;
extern crate tracing;
mod array_into_iter;
mod async_fn_in_trait;
pub mod builtin;
mod context;
mod deref_into_dyn_supertrait;
@ -96,6 +97,7 @@ use rustc_session::lint::builtin::{
};
use array_into_iter::ArrayIntoIter;
use async_fn_in_trait::AsyncFnInTrait;
use builtin::*;
use deref_into_dyn_supertrait::*;
use drop_forget_useless::*;
@ -234,6 +236,7 @@ late_lint_methods!(
MapUnitFn: MapUnitFn,
MissingDebugImplementations: MissingDebugImplementations,
MissingDoc: MissingDoc,
AsyncFnInTrait: AsyncFnInTrait,
]
]
);

View file

@ -1818,3 +1818,24 @@ pub struct UnusedAllocationDiag;
#[derive(LintDiagnostic)]
#[diag(lint_unused_allocation_mut)]
pub struct UnusedAllocationMutDiag;
pub struct AsyncFnInTraitDiag {
pub sugg: Option<Vec<(Span, String)>>,
}
impl<'a> DecorateLint<'a, ()> for AsyncFnInTraitDiag {
fn decorate_lint<'b>(
self,
diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
diag.note(fluent::lint_note);
if let Some(sugg) = self.sugg {
diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect);
}
diag
}
fn msg(&self) -> rustc_errors::DiagnosticMessage {
fluent::lint_async_fn_in_trait
}
}