Skip to content

Commit 7f02896

Browse files
authoredAug 20, 2022
Rollup merge of #100769 - TaKO8Ki:suggest-adding-reference-to-trait-assoc-item, r=cjgillot
Suggest adding a reference to a trait assoc item fixes #100289
2 parents aaa5574 + a311b8a commit 7f02896

File tree

4 files changed

+80
-7
lines changed

4 files changed

+80
-7
lines changed
 

‎compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+25-7
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
882882
obligation.cause.code()
883883
{
884884
&parent_code
885+
} else if let ObligationCauseCode::ItemObligation(_) = obligation.cause.code() {
886+
obligation.cause.code()
885887
} else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) =
886888
span.ctxt().outer_expn_data().kind
887889
{
@@ -930,10 +932,25 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
930932
self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty);
931933
self.predicate_must_hold_modulo_regions(&obligation)
932934
};
933-
let imm_result = mk_result(trait_pred_and_imm_ref);
934-
let mut_result = mk_result(trait_pred_and_mut_ref);
935+
let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
936+
let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
937+
938+
let (ref_inner_ty_satisfies_pred, ref_inner_ty_mut) =
939+
if let ObligationCauseCode::ItemObligation(_) = obligation.cause.code()
940+
&& let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind()
941+
{
942+
(
943+
mk_result(old_pred.map_bound(|trait_pred| (trait_pred, *ty))),
944+
matches!(mutability, hir::Mutability::Mut),
945+
)
946+
} else {
947+
(false, false)
948+
};
935949

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

976-
if imm_result && mut_result {
993+
if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
977994
err.span_suggestions(
978995
span.shrink_to_lo(),
979996
"consider borrowing here",
980997
["&".to_string(), "&mut ".to_string()].into_iter(),
981998
Applicability::MaybeIncorrect,
982999
);
9831000
} else {
1001+
let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
9841002
err.span_suggestion_verbose(
9851003
span.shrink_to_lo(),
9861004
&format!(
9871005
"consider{} borrowing here",
988-
if mut_result { " mutably" } else { "" }
1006+
if is_mut { " mutably" } else { "" }
9891007
),
990-
format!("&{}", if mut_result { "mut " } else { "" }),
1008+
format!("&{}", if is_mut { "mut " } else { "" }),
9911009
Applicability::MaybeIncorrect,
9921010
);
9931011
}
@@ -1001,7 +1019,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
10011019
if let ObligationCauseCode::ImplDerivedObligation(cause) = &*code {
10021020
try_borrowing(cause.derived.parent_trait_pred, &[])
10031021
} else if let ObligationCauseCode::BindingObligation(_, _)
1004-
| ObligationCauseCode::ItemObligation(_) = code
1022+
| ObligationCauseCode::ItemObligation(..) = code
10051023
{
10061024
try_borrowing(poly_trait_pred, &never_suggest_borrow)
10071025
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
#![allow(unused_variables)]
3+
4+
fn foo(foo: &mut usize) {
5+
todo!()
6+
}
7+
8+
fn bar(bar: &usize) {
9+
todo!()
10+
}
11+
12+
fn main() {
13+
foo(&mut Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied
14+
bar(&Default::default()); //~ the trait bound `&usize: Default` is not satisfied
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
#![allow(unused_variables)]
3+
4+
fn foo(foo: &mut usize) {
5+
todo!()
6+
}
7+
8+
fn bar(bar: &usize) {
9+
todo!()
10+
}
11+
12+
fn main() {
13+
foo(Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied
14+
bar(Default::default()); //~ the trait bound `&usize: Default` is not satisfied
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0277]: the trait bound `&mut usize: Default` is not satisfied
2+
--> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:13:9
3+
|
4+
LL | foo(Default::default());
5+
| ^^^^^^^^^^^^^^^^ expected an implementor of trait `Default`
6+
|
7+
help: consider mutably borrowing here
8+
|
9+
LL | foo(&mut Default::default());
10+
| ++++
11+
12+
error[E0277]: the trait bound `&usize: Default` is not satisfied
13+
--> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:14:9
14+
|
15+
LL | bar(Default::default());
16+
| ^^^^^^^^^^^^^^^^ expected an implementor of trait `Default`
17+
|
18+
help: consider borrowing here
19+
|
20+
LL | bar(&Default::default());
21+
| +
22+
23+
error: aborting due to 2 previous errors
24+
25+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)
Please sign in to comment.