rustc_hir_analysis/
bounds.rsuse rustc_hir::LangItem;
use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
use rustc_span::Span;
#[derive(Default, PartialEq, Eq, Clone, Debug)]
pub(crate) struct Bounds<'tcx> {
clauses: Vec<(ty::Clause<'tcx>, Span)>,
}
impl<'tcx> Bounds<'tcx> {
pub(crate) fn push_region_bound(
&mut self,
tcx: TyCtxt<'tcx>,
region: ty::PolyTypeOutlivesPredicate<'tcx>,
span: Span,
) {
self.clauses
.push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).upcast(tcx), span));
}
pub(crate) fn push_trait_bound(
&mut self,
tcx: TyCtxt<'tcx>,
bound_trait_ref: ty::PolyTraitRef<'tcx>,
span: Span,
polarity: ty::PredicatePolarity,
) {
let clause = (
bound_trait_ref
.map_bound(|trait_ref| {
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
})
.upcast(tcx),
span,
);
if tcx.is_lang_item(bound_trait_ref.def_id(), LangItem::Sized) {
self.clauses.insert(0, clause);
} else {
self.clauses.push(clause);
}
}
pub(crate) fn push_projection_bound(
&mut self,
tcx: TyCtxt<'tcx>,
projection: ty::PolyProjectionPredicate<'tcx>,
span: Span,
) {
self.clauses.push((
projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).upcast(tcx),
span,
));
}
pub(crate) fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) {
let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]);
self.clauses.insert(0, (trait_ref.upcast(tcx), span));
}
pub(crate) fn push_const_bound(
&mut self,
tcx: TyCtxt<'tcx>,
bound_trait_ref: ty::PolyTraitRef<'tcx>,
constness: ty::BoundConstness,
span: Span,
) {
if tcx.is_const_trait(bound_trait_ref.def_id()) {
self.clauses.push((bound_trait_ref.to_host_effect_clause(tcx, constness), span));
} else {
tcx.dcx().span_delayed_bug(span, "tried to lower {host:?} bound for non-const trait");
}
}
pub(crate) fn clauses(&self) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ {
self.clauses.iter().cloned()
}
}