diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index c1bf65367aab5..1085caa310b6d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1373,16 +1373,16 @@ fn infer_return_ty_for_fn_sig<'tcx>( // 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; + let mut recovered_ret_ty = None; - if let Some(ret_ty) = ret_ty.make_suggestable(tcx, false, None) { + if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) { diag.span_suggestion( ty.span, "replace with the correct return type", - ret_ty, + suggestable_ret_ty, Applicability::MachineApplicable, ); - should_recover = true; + recovered_ret_ty = Some(suggestable_ret_ty); } else if let Some(sugg) = suggest_impl_trait(&tcx.infer_ctxt().build(), tcx.param_env(def_id), ret_ty) { @@ -1404,18 +1404,13 @@ fn infer_return_ty_for_fn_sig<'tcx>( } 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(), - Ty::new_error(tcx, guar), - fn_sig.c_variadic, - fn_sig.unsafety, - fn_sig.abi, - )) - } + ty::Binder::dummy(tcx.mk_fn_sig( + fn_sig.inputs().iter().copied(), + recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)), + fn_sig.c_variadic, + fn_sig.unsafety, + fn_sig.abi, + )) } None => icx.lowerer().lower_fn_ty( hir_id, diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 20e4110e1378d..eeb8b02850521 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -236,7 +236,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::FnDef(..) | ty::Coroutine(..) | ty::Closure(..) | ty::CoroutineClosure(..) => { - bug!("Unexpected coroutine/closure type in variance computation"); + bug!("Unexpected unnameable type in variance computation: {ty}"); } ty::Ref(region, ty, mutbl) => { diff --git a/tests/ui/variance/leaking-unnameables.rs b/tests/ui/variance/leaking-unnameables.rs new file mode 100644 index 0000000000000..e51d3779d34b5 --- /dev/null +++ b/tests/ui/variance/leaking-unnameables.rs @@ -0,0 +1,13 @@ +// Test variance computation doesn't explode when we leak unnameable +// types due to `-> _` recovery. + +pub struct Type<'a>(&'a ()); + +pub fn g() {} + +pub fn f() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures + g +} + +fn main() {} diff --git a/tests/ui/variance/leaking-unnameables.stderr b/tests/ui/variance/leaking-unnameables.stderr new file mode 100644 index 0000000000000..92afe952801d0 --- /dev/null +++ b/tests/ui/variance/leaking-unnameables.stderr @@ -0,0 +1,12 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/leaking-unnameables.rs:8:18 + | +LL | pub fn f() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `fn()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0121`.