Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest adding a reference to a trait assoc item #100769

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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`.