use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec;
use alloc::vec::Vec;
use crate::rustc_data_structures::fx::FxIndexMap;
use crate::rustc_middle::ty::outlives::{Component, push_outlives_components};
use crate::rustc_middle::ty::{self, GenericArg, GenericArgKind, Region, Ty, TyCtxt};
use crate::rustc_middle::{bug, span_bug};
use crate::rustc_span::Span;
use smallvec::smallvec;
pub(crate) type RequiredClauses<'tcx> = FxIndexMap<ty::ArgOutlivesClause<'tcx>, Span>;
pub(crate) fn insert_outlives_clause<'tcx>(
tcx: TyCtxt<'tcx>,
arg: GenericArg<'tcx>,
outlived_region: Region<'tcx>,
span: Span,
required_clauses: &mut RequiredClauses<'tcx>,
) {
if !is_free_region(outlived_region) {
return;
}
match arg.kind() {
GenericArgKind::Type(ty) => {
let mut components = smallvec![];
push_outlives_components(tcx, ty, &mut components);
for component in components {
match component {
Component::Region(r) => {
insert_outlives_clause(
tcx,
r.into(),
outlived_region,
span,
required_clauses,
);
}
Component::Param(param_ty) => {
let ty: Ty<'tcx> = param_ty.to_ty(tcx);
required_clauses
.entry(ty::OutlivesClause(ty.into(), outlived_region))
.or_insert(span);
}
Component::Placeholder(_) => {
span_bug!(span, "Should not deduce placeholder outlives component");
}
Component::Alias(is_rigid, alias_ty) => {
let ty = alias_ty.to_ty(tcx, is_rigid);
required_clauses
.entry(ty::OutlivesClause(ty.into(), outlived_region))
.or_insert(span);
}
Component::EscapingAlias(_) => {
}
Component::UnresolvedInferenceVariable(_) => bug!("not using infcx"),
}
}
}
GenericArgKind::Lifetime(r) => {
if !is_free_region(r) {
return;
}
required_clauses.entry(ty::OutlivesClause(arg, outlived_region)).or_insert(span);
}
GenericArgKind::Const(_) => {
}
}
}
fn is_free_region(region: Region<'_>) -> bool {
match region.kind() {
ty::ReEarlyParam(_) => true,
ty::ReStatic => false,
ty::ReBound(..) => false,
ty::ReError(_) => false,
ty::ReErased | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReLateParam(..) => {
bug!("unexpected region in outlives inference: {:?}", region);
}
}
}