Change:
I tried this code: The resulting diagnostic suggests replacing fn() -i32 {f}f(): This, of course, doesn't work: I'd expect the diagnostic to suggest replacing fn() -i32impl Fn() -i32, both of which compile successfully. : <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
modify labels: +A-diagnostics +D-incorrect
This also seems to happen with closures:
claim
Function pointers are now working, but it looks like closures will be a bit harder of a task.
This brings up some questions though, unfortunately. For example, this code has the same type of issue: This code brings up this diagnostic: And to be honest, these diagnostics aren't entirely incorrect—that is the return type, it's just not valid syntax. Using a function pointer would be taking that unique type and coercing it into a function pointer or non-unique closure type. Arguably, it should have something like fn() -i32`, but doing this would end up meaning changing a lot of typeck code. I'm not really sure how to go through with this considering these things (as I'm not really too experienced with rustc code and therefore might mess up a bit of things).
For errors like E0308, it would make sense to state the actual type since that is the root cause of the issue (functions cannot be coerced to ). E0121, however, suggests replacing `` with the type it gives you, which falls apart in the face of these unnameable types. This can be a papercut to people who don't know how to return a function pointer/closure and become confused when the suggestion fails to compile. This is probably problematic, since changing the impl of types (it seems like that's what's being used per []) would likely mess up E0308 and other similar diagnostics. []: I haven't looked into the underlying issue personally, but I can see a few options: Don't emit a suggestion for closures or functions. This is the simplest solution and would preserve the other typecheck-related diagnostics, but may be unhelpful to those who rely on E0121 as a simulacrum of [typed holes]. Add if the returned value is a function, but don't emit a suggestion for closures. I'm not sure of the depth of changes necessary for just this, and again, I'm not sure if this meshes well with other diagnostics. Emit a different suggestion for closures and possibly functions along the lines of . [typed holes]:
I think that I'll probably do this I guess: If it's a function, suggest a function pointer, but also add that suggestion about a Fn/FnOnce/FnMut trait bound If it's a closure, suggest a Fn/FnOnce/FnMut trait bound as well
Should I link to the or maybe the ?
Rust by Example or would probably be preferable since they explain Fn, FnMut, and FnOnce in one place, but I'm not certain if there's any precedent or policy about linking to them in diagnostics.
Alright. Does this look good? Function definition: I'll get closures in a bit, cause my rustc dev build decided to die on me and I have to completely rebuild it :slightlyfrowningface:
Looks good to me, but I'd like to emphasize that I'm not ready a contributor, so take this with a grain of salt.
Closures:
I think I'm going to remove the (/) from function definitions as it's kind of not strictly necessary as it's a return type, not an input param
Thank you so much for all of your hard work! Just a nitpick: .
Yeah, camelid noted that in a Zulip thread related to this so I fixed that.
This still fails on generators (): I'm working on a PR to fix this as well as making this suggestion and E0308's suggestion use the same mechanism for checking if a type is suggestable directly. claim
Moving this to release-assignment

Discussion:
let mut diag = bad_placeholder_type(tcx, visitor.0); let ret_ty = fn_sig.output(); if ret_ty != tcx.ty_error() { <del> diag.span_suggestion( ty.span, "replace with the correct return type", ret_ty.to_string(), Applicability::MaybeIncorrect, ); </del> <ins> if !ret_ty.is_closure() { let ret_ty_str = match ret_ty.kind() { // Suggest a function pointer return type instead of a unique function definition // (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid // syntax) ty::FnDef(..) => ret_ty.fn_sig(tcx).to_string(), _ => ret_ty.to_string(), }; diag.span_suggestion( ty.span, "replace with the correct return type", ret_ty_str, Applicability::MaybeIncorrect, ); } else { // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds // to prevent the user from getting a papercut while trying to use the unique closure // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`). diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound"); diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html"); } </ins> } diag.emit(); ty::Binder::bind(fn_sig)

<ins> // Functions with a type placeholder `_` as the return type should // show a function pointer suggestion when given a function item // and suggest how to return closures correctly from a function. // This is a regression test of #80179 fn returns_i32() -> i32 { 0 } fn returns_fn_ptr() -> _ { //~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121] //~| NOTE not allowed in type signatures //~| HELP replace with the correct return type //~| SUGGESTION fn() -> i32 returns_i32 } fn returns_closure() -> _ { //~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121] //~| NOTE not allowed in type signatures //~| HELP consider using an `Fn`, `FnMut`, or `FnOnce` trait bound //~| NOTE for more information on `Fn` traits and closure types, see //        https://doc.rust-lang.org/book/ch13-01-closures.html || 0 } fn main() {} </ins>

<ins> error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/issue-80179.rs:10:24 | LL | fn returns_fn_ptr() -> _ { |                        ^ |                        | |                        not allowed in type signatures |                        help: replace with the correct return type: `fn() -> i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/issue-80179.rs:18:25 | LL | fn returns_closure() -> _ { |                         ^ not allowed in type signatures | = help: consider using an `Fn`, `FnMut`, or `FnOnce` trait bound = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0121`. </ins>