Rollup merge of #152323 - JohnTitor:issue-135845-2, r=lcnr

Fix ICE in borrowck when recovering `fn_sig` for `-> _`

(Should be) a proper fix for rust-lang/rust#135845, replaces a dummy binder with a concrete one not to ICE, as mentioned in https://github.com/rust-lang/rust/pull/147631#issuecomment-3460724226.
Fixes rust-lang/rust#135845
r? @lcnr @jackh726
This commit is contained in:
Jonathan Brouwer 2026-02-13 13:34:58 +01:00 committed by GitHub
commit 9d662b5815
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 101 additions and 8 deletions

View file

@ -1063,6 +1063,70 @@ fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
)
}
/// Convert `ReLateParam`s in `value` back into `ReBound`s and bind it with `bound_vars`.
fn late_param_regions_to_bound<'tcx, T>(
tcx: TyCtxt<'tcx>,
scope: DefId,
bound_vars: &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
value: T,
) -> ty::Binder<'tcx, T>
where
T: ty::TypeFoldable<TyCtxt<'tcx>>,
{
let value = fold_regions(tcx, value, |r, debruijn| match r.kind() {
ty::ReLateParam(lp) => {
// Should be in scope, otherwise inconsistency happens somewhere.
assert_eq!(lp.scope, scope);
let br = match lp.kind {
// These variants preserve the bound var index.
kind @ (ty::LateParamRegionKind::Anon(idx)
| ty::LateParamRegionKind::NamedAnon(idx, _)) => {
let idx = idx as usize;
let var = ty::BoundVar::from_usize(idx);
let Some(ty::BoundVariableKind::Region(kind)) = bound_vars.get(idx).copied()
else {
bug!("unexpected late-bound region {kind:?} for bound vars {bound_vars:?}");
};
ty::BoundRegion { var, kind }
}
// For named regions, look up the corresponding bound var.
ty::LateParamRegionKind::Named(def_id) => bound_vars
.iter()
.enumerate()
.find_map(|(idx, bv)| match bv {
ty::BoundVariableKind::Region(kind @ ty::BoundRegionKind::Named(did))
if did == def_id =>
{
Some(ty::BoundRegion { var: ty::BoundVar::from_usize(idx), kind })
}
_ => None,
})
.unwrap(),
ty::LateParamRegionKind::ClosureEnv => bound_vars
.iter()
.enumerate()
.find_map(|(idx, bv)| match bv {
ty::BoundVariableKind::Region(kind @ ty::BoundRegionKind::ClosureEnv) => {
Some(ty::BoundRegion { var: ty::BoundVar::from_usize(idx), kind })
}
_ => None,
})
.unwrap(),
};
ty::Region::new_bound(tcx, debruijn, br)
}
_ => r,
});
ty::Binder::bind_with_vars(value, bound_vars)
}
fn recover_infer_ret_ty<'tcx>(
icx: &ItemCtxt<'tcx>,
infer_ret_ty: &'tcx hir::Ty<'tcx>,
@ -1138,13 +1202,22 @@ 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,
))
);
late_param_regions_to_bound(tcx, scope, bound_vars, fn_sig)
}
pub fn suggest_impl_trait<'tcx>(

View file

@ -1,6 +0,0 @@
//@ known-bug: #135845
struct S<'a, T: ?Sized>(&'a T);
fn b<'a>() -> S<'static, _> {
S::<'a>(&0)
}

View file

@ -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() {}

View file

@ -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`.