Suggest only when all fields impl the trait
This commit is contained in:
parent
0ff2f58330
commit
de237823e0
4 changed files with 50 additions and 26 deletions
|
@ -536,7 +536,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
self.note_version_mismatch(&mut err, &trait_ref);
|
self.note_version_mismatch(&mut err, &trait_ref);
|
||||||
self.suggest_remove_await(&obligation, &mut err);
|
self.suggest_remove_await(&obligation, &mut err);
|
||||||
self.suggest_derive(&mut err, trait_predicate);
|
self.suggest_derive(&obligation, &mut err, trait_predicate);
|
||||||
|
|
||||||
if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() {
|
if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() {
|
||||||
self.suggest_await_before_try(
|
self.suggest_await_before_try(
|
||||||
|
|
|
@ -190,7 +190,12 @@ pub trait InferCtxtExt<'tcx> {
|
||||||
trait_ref: &ty::PolyTraitRef<'tcx>,
|
trait_ref: &ty::PolyTraitRef<'tcx>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn suggest_derive(&self, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>);
|
fn suggest_derive(
|
||||||
|
&self,
|
||||||
|
obligation: &PredicateObligation<'tcx>,
|
||||||
|
err: &mut Diagnostic,
|
||||||
|
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) {
|
fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) {
|
||||||
|
@ -2592,33 +2597,60 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suggest_derive(&self, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>) {
|
fn suggest_derive(
|
||||||
|
&self,
|
||||||
|
obligation: &PredicateObligation<'tcx>,
|
||||||
|
err: &mut Diagnostic,
|
||||||
|
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||||
|
) {
|
||||||
let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
|
let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(self_ty) = trait_pred.self_ty().no_bound_vars() else {
|
let (adt, substs) = match trait_pred.skip_binder().self_ty().kind() {
|
||||||
return;
|
ty::Adt(adt, substs) if adt.did().is_local() => (adt, substs),
|
||||||
};
|
|
||||||
|
|
||||||
let adt = match self_ty.ty_adt_def() {
|
|
||||||
Some(adt) if adt.did().is_local() => adt,
|
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let can_derive = match diagnostic_name {
|
let can_derive = {
|
||||||
|
let is_derivable_trait = match diagnostic_name {
|
||||||
sym::Default => !adt.is_enum(),
|
sym::Default => !adt.is_enum(),
|
||||||
sym::PartialEq | sym::PartialOrd => {
|
sym::PartialEq | sym::PartialOrd => {
|
||||||
let rhs_ty = trait_pred.skip_binder().trait_ref.substs.type_at(1);
|
let rhs_ty = trait_pred.skip_binder().trait_ref.substs.type_at(1);
|
||||||
self_ty == rhs_ty
|
trait_pred.skip_binder().self_ty() == rhs_ty
|
||||||
}
|
}
|
||||||
sym::Eq | sym::Ord | sym::Clone | sym::Copy | sym::Hash | sym::Debug => true,
|
sym::Eq | sym::Ord | sym::Clone | sym::Copy | sym::Hash | sym::Debug => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
is_derivable_trait &&
|
||||||
|
// Ensure all fields impl the trait.
|
||||||
|
adt.all_fields().all(|field| {
|
||||||
|
let field_ty = field.ty(self.tcx, substs);
|
||||||
|
let trait_substs = match diagnostic_name {
|
||||||
|
sym::PartialEq | sym::PartialOrd => {
|
||||||
|
self.tcx.mk_substs_trait(field_ty, &[field_ty.into()])
|
||||||
|
}
|
||||||
|
_ => self.tcx.mk_substs_trait(field_ty, &[]),
|
||||||
|
};
|
||||||
|
let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitPredicate {
|
||||||
|
trait_ref: ty::TraitRef {
|
||||||
|
substs: trait_substs,
|
||||||
|
..trait_pred.skip_binder().trait_ref
|
||||||
|
},
|
||||||
|
..*tr
|
||||||
|
});
|
||||||
|
let field_obl = Obligation::new(
|
||||||
|
obligation.cause.clone(),
|
||||||
|
obligation.param_env,
|
||||||
|
trait_pred.to_predicate(self.tcx),
|
||||||
|
);
|
||||||
|
self.predicate_must_hold_modulo_regions(&field_obl)
|
||||||
|
})
|
||||||
|
};
|
||||||
if can_derive {
|
if can_derive {
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
self.tcx.def_span(adt.did()).shrink_to_lo(),
|
self.tcx.def_span(adt.did()).shrink_to_lo(),
|
||||||
&format!(
|
&format!(
|
||||||
"consider annotating `{}` with `#[derive({})]`",
|
"consider annotating `{}` with `#[derive({})]`",
|
||||||
trait_pred.skip_binder().self_ty().to_string(),
|
trait_pred.skip_binder().self_ty(),
|
||||||
diagnostic_name.to_string(),
|
diagnostic_name.to_string(),
|
||||||
),
|
),
|
||||||
format!("#[derive({})]\n", diagnostic_name.to_string()),
|
format!("#[derive({})]\n", diagnostic_name.to_string()),
|
||||||
|
|
|
@ -7,10 +7,6 @@ LL | [Foo(String::new()); 4];
|
||||||
= help: the following implementations were found:
|
= help: the following implementations were found:
|
||||||
<Foo<T> as Copy>
|
<Foo<T> as Copy>
|
||||||
= note: the `Copy` trait is required because the repeated element will be copied
|
= note: the `Copy` trait is required because the repeated element will be copied
|
||||||
help: consider annotating `Foo<String>` with `#[derive(Copy)]`
|
|
||||||
|
|
|
||||||
LL | #[derive(Copy)]
|
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -129,10 +129,6 @@ note: required by a bound in `assert_copy`
|
||||||
|
|
|
|
||||||
LL | fn assert_copy<T:Copy>() { }
|
LL | fn assert_copy<T:Copy>() { }
|
||||||
| ^^^^ required by this bound in `assert_copy`
|
| ^^^^ required by this bound in `assert_copy`
|
||||||
help: consider annotating `MyNoncopyStruct` with `#[derive(Copy)]`
|
|
||||||
|
|
|
||||||
LL | #[derive(Copy)]
|
|
||||||
|
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `Rc<isize>: Copy` is not satisfied
|
error[E0277]: the trait bound `Rc<isize>: Copy` is not satisfied
|
||||||
--> $DIR/kindck-copy.rs:67:19
|
--> $DIR/kindck-copy.rs:67:19
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue