Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 75 additions & 2 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down Expand Up @@ -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>(
Expand Down
6 changes: 0 additions & 6 deletions tests/crashes/135845.rs

This file was deleted.

11 changes: 11 additions & 0 deletions tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.rs
Original file line number Diff line number Diff line change
@@ -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() {}
15 changes: 15 additions & 0 deletions tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Loading