Skip to content

Commit 82cb9ee

Browse files
authored
Rollup merge of rust-lang#102813 - Akida31:issue-64915/simpler_diagnostic_when_passing_arg_to_closure_and_missing_borrow, r=estebank
Simpler diagnostic when passing arg to closure and missing borrow fixes rust-lang#64915 I followed roughly the instructions and the older PR rust-lang#76362. The number of references for the expected and the found types will be compared and depending on which has more the diagnostic will be emitted. I'm not quite sure if my approach with the many `span_bug!`s is good, it could lead to some ICEs. Would it be better if those errors are ignored? As far as I know the following code works similarly but in a different context. Is this probably reusable since it looks like it would emit better diagnostics? https://github.com/rust-lang/rust/blob/a688a0305fad9219505a8f2576446510601bafe8/compiler/rustc_hir_analysis/src/check/demand.rs#L713-L1061 When running the tests locally, a codegen test failed. Is there something I can/ should do about that? If you have some improvements/ corrections please say so and I will happily include them. r? `@estebank` (as you added the mentoring instructions to the issue)
2 parents c6251c9 + 0f5409b commit 82cb9ee

File tree

6 files changed

+153
-0
lines changed

6 files changed

+153
-0
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
12071207
_ => None,
12081208
};
12091209

1210+
let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did));
12101211
let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));
12111212

12121213
if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
@@ -1260,6 +1261,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
12601261
found_trait_ref,
12611262
expected_trait_ref,
12621263
obligation.cause.code(),
1264+
found_node,
12631265
)
12641266
} else {
12651267
let (closure_span, found) = found_did

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

+67
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ pub trait TypeErrCtxtExt<'tcx> {
257257
found: ty::PolyTraitRef<'tcx>,
258258
expected: ty::PolyTraitRef<'tcx>,
259259
cause: &ObligationCauseCode<'tcx>,
260+
found_node: Option<Node<'_>>,
260261
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
261262

262263
fn note_conflicting_closure_bounds(
@@ -1680,6 +1681,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
16801681
found: ty::PolyTraitRef<'tcx>,
16811682
expected: ty::PolyTraitRef<'tcx>,
16821683
cause: &ObligationCauseCode<'tcx>,
1684+
found_node: Option<Node<'_>>,
16831685
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
16841686
pub(crate) fn build_fn_sig_ty<'tcx>(
16851687
infcx: &InferCtxt<'tcx>,
@@ -1743,6 +1745,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
17431745

17441746
self.note_conflicting_closure_bounds(cause, &mut err);
17451747

1748+
if let Some(found_node) = found_node {
1749+
hint_missing_borrow(span, found_span, found, expected, found_node, &mut err);
1750+
}
1751+
17461752
err
17471753
}
17481754

@@ -3122,6 +3128,67 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
31223128
}
31233129
}
31243130

3131+
/// Add a hint to add a missing borrow or remove an unnecessary one.
3132+
fn hint_missing_borrow<'tcx>(
3133+
span: Span,
3134+
found_span: Span,
3135+
found: Ty<'tcx>,
3136+
expected: Ty<'tcx>,
3137+
found_node: Node<'_>,
3138+
err: &mut Diagnostic,
3139+
) {
3140+
let found_args = match found.kind() {
3141+
ty::FnPtr(f) => f.inputs().skip_binder().iter(),
3142+
kind => {
3143+
span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
3144+
}
3145+
};
3146+
let expected_args = match expected.kind() {
3147+
ty::FnPtr(f) => f.inputs().skip_binder().iter(),
3148+
kind => {
3149+
span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
3150+
}
3151+
};
3152+
3153+
let fn_decl = found_node
3154+
.fn_decl()
3155+
.unwrap_or_else(|| span_bug!(found_span, "found node must be a function"));
3156+
3157+
let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
3158+
3159+
fn get_deref_type_and_refs<'tcx>(mut ty: Ty<'tcx>) -> (Ty<'tcx>, usize) {
3160+
let mut refs = 0;
3161+
3162+
while let ty::Ref(_, new_ty, _) = ty.kind() {
3163+
ty = *new_ty;
3164+
refs += 1;
3165+
}
3166+
3167+
(ty, refs)
3168+
}
3169+
3170+
for ((found_arg, expected_arg), arg_span) in found_args.zip(expected_args).zip(arg_spans) {
3171+
let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
3172+
let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
3173+
3174+
if found_ty == expected_ty {
3175+
let hint = if found_refs < expected_refs {
3176+
"consider borrowing the argument"
3177+
} else if found_refs == expected_refs {
3178+
continue;
3179+
} else {
3180+
"do not borrow the argument"
3181+
};
3182+
err.span_suggestion_verbose(
3183+
arg_span,
3184+
hint,
3185+
expected_arg.to_string(),
3186+
Applicability::MaybeIncorrect,
3187+
);
3188+
}
3189+
}
3190+
}
3191+
31253192
/// Collect all the returned expressions within the input expression.
31263193
/// Used to point at the return spans when we want to suggest some change to them.
31273194
#[derive(Default)]

src/test/ui/anonymous-higher-ranked-lifetime.stderr

+72
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ note: required by a bound in `f1`
1313
|
1414
LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
1515
| ^^^^^^^^^^^^ required by this bound in `f1`
16+
help: consider borrowing the argument
17+
|
18+
LL | f1(|_: &(), _: ()| {});
19+
| ~~~
20+
help: consider borrowing the argument
21+
|
22+
LL | f1(|_: (), _: &()| {});
23+
| ~~~
1624

1725
error[E0631]: type mismatch in closure arguments
1826
--> $DIR/anonymous-higher-ranked-lifetime.rs:3:5
@@ -29,6 +37,14 @@ note: required by a bound in `f2`
2937
|
3038
LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
3139
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2`
40+
help: consider borrowing the argument
41+
|
42+
LL | f2(|_: &'a (), _: ()| {});
43+
| ~~~~~~
44+
help: consider borrowing the argument
45+
|
46+
LL | f2(|_: (), _: &()| {});
47+
| ~~~
3248

3349
error[E0631]: type mismatch in closure arguments
3450
--> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
@@ -45,6 +61,14 @@ note: required by a bound in `f3`
4561
|
4662
LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
4763
| ^^^^^^^^^^^^^^^ required by this bound in `f3`
64+
help: consider borrowing the argument
65+
|
66+
LL | f3(|_: &(), _: ()| {});
67+
| ~~~
68+
help: consider borrowing the argument
69+
|
70+
LL | f3(|_: (), _: &()| {});
71+
| ~~~
4872

4973
error[E0631]: type mismatch in closure arguments
5074
--> $DIR/anonymous-higher-ranked-lifetime.rs:5:5
@@ -61,6 +85,14 @@ note: required by a bound in `f4`
6185
|
6286
LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
6387
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4`
88+
help: consider borrowing the argument
89+
|
90+
LL | f4(|_: &(), _: ()| {});
91+
| ~~~
92+
help: consider borrowing the argument
93+
|
94+
LL | f4(|_: (), _: &'r ()| {});
95+
| ~~~~~~
6496

6597
error[E0631]: type mismatch in closure arguments
6698
--> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
@@ -77,6 +109,14 @@ note: required by a bound in `f5`
77109
|
78110
LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
79111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5`
112+
help: consider borrowing the argument
113+
|
114+
LL | f5(|_: &'r (), _: ()| {});
115+
| ~~~~~~
116+
help: consider borrowing the argument
117+
|
118+
LL | f5(|_: (), _: &'r ()| {});
119+
| ~~~~~~
80120

81121
error[E0631]: type mismatch in closure arguments
82122
--> $DIR/anonymous-higher-ranked-lifetime.rs:7:5
@@ -93,6 +133,10 @@ note: required by a bound in `g1`
93133
|
94134
LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
95135
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g1`
136+
help: consider borrowing the argument
137+
|
138+
LL | g1(|_: &(), _: ()| {});
139+
| ~~~
96140

97141
error[E0631]: type mismatch in closure arguments
98142
--> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
@@ -109,6 +153,10 @@ note: required by a bound in `g2`
109153
|
110154
LL | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
111155
| ^^^^^^^^^^^^^^^^ required by this bound in `g2`
156+
help: consider borrowing the argument
157+
|
158+
LL | g2(|_: &(), _: ()| {});
159+
| ~~~
112160

113161
error[E0631]: type mismatch in closure arguments
114162
--> $DIR/anonymous-higher-ranked-lifetime.rs:9:5
@@ -125,6 +173,10 @@ note: required by a bound in `g3`
125173
|
126174
LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
127175
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g3`
176+
help: consider borrowing the argument
177+
|
178+
LL | g3(|_: &'s (), _: ()| {});
179+
| ~~~~~~
128180

129181
error[E0631]: type mismatch in closure arguments
130182
--> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
@@ -141,6 +193,10 @@ note: required by a bound in `g4`
141193
|
142194
LL | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
143195
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g4`
196+
help: consider borrowing the argument
197+
|
198+
LL | g4(|_: &(), _: ()| {});
199+
| ~~~
144200

145201
error[E0631]: type mismatch in closure arguments
146202
--> $DIR/anonymous-higher-ranked-lifetime.rs:11:5
@@ -157,6 +213,14 @@ note: required by a bound in `h1`
157213
|
158214
LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
159215
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h1`
216+
help: consider borrowing the argument
217+
|
218+
LL | h1(|_: &(), _: (), _: (), _: ()| {});
219+
| ~~~
220+
help: consider borrowing the argument
221+
|
222+
LL | h1(|_: (), _: (), _: &(), _: ()| {});
223+
| ~~~
160224

161225
error[E0631]: type mismatch in closure arguments
162226
--> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
@@ -173,6 +237,14 @@ note: required by a bound in `h2`
173237
|
174238
LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
175239
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2`
240+
help: consider borrowing the argument
241+
|
242+
LL | h2(|_: &(), _: (), _: (), _: ()| {});
243+
| ~~~
244+
help: consider borrowing the argument
245+
|
246+
LL | h2(|_: (), _: (), _: &'t0 (), _: ()| {});
247+
| ~~~~~~~
176248

177249
error: aborting due to 11 previous errors
178250

src/test/ui/closures/multiple-fn-bounds.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ note: required by a bound in `foo`
1818
|
1919
LL | fn foo<F: Fn(&char) -> bool + Fn(char) -> bool>(f: F) {
2020
| ^^^^^^^^^^^^^^^^ required by this bound in `foo`
21+
help: do not borrow the argument
22+
|
23+
LL | foo(move |char| v);
24+
| ~~~~
2125

2226
error: aborting due to previous error
2327

src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ note: required by a bound in `map`
1313
|
1414
LL | F: FnMut(Self::Item) -> B,
1515
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
16+
help: consider borrowing the argument
17+
|
18+
LL | a.iter().map(|_: &(u32, u32)| 45);
19+
| ~~~~~~~~~~~
1620

1721
error[E0631]: type mismatch in closure arguments
1822
--> $DIR/closure-arg-type-mismatch.rs:4:14

src/test/ui/mismatched_types/issue-36053-2.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ note: required by a bound in `filter`
1313
|
1414
LL | P: FnMut(&Self::Item) -> bool,
1515
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `filter`
16+
help: consider borrowing the argument
17+
|
18+
LL | once::<&str>("str").fuse().filter(|a: &&str| true).count();
19+
| ~~~~~
1620

1721
error[E0599]: the method `count` exists for struct `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>`, but its trait bounds were not satisfied
1822
--> $DIR/issue-36053-2.rs:7:55

0 commit comments

Comments
 (0)