Skip to content

Commit 3e8f32e

Browse files
committed
Auto merge of #89263 - TaKO8Ki:suggest-both-immutable-and-mutable-trait-implementations, r=estebank
Suggest both of immutable and mutable trait implementations closes #85865
2 parents 583437a + 3bab363 commit 3e8f32e

12 files changed

+211
-92
lines changed

Diff for: compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+34-32
Original file line numberDiff line numberDiff line change
@@ -714,22 +714,28 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
714714
let mut_substs = self.tcx.mk_substs_trait(mut_borrowed_found_ty, &[]);
715715

716716
// Try to apply the original trait binding obligation by borrowing.
717-
let mut try_borrowing = |new_trait_ref: ty::TraitRef<'tcx>,
717+
let mut try_borrowing = |new_imm_trait_ref: ty::TraitRef<'tcx>,
718+
new_mut_trait_ref: ty::TraitRef<'tcx>,
718719
expected_trait_ref: ty::TraitRef<'tcx>,
719-
mtbl: bool,
720720
blacklist: &[DefId]|
721721
-> bool {
722722
if blacklist.contains(&expected_trait_ref.def_id) {
723723
return false;
724724
}
725725

726-
let new_obligation = Obligation::new(
726+
let imm_result = self.predicate_must_hold_modulo_regions(&Obligation::new(
727727
ObligationCause::dummy(),
728728
param_env,
729-
ty::Binder::dummy(new_trait_ref).without_const().to_predicate(self.tcx),
730-
);
729+
ty::Binder::dummy(new_imm_trait_ref).without_const().to_predicate(self.tcx),
730+
));
731731

732-
if self.predicate_must_hold_modulo_regions(&new_obligation) {
732+
let mut_result = self.predicate_must_hold_modulo_regions(&Obligation::new(
733+
ObligationCause::dummy(),
734+
param_env,
735+
ty::Binder::dummy(new_mut_trait_ref).without_const().to_predicate(self.tcx),
736+
));
737+
738+
if imm_result || mut_result {
733739
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
734740
// We have a very specific type of error, where just borrowing this argument
735741
// might solve the problem. In cases like this, the important part is the
@@ -773,15 +779,24 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
773779
// }
774780
// ```
775781

776-
err.span_suggestion(
777-
span,
778-
&format!(
779-
"consider{} borrowing here",
780-
if mtbl { " mutably" } else { "" }
781-
),
782-
format!("&{}{}", if mtbl { "mut " } else { "" }, snippet),
783-
Applicability::MaybeIncorrect,
784-
);
782+
if imm_result && mut_result {
783+
err.span_suggestions(
784+
span.shrink_to_lo(),
785+
"consider borrowing here",
786+
["&".to_string(), "&mut ".to_string()].into_iter(),
787+
Applicability::MaybeIncorrect,
788+
);
789+
} else {
790+
err.span_suggestion_verbose(
791+
span.shrink_to_lo(),
792+
&format!(
793+
"consider{} borrowing here",
794+
if mut_result { " mutably" } else { "" }
795+
),
796+
format!("&{}", if mut_result { "mut " } else { "" }),
797+
Applicability::MaybeIncorrect,
798+
);
799+
}
785800
}
786801
return true;
787802
}
@@ -795,29 +810,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
795810
ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs);
796811
let new_mut_trait_ref =
797812
ty::TraitRef::new(obligation.parent_trait_ref.def_id(), mut_substs);
798-
if try_borrowing(new_imm_trait_ref, expected_trait_ref, false, &[]) {
799-
return true;
800-
} else {
801-
return try_borrowing(new_mut_trait_ref, expected_trait_ref, true, &[]);
802-
}
813+
return try_borrowing(new_imm_trait_ref, new_mut_trait_ref, expected_trait_ref, &[]);
803814
} else if let ObligationCauseCode::BindingObligation(_, _)
804815
| ObligationCauseCode::ItemObligation(_) = &*code
805816
{
806-
if try_borrowing(
817+
return try_borrowing(
807818
ty::TraitRef::new(trait_ref.def_id, imm_substs),
819+
ty::TraitRef::new(trait_ref.def_id, mut_substs),
808820
trait_ref,
809-
false,
810821
&never_suggest_borrow[..],
811-
) {
812-
return true;
813-
} else {
814-
return try_borrowing(
815-
ty::TraitRef::new(trait_ref.def_id, mut_substs),
816-
trait_ref,
817-
true,
818-
&never_suggest_borrow[..],
819-
);
820-
}
822+
);
821823
} else {
822824
false
823825
}

Diff for: src/test/ui/derives/deriving-copyclone.stderr

+18-12
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ error[E0277]: the trait bound `C: Copy` is not satisfied
22
--> $DIR/deriving-copyclone.rs:31:13
33
|
44
LL | is_copy(B { a: 1, b: C });
5-
| ------- ^^^^^^^^^^^^^^^^
6-
| | |
7-
| | expected an implementor of trait `Copy`
8-
| | help: consider borrowing here: `&B { a: 1, b: C }`
5+
| ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Copy`
6+
| |
97
| required by a bound introduced by this call
108
|
119
note: required because of the requirements on the impl of `Copy` for `B<C>`
@@ -19,15 +17,17 @@ note: required by a bound in `is_copy`
1917
LL | fn is_copy<T: Copy>(_: T) {}
2018
| ^^^^ required by this bound in `is_copy`
2119
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
20+
help: consider borrowing here
21+
|
22+
LL | is_copy(&B { a: 1, b: C });
23+
| +
2224

2325
error[E0277]: the trait bound `C: Clone` is not satisfied
2426
--> $DIR/deriving-copyclone.rs:32:14
2527
|
2628
LL | is_clone(B { a: 1, b: C });
27-
| -------- ^^^^^^^^^^^^^^^^
28-
| | |
29-
| | expected an implementor of trait `Clone`
30-
| | help: consider borrowing here: `&B { a: 1, b: C }`
29+
| -------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Clone`
30+
| |
3131
| required by a bound introduced by this call
3232
|
3333
note: required because of the requirements on the impl of `Clone` for `B<C>`
@@ -41,15 +41,17 @@ note: required by a bound in `is_clone`
4141
LL | fn is_clone<T: Clone>(_: T) {}
4242
| ^^^^^ required by this bound in `is_clone`
4343
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
44+
help: consider borrowing here
45+
|
46+
LL | is_clone(&B { a: 1, b: C });
47+
| +
4448

4549
error[E0277]: the trait bound `D: Copy` is not satisfied
4650
--> $DIR/deriving-copyclone.rs:35:13
4751
|
4852
LL | is_copy(B { a: 1, b: D });
49-
| ------- ^^^^^^^^^^^^^^^^
50-
| | |
51-
| | expected an implementor of trait `Copy`
52-
| | help: consider borrowing here: `&B { a: 1, b: D }`
53+
| ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Copy`
54+
| |
5355
| required by a bound introduced by this call
5456
|
5557
note: required because of the requirements on the impl of `Copy` for `B<D>`
@@ -63,6 +65,10 @@ note: required by a bound in `is_copy`
6365
LL | fn is_copy<T: Copy>(_: T) {}
6466
| ^^^^ required by this bound in `is_copy`
6567
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
68+
help: consider borrowing here
69+
|
70+
LL | is_copy(&B { a: 1, b: D });
71+
| +
6672

6773
error: aborting due to 3 previous errors
6874

Diff for: src/test/ui/issues/issue-20605.stderr

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ error[E0277]: the size for values of type `dyn Iterator<Item = &'a mut u8>` cann
22
--> $DIR/issue-20605.rs:2:17
33
|
44
LL | for item in *things { *item = 0 }
5-
| ^^^^^^^
6-
| |
7-
| expected an implementor of trait `IntoIterator`
8-
| help: consider mutably borrowing here: `&mut *things`
5+
| ^^^^^^^ expected an implementor of trait `IntoIterator`
96
|
107
= note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
118
= note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator<Item = &'a mut u8>`
@@ -14,6 +11,10 @@ note: required by `into_iter`
1411
|
1512
LL | fn into_iter(self) -> Self::IntoIter;
1613
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
help: consider mutably borrowing here
15+
|
16+
LL | for item in &mut *things { *item = 0 }
17+
| ++++
1718

1819
error: aborting due to previous error
1920

Diff for: src/test/ui/suggestions/imm-ref-trait-object-literal.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,19 @@ error[E0277]: the trait bound `S: Trait` is not satisfied
2222
--> $DIR/imm-ref-trait-object-literal.rs:13:7
2323
|
2424
LL | foo(s);
25-
| --- ^
26-
| | |
27-
| | expected an implementor of trait `Trait`
28-
| | help: consider mutably borrowing here: `&mut s`
25+
| --- ^ expected an implementor of trait `Trait`
26+
| |
2927
| required by a bound introduced by this call
3028
|
3129
note: required by a bound in `foo`
3230
--> $DIR/imm-ref-trait-object-literal.rs:7:11
3331
|
3432
LL | fn foo<X: Trait>(_: X) {}
3533
| ^^^^^ required by this bound in `foo`
34+
help: consider mutably borrowing here
35+
|
36+
LL | foo(&mut s);
37+
| ++++
3638

3739
error: aborting due to 2 previous errors
3840

Diff for: src/test/ui/suggestions/issue-62843.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ error[E0277]: expected a `FnMut<(char,)>` closure, found `String`
22
--> $DIR/issue-62843.rs:4:32
33
|
44
LL | println!("{:?}", line.find(pattern));
5-
| ---- ^^^^^^^
6-
| | |
7-
| | expected an implementor of trait `Pattern<'_>`
8-
| | help: consider borrowing here: `&pattern`
5+
| ---- ^^^^^^^ expected an implementor of trait `Pattern<'_>`
6+
| |
97
| required by a bound introduced by this call
108
|
119
= note: the trait bound `String: Pattern<'_>` is not satisfied
1210
= note: required because of the requirements on the impl of `Pattern<'_>` for `String`
11+
help: consider borrowing here
12+
|
13+
LL | println!("{:?}", line.find(&pattern));
14+
| +
1315

1416
error: aborting due to previous error
1517

Diff for: src/test/ui/suggestions/issue-84973-2.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@ error[E0277]: the trait bound `i32: Tr` is not satisfied
22
--> $DIR/issue-84973-2.rs:11:9
33
|
44
LL | foo(a);
5-
| --- ^
6-
| | |
7-
| | expected an implementor of trait `Tr`
8-
| | help: consider mutably borrowing here: `&mut a`
5+
| --- ^ expected an implementor of trait `Tr`
6+
| |
97
| required by a bound introduced by this call
108
|
119
note: required by a bound in `foo`
1210
--> $DIR/issue-84973-2.rs:7:11
1311
|
1412
LL | fn foo<T: Tr>(i: T) {}
1513
| ^^ required by this bound in `foo`
14+
help: consider mutably borrowing here
15+
|
16+
LL | foo(&mut a);
17+
| ++++
1618

1719
error: aborting due to previous error
1820

Diff for: src/test/ui/suggestions/issue-84973-negative.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@ error[E0277]: the trait bound `f32: Tr` is not satisfied
1616
--> $DIR/issue-84973-negative.rs:11:9
1717
|
1818
LL | bar(b);
19-
| --- ^
20-
| | |
21-
| | expected an implementor of trait `Tr`
22-
| | help: consider borrowing here: `&b`
19+
| --- ^ expected an implementor of trait `Tr`
20+
| |
2321
| required by a bound introduced by this call
2422
|
2523
note: required by a bound in `bar`
2624
--> $DIR/issue-84973-negative.rs:5:11
2725
|
2826
LL | fn bar<T: Tr>(t: T) {}
2927
| ^^ required by this bound in `bar`
28+
help: consider borrowing here
29+
|
30+
LL | bar(&b);
31+
| +
3032

3133
error: aborting due to 2 previous errors
3234

Diff for: src/test/ui/suggestions/issue-84973.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@ error[E0277]: the trait bound `Fancy: SomeTrait` is not satisfied
22
--> $DIR/issue-84973.rs:6:24
33
|
44
LL | let o = Other::new(f);
5-
| ---------- ^
6-
| | |
7-
| | expected an implementor of trait `SomeTrait`
8-
| | help: consider borrowing here: `&f`
5+
| ---------- ^ expected an implementor of trait `SomeTrait`
6+
| |
97
| required by a bound introduced by this call
108
|
119
note: required by `Other::<'a, G>::new`
1210
--> $DIR/issue-84973.rs:27:5
1311
|
1412
LL | pub fn new(g: G) -> Self {
1513
| ^^^^^^^^^^^^^^^^^^^^^^^^
14+
help: consider borrowing here
15+
|
16+
LL | let o = Other::new(&f);
17+
| +
1618

1719
error: aborting due to previous error
1820

0 commit comments

Comments
 (0)