From 7d7b3816607c3f0c5afd4562bb3efca8b6eea777 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 8 Feb 2026 16:42:28 +0900 Subject: [PATCH] Fix ICE in borrowck when recovering `fn_sig` for `-> _` --- compiler/rustc_hir_analysis/src/collect.rs | 56 ++++++++++++++++++- tests/crashes/135845.rs | 6 -- .../recover-infer-ret-ty-issue-135845.rs | 11 ++++ .../recover-infer-ret-ty-issue-135845.stderr | 15 +++++ 4 files changed, 80 insertions(+), 8 deletions(-) delete mode 100644 tests/crashes/135845.rs create mode 100644 tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.rs create mode 100644 tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.stderr diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 03bbc9c0a7c9..29a2e7e36220 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1138,13 +1138,65 @@ fn recover_infer_ret_ty<'tcx>( ); } let guar = diag.emit(); - ty::Binder::dummy(tcx.mk_fn_sig( + + // If we return a dummy binder here, we can ICE later in borrowck when it encounters + // `ReLateParam` regions (e.g. in a local type annotation) which weren't registered via the + // signature binder. See #135845. + let bound_vars = tcx.late_bound_vars(hir_id); + let scope = def_id.to_def_id(); + + let fn_sig = 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.safety, fn_sig.abi, - )) + ); + + let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() { + ty::ReLateParam(lp) if lp.scope == scope => { + let br = match lp.kind { + ty::LateParamRegionKind::Anon(idx) | ty::LateParamRegionKind::NamedAnon(idx, _) => { + let idx = idx as usize; + match bound_vars.get(idx).copied() { + Some(ty::BoundVariableKind::Region(br_kind)) => Some(ty::BoundRegion { + var: ty::BoundVar::from_usize(idx), + kind: br_kind, + }), + _ => None, + } + } + ty::LateParamRegionKind::Named(def_id) => { + bound_vars.iter().enumerate().find_map(|(idx, bv)| match bv { + ty::BoundVariableKind::Region( + br_kind @ ty::BoundRegionKind::Named(did), + ) if did == def_id => Some(ty::BoundRegion { + var: ty::BoundVar::from_usize(idx), + kind: br_kind, + }), + _ => None, + }) + } + ty::LateParamRegionKind::ClosureEnv => { + bound_vars.iter().enumerate().find_map(|(idx, bv)| match bv { + ty::BoundVariableKind::Region( + br_kind @ ty::BoundRegionKind::ClosureEnv, + ) => Some(ty::BoundRegion { + var: ty::BoundVar::from_usize(idx), + kind: br_kind, + }), + _ => None, + }) + } + }; + + br.map(|br| ty::Region::new_bound(tcx, ty::INNERMOST, br)) + .unwrap_or_else(|| ty::Region::new_error(tcx, guar)) + } + _ => r, + }); + + ty::Binder::bind_with_vars(fn_sig, bound_vars) } pub fn suggest_impl_trait<'tcx>( diff --git a/tests/crashes/135845.rs b/tests/crashes/135845.rs deleted file mode 100644 index ed038d8a1f18..000000000000 --- a/tests/crashes/135845.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #135845 -struct S<'a, T: ?Sized>(&'a T); - -fn b<'a>() -> S<'static, _> { - S::<'a>(&0) -} diff --git a/tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.rs b/tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.rs new file mode 100644 index 000000000000..acce49b1af72 --- /dev/null +++ b/tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.rs @@ -0,0 +1,11 @@ +// Regression test for #135845. + +use std::marker::PhantomData; + +fn b<'a>() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + let _: PhantomData<&'a ()> = PhantomData; + 0 +} + +fn main() {} diff --git a/tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.stderr b/tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.stderr new file mode 100644 index 000000000000..9f3695e88f82 --- /dev/null +++ b/tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.stderr @@ -0,0 +1,15 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/recover-infer-ret-ty-issue-135845.rs:5:15 + | +LL | fn b<'a>() -> _ { + | ^ not allowed in type signatures + | +help: replace with the correct return type + | +LL - fn b<'a>() -> _ { +LL + fn b<'a>() -> i32 { + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0121`.