Suggest derivable trait on E0277

This commit is contained in:
ohno418 2022-03-31 23:58:45 +09:00
parent 60e50fc1cf
commit 0d2a00058b
62 changed files with 310 additions and 0 deletions

View file

@ -536,6 +536,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
);
self.note_version_mismatch(&mut err, &trait_ref);
self.suggest_remove_await(&obligation, &mut err);
self.suggest_derive(&mut err, trait_predicate);
if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() {
self.suggest_await_before_try(

View file

@ -189,6 +189,8 @@ pub trait InferCtxtExt<'tcx> {
err: &mut Diagnostic,
trait_ref: &ty::PolyTraitRef<'tcx>,
);
fn suggest_derive(&self, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>);
}
fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) {
@ -2589,6 +2591,39 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
_ => {}
}
}
fn suggest_derive(&self, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>) {
if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
let adt = match trait_pred.skip_binder().self_ty().ty_adt_def() {
Some(adt) if adt.did().is_local() => adt,
_ => return,
};
let can_derive = match diagnostic_name {
sym::Default => !adt.is_enum(),
sym::Eq
| sym::PartialEq
| sym::Ord
| sym::PartialOrd
| sym::Clone
| sym::Copy
| sym::Hash
| sym::Debug => true,
_ => false,
};
if can_derive {
err.span_suggestion_verbose(
self.tcx.def_span(adt.did()).shrink_to_lo(),
&format!(
"consider annotating `{}` with `#[derive({})]`",
trait_pred.skip_binder().self_ty().to_string(),
diagnostic_name.to_string(),
),
format!("#[derive({})]\n", diagnostic_name.to_string()),
Applicability::MaybeIncorrect,
);
}
}
}
}
/// Collect all the returned expressions within the input expression.