Skip to content

Commit

Permalink
Rollup merge of #100769 - TaKO8Ki:suggest-adding-reference-to-trait-a…
Browse files Browse the repository at this point in the history
…ssoc-item, r=cjgillot

Suggest adding a reference to a trait assoc item

fixes #100289
  • Loading branch information
matthiaskrgr authored Aug 20, 2022
2 parents aaa5574 + a311b8a commit 7f02896
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
obligation.cause.code()
{
&parent_code
} else if let ObligationCauseCode::ItemObligation(_) = obligation.cause.code() {
obligation.cause.code()
} else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) =
span.ctxt().outer_expn_data().kind
{
Expand Down Expand Up @@ -930,10 +932,25 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty);
self.predicate_must_hold_modulo_regions(&obligation)
};
let imm_result = mk_result(trait_pred_and_imm_ref);
let mut_result = mk_result(trait_pred_and_mut_ref);
let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);

let (ref_inner_ty_satisfies_pred, ref_inner_ty_mut) =
if let ObligationCauseCode::ItemObligation(_) = obligation.cause.code()
&& let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind()
{
(
mk_result(old_pred.map_bound(|trait_pred| (trait_pred, *ty))),
matches!(mutability, hir::Mutability::Mut),
)
} else {
(false, false)
};

if imm_result || mut_result {
if imm_ref_self_ty_satisfies_pred
|| mut_ref_self_ty_satisfies_pred
|| ref_inner_ty_satisfies_pred
{
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
// We have a very specific type of error, where just borrowing this argument
// might solve the problem. In cases like this, the important part is the
Expand Down Expand Up @@ -973,21 +990,22 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// }
// ```

if imm_result && mut_result {
if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
err.span_suggestions(
span.shrink_to_lo(),
"consider borrowing here",
["&".to_string(), "&mut ".to_string()].into_iter(),
Applicability::MaybeIncorrect,
);
} else {
let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
err.span_suggestion_verbose(
span.shrink_to_lo(),
&format!(
"consider{} borrowing here",
if mut_result { " mutably" } else { "" }
if is_mut { " mutably" } else { "" }
),
format!("&{}", if mut_result { "mut " } else { "" }),
format!("&{}", if is_mut { "mut " } else { "" }),
Applicability::MaybeIncorrect,
);
}
Expand All @@ -1001,7 +1019,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
if let ObligationCauseCode::ImplDerivedObligation(cause) = &*code {
try_borrowing(cause.derived.parent_trait_pred, &[])
} else if let ObligationCauseCode::BindingObligation(_, _)
| ObligationCauseCode::ItemObligation(_) = code
| ObligationCauseCode::ItemObligation(..) = code
{
try_borrowing(poly_trait_pred, &never_suggest_borrow)
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// run-rustfix
#![allow(unused_variables)]

fn foo(foo: &mut usize) {
todo!()
}

fn bar(bar: &usize) {
todo!()
}

fn main() {
foo(&mut Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied
bar(&Default::default()); //~ the trait bound `&usize: Default` is not satisfied
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// run-rustfix
#![allow(unused_variables)]

fn foo(foo: &mut usize) {
todo!()
}

fn bar(bar: &usize) {
todo!()
}

fn main() {
foo(Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied
bar(Default::default()); //~ the trait bound `&usize: Default` is not satisfied
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
error[E0277]: the trait bound `&mut usize: Default` is not satisfied
--> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:13:9
|
LL | foo(Default::default());
| ^^^^^^^^^^^^^^^^ expected an implementor of trait `Default`
|
help: consider mutably borrowing here
|
LL | foo(&mut Default::default());
| ++++

error[E0277]: the trait bound `&usize: Default` is not satisfied
--> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:14:9
|
LL | bar(Default::default());
| ^^^^^^^^^^^^^^^^ expected an implementor of trait `Default`
|
help: consider borrowing here
|
LL | bar(&Default::default());
| +

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.

0 comments on commit 7f02896

Please sign in to comment.