Skip to content

Commit f2f1234

Browse files
authored
Rollup merge of rust-lang#107287 - mattjperez:improve-fn-pointer-notes, r=compiler-errors
Improve fn pointer notes continuation of rust-lang#105552 r? `@compiler-errors`
2 parents c1d722c + 3016f55 commit f2f1234

File tree

4 files changed

+53
-9
lines changed

4 files changed

+53
-9
lines changed

Diff for: compiler/rustc_infer/src/infer/error_reporting/suggest.rs

+44-8
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
380380
return;
381381
}
382382

383-
let (msg, sugg) = match (expected.is_ref(), found.is_ref()) {
383+
let (msg, sug) = match (expected.is_ref(), found.is_ref()) {
384384
(true, false) => {
385385
let msg = "consider using a reference";
386386
let sug = format!("&{fn_name}");
@@ -404,22 +404,58 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
404404
(msg, sug)
405405
}
406406
};
407-
diag.span_suggestion(span, msg, &sugg, Applicability::MaybeIncorrect);
407+
diag.span_suggestion(span, msg, sug, Applicability::MaybeIncorrect);
408408
}
409409
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
410410
let expected_sig =
411411
&(self.normalize_fn_sig)(self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1));
412412
let found_sig =
413413
&(self.normalize_fn_sig)(self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2));
414414

415-
if self.same_type_modulo_infer(*found_sig, *expected_sig) {
416-
diag.note(
417-
"different fn items have unique types, even if their signatures are the same",
418-
);
415+
if self.same_type_modulo_infer(*expected_sig, *found_sig) {
416+
diag.note("different fn items have unique types, even if their signatures are the same");
417+
}
418+
419+
if !self.same_type_modulo_infer(*found_sig, *expected_sig)
420+
|| !found_sig.is_suggestable(self.tcx, true)
421+
|| !expected_sig.is_suggestable(self.tcx, true)
422+
|| ty::util::is_intrinsic(self.tcx, *did1)
423+
|| ty::util::is_intrinsic(self.tcx, *did2)
424+
{
425+
return;
419426
}
427+
428+
let fn_name = self.tcx.def_path_str_with_substs(*did2, substs2);
429+
let sug = if found.is_ref() {
430+
format!("&({fn_name} as {found_sig})")
431+
} else {
432+
format!("{fn_name} as {found_sig}")
433+
};
434+
435+
let msg = format!(
436+
"consider casting both fn items to fn pointers using `as {expected_sig}`"
437+
);
438+
439+
diag.span_suggestion_hidden(span, msg, sug, Applicability::MaybeIncorrect);
420440
}
421-
(ty::FnDef(_, _), ty::FnPtr(_)) => {
422-
diag.note("fn items are distinct from fn pointers");
441+
(ty::FnDef(did, substs), ty::FnPtr(sig)) => {
442+
let expected_sig =
443+
&(self.normalize_fn_sig)(self.tcx.bound_fn_sig(*did).subst(self.tcx, substs));
444+
let found_sig = &(self.normalize_fn_sig)(*sig);
445+
446+
if !self.same_type_modulo_infer(*found_sig, *expected_sig) {
447+
return;
448+
}
449+
450+
let fn_name = self.tcx.def_path_str_with_substs(*did, substs);
451+
452+
let casting = if expected.is_ref() {
453+
format!("&({fn_name} as {found_sig})")
454+
} else {
455+
format!("{fn_name} as {found_sig}")
456+
};
457+
458+
diag.help(&format!("consider casting the fn item to a fn pointer: `{}`", casting));
423459
}
424460
_ => {
425461
return;

Diff for: tests/ui/fn/fn-compare-mismatch.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ LL | let x = f == g;
2020
= note: expected fn item `fn() {f}`
2121
found fn item `fn() {g}`
2222
= note: different fn items have unique types, even if their signatures are the same
23+
= help: consider casting both fn items to fn pointers using `as fn()`
2324

2425
error: aborting due to 2 previous errors
2526

Diff for: tests/ui/fn/fn-item-type.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ note: function defined here
1414
|
1515
LL | fn eq<T>(x: T, y: T) {}
1616
| ^^ ----
17+
= help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
1718

1819
error[E0308]: mismatched types
1920
--> $DIR/fn-item-type.rs:29:19
@@ -31,6 +32,7 @@ note: function defined here
3132
|
3233
LL | fn eq<T>(x: T, y: T) {}
3334
| ^^ ----
35+
= help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
3436

3537
error[E0308]: mismatched types
3638
--> $DIR/fn-item-type.rs:34:23
@@ -48,6 +50,7 @@ note: function defined here
4850
|
4951
LL | fn eq<T>(x: T, y: T) {}
5052
| ^^ ----
53+
= help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
5154

5255
error[E0308]: mismatched types
5356
--> $DIR/fn-item-type.rs:41:26
@@ -65,6 +68,7 @@ note: function defined here
6568
|
6669
LL | fn eq<T>(x: T, y: T) {}
6770
| ^^ ----
71+
= help: consider casting both fn items to fn pointers using `as fn()`
6872

6973
error[E0308]: mismatched types
7074
--> $DIR/fn-item-type.rs:46:19
@@ -76,7 +80,7 @@ LL | eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
7680
|
7781
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
7882
found fn pointer `fn(_) -> _`
79-
= note: fn items are distinct from fn pointers
83+
= help: consider casting the fn item to a fn pointer: `foo::<u8> as fn(isize) -> isize`
8084
note: function defined here
8185
--> $DIR/fn-item-type.rs:11:4
8286
|

Diff for: tests/ui/fn/fn-pointer-mismatch.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ LL | let g = if n % 2 == 0 { &foo } else { &bar };
99
= note: expected reference `&fn(u32) -> u32 {foo}`
1010
found reference `&fn(u32) -> u32 {bar}`
1111
= note: different fn items have unique types, even if their signatures are the same
12+
= help: consider casting both fn items to fn pointers using `as fn(u32) -> u32`
1213

1314
error[E0308]: mismatched types
1415
--> $DIR/fn-pointer-mismatch.rs:23:9
@@ -21,6 +22,7 @@ LL | a = bar;
2122
= note: expected fn item `fn(_) -> _ {foo}`
2223
found fn item `fn(_) -> _ {bar}`
2324
= note: different fn items have unique types, even if their signatures are the same
25+
= help: consider casting both fn items to fn pointers using `as fn(u32) -> u32`
2426

2527
error[E0308]: mismatched types
2628
--> $DIR/fn-pointer-mismatch.rs:31:18
@@ -35,6 +37,7 @@ LL | b = Box::new(bar);
3537
= note: different fn items have unique types, even if their signatures are the same
3638
note: associated function defined here
3739
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
40+
= help: consider casting both fn items to fn pointers using `as fn(u32) -> u32`
3841

3942
error[E0308]: mismatched types
4043
--> $DIR/fn-pointer-mismatch.rs:36:29

0 commit comments

Comments
 (0)