Ensure async trait impls are async (or otherwise return an opaque type)
As a workaround for the full `#[refine]` semantics not being implemented yet, forbit returning a concrete future type like `Box<dyn Future>` or a manually implemented Future. `-> impl Future` is still permitted; while that can also cause accidental refinement, that's behind a different feature gate (`return_position_impl_trait_in_trait`) and that problem exists regardless of whether the trait method is async, so will have to be solved more generally. Fixes #102745
This commit is contained in:
parent
b70baa4f92
commit
da98ef9a5d
12 changed files with 146 additions and 25 deletions
|
@ -67,6 +67,10 @@ pub(crate) fn compare_impl_method<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
if let Err(_) = compare_asyncness(tcx, impl_m, impl_m_span, trait_m, trait_item_span) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
|
||||
{
|
||||
return;
|
||||
|
@ -323,6 +327,34 @@ fn compare_predicate_entailment<'tcx>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn compare_asyncness<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_m: &ty::AssocItem,
|
||||
impl_m_span: Span,
|
||||
trait_m: &ty::AssocItem,
|
||||
trait_item_span: Option<Span>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async {
|
||||
match tcx.fn_sig(impl_m.def_id).skip_binder().output().kind() {
|
||||
ty::Alias(ty::Opaque, ..) => {
|
||||
// allow both `async fn foo()` and `fn foo() -> impl Future`
|
||||
}
|
||||
ty::Error(rustc_errors::ErrorGuaranteed { .. }) => {
|
||||
// We don't know if it's ok, but at least it's already an error.
|
||||
}
|
||||
_ => {
|
||||
return Err(tcx.sess.emit_err(crate::errors::AsyncTraitImplShouldBeAsync {
|
||||
span: impl_m_span,
|
||||
method_name: trait_m.name,
|
||||
trait_item_span,
|
||||
}));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(tcx), level = "debug", ret)]
|
||||
pub fn collect_trait_impl_trait_tys<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
|
|
@ -51,6 +51,17 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
|
|||
pub ident: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_async_trait_impl_should_be_async)]
|
||||
pub struct AsyncTraitImplShouldBeAsync {
|
||||
#[primary_span]
|
||||
// #[label]
|
||||
pub span: Span,
|
||||
#[label(trait_item_label)]
|
||||
pub trait_item_span: Option<Span>,
|
||||
pub method_name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_drop_impl_on_wrong_item, code = "E0120")]
|
||||
pub struct DropImplOnWrongItem {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue