From c8874e24458e7ba88fad7969562a45c951d002a8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 22 Apr 2023 19:29:30 +0000 Subject: [PATCH] Don't infer fn return type to return itself --- compiler/rustc_hir_analysis/src/collect.rs | 31 ++++++++++++------- .../ui/typeck/bad-recursive-type-sig-infer.rs | 11 +++++++ .../bad-recursive-type-sig-infer.stderr | 15 +++++++++ 3 files changed, 46 insertions(+), 11 deletions(-) create mode 100644 tests/ui/typeck/bad-recursive-type-sig-infer.rs create mode 100644 tests/ui/typeck/bad-recursive-type-sig-infer.stderr diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 36e294e8aa2..9fe0c07814e 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1146,8 +1146,14 @@ fn infer_return_ty_for_fn_sig<'tcx>( let mut visitor = HirPlaceholderCollector::default(); visitor.visit_ty(ty); + let mut diag = bad_placeholder(tcx, visitor.0, "return type"); let ret_ty = fn_sig.output(); + // Don't leak types into signatures unless they're nameable! + // For example, if a function returns itself, we don't want that + // recursive function definition to leak out into the fn sig. + let mut should_recover = false; + if let Some(ret_ty) = ret_ty.make_suggestable(tcx, false) { diag.span_suggestion( ty.span, @@ -1155,15 +1161,7 @@ fn infer_return_ty_for_fn_sig<'tcx>( ret_ty, Applicability::MachineApplicable, ); - } else if matches!(ret_ty.kind(), ty::FnDef(..)) - && let Some(fn_sig) = ret_ty.fn_sig(tcx).make_suggestable(tcx, false) - { - diag.span_suggestion( - ty.span, - "replace with the correct return type", - fn_sig, - Applicability::MachineApplicable, - ); + should_recover = true; } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, def_id) { diag.span_suggestion( ty.span, @@ -1181,9 +1179,20 @@ fn infer_return_ty_for_fn_sig<'tcx>( https://doc.rust-lang.org/book/ch13-01-closures.html", ); } - diag.emit(); - ty::Binder::dummy(fn_sig) + let guar = diag.emit(); + + if should_recover { + ty::Binder::dummy(fn_sig) + } else { + ty::Binder::dummy(tcx.mk_fn_sig( + fn_sig.inputs().iter().copied(), + tcx.ty_error(guar), + fn_sig.c_variadic, + fn_sig.unsafety, + fn_sig.abi, + )) + } } None => icx.astconv().ty_of_fn( hir_id, diff --git a/tests/ui/typeck/bad-recursive-type-sig-infer.rs b/tests/ui/typeck/bad-recursive-type-sig-infer.rs new file mode 100644 index 00000000000..9812d8c3811 --- /dev/null +++ b/tests/ui/typeck/bad-recursive-type-sig-infer.rs @@ -0,0 +1,11 @@ +fn a() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + &a +} + +fn b() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + &a +} + +fn main() {} diff --git a/tests/ui/typeck/bad-recursive-type-sig-infer.stderr b/tests/ui/typeck/bad-recursive-type-sig-infer.stderr new file mode 100644 index 00000000000..e145da5623a --- /dev/null +++ b/tests/ui/typeck/bad-recursive-type-sig-infer.stderr @@ -0,0 +1,15 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/bad-recursive-type-sig-infer.rs:1:11 + | +LL | fn a() -> _ { + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/bad-recursive-type-sig-infer.rs:6:11 + | +LL | fn b() -> _ { + | ^ not allowed in type signatures + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`.