1 //! Bounds are restrictions applied to some types after they've been converted into the 2 //! `ty` form from the HIR. 3 4 use rustc_hir::LangItem; 5 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; 6 use rustc_span::Span; 7 8 /// Collects together a list of type bounds. These lists of bounds occur in many places 9 /// in Rust's syntax: 10 /// 11 /// ```text 12 /// trait Foo: Bar + Baz { } 13 /// ^^^^^^^^^ supertrait list bounding the `Self` type parameter 14 /// 15 /// fn foo<T: Bar + Baz>() { } 16 /// ^^^^^^^^^ bounding the type parameter `T` 17 /// 18 /// impl dyn Bar + Baz 19 /// ^^^^^^^^^ bounding the type-erased dynamic type 20 /// ``` 21 /// 22 /// Our representation is a bit mixed here -- in some cases, we 23 /// include the self type (e.g., `trait_bounds`) but in others we do not 24 #[derive(Default, PartialEq, Eq, Clone, Debug)] 25 pub struct Bounds<'tcx> { 26 pub clauses: Vec<(ty::Clause<'tcx>, Span)>, 27 } 28 29 impl<'tcx> Bounds<'tcx> { push_region_bound( &mut self, tcx: TyCtxt<'tcx>, region: ty::PolyTypeOutlivesPredicate<'tcx>, span: Span, )30 pub fn push_region_bound( 31 &mut self, 32 tcx: TyCtxt<'tcx>, 33 region: ty::PolyTypeOutlivesPredicate<'tcx>, 34 span: Span, 35 ) { 36 self.clauses 37 .push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).to_predicate(tcx), span)); 38 } 39 push_trait_bound( &mut self, tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, span: Span, constness: ty::BoundConstness, polarity: ty::ImplPolarity, )40 pub fn push_trait_bound( 41 &mut self, 42 tcx: TyCtxt<'tcx>, 43 trait_ref: ty::PolyTraitRef<'tcx>, 44 span: Span, 45 constness: ty::BoundConstness, 46 polarity: ty::ImplPolarity, 47 ) { 48 self.clauses.push(( 49 trait_ref 50 .map_bound(|trait_ref| { 51 ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness, polarity }) 52 }) 53 .to_predicate(tcx), 54 span, 55 )); 56 } 57 push_projection_bound( &mut self, tcx: TyCtxt<'tcx>, projection: ty::PolyProjectionPredicate<'tcx>, span: Span, )58 pub fn push_projection_bound( 59 &mut self, 60 tcx: TyCtxt<'tcx>, 61 projection: ty::PolyProjectionPredicate<'tcx>, 62 span: Span, 63 ) { 64 self.clauses.push(( 65 projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).to_predicate(tcx), 66 span, 67 )); 68 } 69 push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span)70 pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) { 71 let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span)); 72 let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]); 73 // Preferable to put this obligation first, since we report better errors for sized ambiguity. 74 self.clauses.insert(0, (trait_ref.to_predicate(tcx), span)); 75 } 76 clauses(&self) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_77 pub fn clauses(&self) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ { 78 self.clauses.iter().cloned() 79 } 80 } 81