From 4f6be466fdec69dbf6ce768d41a43acf0fc3b47b Mon Sep 17 00:00:00 2001 From: ThePuzzlemaker Date: Mon, 21 Dec 2020 20:23:21 -0600 Subject: [PATCH] Suggest fn ptr rather than fn item and suggest to use `Fn` trait bounds rather than the unique closure type in E0121 This is a squash of the titular commit along with these minor commits: - Improve note - Improve note pt2 --- compiler/rustc_typeck/src/collect.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index bc6b2037c18..ebbcf6304b6 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1544,12 +1544,27 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { let mut diag = bad_placeholder_type(tcx, visitor.0); let ret_ty = fn_sig.output(); if ret_ty != tcx.ty_error() { - diag.span_suggestion( - ty.span, - "replace with the correct return type", - ret_ty.to_string(), - Applicability::MaybeIncorrect, - ); + 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"); + } } diag.emit(); ty::Binder::bind(fn_sig)