use rustc_hir::def_id::DefId;
use rustc_middle::ty::{EarlyParamRegion, GenericParamDefKind, Region, RegionKind, Ty, TyCtxt};
pub(crate) fn resolve_region_name<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
name: &str,
) -> Option<Region<'tcx>> {
if name == "static" || name == "static_lifetime" {
return Some(tcx.lifetimes.re_static);
}
let ticked = format!("'{name}");
let generics = tcx.generics_of(def_id);
for param in &generics.own_params {
if matches!(param.kind, GenericParamDefKind::Lifetime)
&& (param.name.as_str() == name || param.name.as_str() == ticked.as_str())
{
return Some(Region::new_early_param(
tcx,
EarlyParamRegion {
index: param.index,
name: param.name,
},
));
}
}
None
}
pub(crate) fn region_outlives<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
src: Region<'tcx>,
ret: Region<'tcx>,
) -> bool {
match (src.kind(), ret.kind()) {
(RegionKind::ReStatic, _) => true,
(_, RegionKind::ReStatic) => false,
_ => {
if src == ret {
return true;
}
if !src.is_free() || !ret.is_free() {
return false;
}
free_region_outlives(tcx, def_id, src, ret)
}
}
}
fn free_region_outlives<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
src: Region<'tcx>,
ret: Region<'tcx>,
) -> bool {
use rustc_data_structures::fx::FxHashSet;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
let param_env = tcx.param_env(def_id);
let env = OutlivesEnvironment::from_normalized_bounds(
param_env,
Vec::new(),
std::iter::empty(),
FxHashSet::default(),
);
env.free_region_map().sub_free_regions(tcx, ret, src)
}
pub(crate) fn region_outlives_implied<'tcx>(
tcx: TyCtxt<'tcx>,
src_region: Region<'tcx>,
self_ty: Ty<'tcx>,
) -> bool {
use rustc_data_structures::smallvec::SmallVec;
use rustc_middle::ty::outlives::{Component, push_outlives_components};
let mut out: SmallVec<[Component<TyCtxt<'tcx>>; 4]> = SmallVec::new();
push_outlives_components(tcx, self_ty, &mut out);
out.iter()
.any(|c| matches!(c, Component::Region(r) if *r == src_region))
}
fn liberate_fn_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> rustc_middle::ty::FnSig<'tcx> {
let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
#[cfg(rapx_ge_99)]
let fn_sig = fn_sig.skip_norm_wip();
tcx.liberate_late_bound_regions(def_id, fn_sig)
}
pub(crate) fn fn_return_region<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Region<'tcx>> {
use rustc_middle::ty::TyKind;
match liberate_fn_sig(tcx, def_id).output().kind() {
TyKind::Ref(region, _, _) => Some(*region),
_ => None,
}
}
pub(crate) fn fn_arg_ty<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, index: usize) -> Option<Ty<'tcx>> {
liberate_fn_sig(tcx, def_id).inputs().get(index).copied()
}