Skip to content

Commit 07abff5

Browse files
authored
Rollup merge of rust-lang#73630 - estebank:fn-item-e0308, r=davidtwco
Provide context on E0308 involving fn items Fix rust-lang#73487.
2 parents 9274c3e + 6e8aa1f commit 07abff5

File tree

5 files changed

+94
-11
lines changed

5 files changed

+94
-11
lines changed

src/librustc_infer/infer/error_reporting/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1256,7 +1256,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12561256
(ty::FnDef(did1, substs1), ty::FnPtr(sig2)) => {
12571257
let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
12581258
let mut values = self.cmp_fn_sig(&sig1, sig2);
1259-
values.0.push_normal(format!(
1259+
values.0.push_highlighted(format!(
12601260
" {{{}}}",
12611261
self.tcx.def_path_str_with_substs(*did1, substs1)
12621262
));

src/librustc_typeck/check/demand.rs

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3434
}
3535
self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
3636
self.suggest_missing_await(err, expr, expected, expr_ty);
37+
self.note_need_for_fn_pointer(err, expected, expr_ty);
3738
}
3839

3940
// Requires that the two types unify, and prints an error message if

src/librustc_typeck/check/mod.rs

+37
Original file line numberDiff line numberDiff line change
@@ -5362,6 +5362,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
53625362
}
53635363
}
53645364

5365+
fn note_need_for_fn_pointer(
5366+
&self,
5367+
err: &mut DiagnosticBuilder<'_>,
5368+
expected: Ty<'tcx>,
5369+
found: Ty<'tcx>,
5370+
) {
5371+
let (sig, did, substs) = match (&expected.kind, &found.kind) {
5372+
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
5373+
let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
5374+
let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
5375+
if sig1 != sig2 {
5376+
return;
5377+
}
5378+
err.note(
5379+
"different `fn` items always have unique types, even if their signatures are \
5380+
the same",
5381+
);
5382+
(sig1, *did1, substs1)
5383+
}
5384+
(ty::FnDef(did, substs), ty::FnPtr(sig2)) => {
5385+
let sig1 = self.tcx.fn_sig(*did).subst(self.tcx, substs);
5386+
if sig1 != *sig2 {
5387+
return;
5388+
}
5389+
(sig1, *did, substs)
5390+
}
5391+
_ => return,
5392+
};
5393+
err.help(&format!("change the expected type to be function pointer `{}`", sig));
5394+
err.help(&format!(
5395+
"if the expected type is due to type inference, cast the expected `fn` to a function \
5396+
pointer: `{} as {}`",
5397+
self.tcx.def_path_str_with_substs(did, substs),
5398+
sig
5399+
));
5400+
}
5401+
53655402
/// A common error is to add an extra semicolon:
53665403
///
53675404
/// ```

src/test/ui/fn/fn-item-type.rs

+28-6
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,44 @@ impl<T> Foo for T { /* `foo` is still default here */ }
1212
fn main() {
1313
eq(foo::<u8>, bar::<u8>);
1414
//~^ ERROR mismatched types
15-
//~| expected fn item `fn(_) -> _ {foo::<u8>}`
16-
//~| found fn item `fn(_) -> _ {bar::<u8>}`
17-
//~| expected fn item, found a different fn item
15+
//~| expected fn item `fn(_) -> _ {foo::<u8>}`
16+
//~| found fn item `fn(_) -> _ {bar::<u8>}`
17+
//~| expected fn item, found a different fn item
18+
//~| different `fn` items always have unique types, even if their signatures are the same
19+
//~| change the expected type to be function pointer
20+
//~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
1821

1922
eq(foo::<u8>, foo::<i8>);
2023
//~^ ERROR mismatched types
2124
//~| expected `u8`, found `i8`
25+
//~| different `fn` items always have unique types, even if their signatures are the same
26+
//~| change the expected type to be function pointer
27+
//~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
2228

2329
eq(bar::<String>, bar::<Vec<u8>>);
2430
//~^ ERROR mismatched types
25-
//~| expected fn item `fn(_) -> _ {bar::<std::string::String>}`
26-
//~| found fn item `fn(_) -> _ {bar::<std::vec::Vec<u8>>}`
27-
//~| expected struct `std::string::String`, found struct `std::vec::Vec`
31+
//~| expected fn item `fn(_) -> _ {bar::<std::string::String>}`
32+
//~| found fn item `fn(_) -> _ {bar::<std::vec::Vec<u8>>}`
33+
//~| expected struct `std::string::String`, found struct `std::vec::Vec`
34+
//~| different `fn` items always have unique types, even if their signatures are the same
35+
//~| change the expected type to be function pointer
36+
//~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
2837

2938
// Make sure we distinguish between trait methods correctly.
3039
eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
3140
//~^ ERROR mismatched types
3241
//~| expected `u8`, found `u16`
42+
//~| different `fn` items always have unique types, even if their signatures are the same
43+
//~| change the expected type to be function pointer
44+
//~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
45+
46+
eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
47+
//~^ ERROR mismatched types
48+
//~| expected fn item `fn(_) -> _ {foo::<u8>}`
49+
//~| found fn pointer `fn(_) -> _`
50+
//~| expected fn item, found fn pointer
51+
//~| change the expected type to be function pointer
52+
//~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
53+
54+
eq(foo::<u8> as fn(isize) -> isize, bar::<u8>); // ok!
3355
}

src/test/ui/fn/fn-item-type.stderr

+27-4
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,57 @@ LL | eq(foo::<u8>, bar::<u8>);
66
|
77
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
88
found fn item `fn(_) -> _ {bar::<u8>}`
9+
= note: different `fn` items always have unique types, even if their signatures are the same
10+
= help: change the expected type to be function pointer `fn(isize) -> isize`
11+
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
912

1013
error[E0308]: mismatched types
11-
--> $DIR/fn-item-type.rs:19:19
14+
--> $DIR/fn-item-type.rs:22:19
1215
|
1316
LL | eq(foo::<u8>, foo::<i8>);
1417
| ^^^^^^^^^ expected `u8`, found `i8`
1518
|
1619
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
1720
found fn item `fn(_) -> _ {foo::<i8>}`
21+
= note: different `fn` items always have unique types, even if their signatures are the same
22+
= help: change the expected type to be function pointer `fn(isize) -> isize`
23+
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
1824

1925
error[E0308]: mismatched types
20-
--> $DIR/fn-item-type.rs:23:23
26+
--> $DIR/fn-item-type.rs:29:23
2127
|
2228
LL | eq(bar::<String>, bar::<Vec<u8>>);
2329
| ^^^^^^^^^^^^^^ expected struct `std::string::String`, found struct `std::vec::Vec`
2430
|
2531
= note: expected fn item `fn(_) -> _ {bar::<std::string::String>}`
2632
found fn item `fn(_) -> _ {bar::<std::vec::Vec<u8>>}`
33+
= note: different `fn` items always have unique types, even if their signatures are the same
34+
= help: change the expected type to be function pointer `fn(isize) -> isize`
35+
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `bar::<std::string::String> as fn(isize) -> isize`
2736

2837
error[E0308]: mismatched types
29-
--> $DIR/fn-item-type.rs:30:26
38+
--> $DIR/fn-item-type.rs:39:26
3039
|
3140
LL | eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
3241
| ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
3342
|
3443
= note: expected fn item `fn() {<u8 as Foo>::foo}`
3544
found fn item `fn() {<u16 as Foo>::foo}`
45+
= note: different `fn` items always have unique types, even if their signatures are the same
46+
= help: change the expected type to be function pointer `fn()`
47+
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `<u8 as Foo>::foo as fn()`
3648

37-
error: aborting due to 4 previous errors
49+
error[E0308]: mismatched types
50+
--> $DIR/fn-item-type.rs:46:19
51+
|
52+
LL | eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer
54+
|
55+
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
56+
found fn pointer `fn(_) -> _`
57+
= help: change the expected type to be function pointer `fn(isize) -> isize`
58+
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
59+
60+
error: aborting due to 5 previous errors
3861

3962
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)