1 //! Bounds are restrictions applied to some types after they've been converted into the
2 //! `ty` form from the HIR.
4 use rustc_middle
::ty
::{self, ToPredicate, Ty, TyCtxt}
;
7 /// Collects together a list of type bounds. These lists of bounds occur in many places
11 /// trait Foo: Bar + Baz { }
12 /// ^^^^^^^^^ supertrait list bounding the `Self` type parameter
14 /// fn foo<T: Bar + Baz>() { }
15 /// ^^^^^^^^^ bounding the type parameter `T`
17 /// impl dyn Bar + Baz
18 /// ^^^^^^^^^ bounding the forgotten dynamic type
21 /// Our representation is a bit mixed here -- in some cases, we
22 /// include the self type (e.g., `trait_bounds`) but in others we do not
23 #[derive(Default, PartialEq, Eq, Clone, Debug)]
24 pub struct Bounds
<'tcx
> {
25 /// A list of region bounds on the (implicit) self type. So if you
26 /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
27 /// the `T` is not explicitly included).
28 pub region_bounds
: Vec
<(ty
::Binder
<'tcx
, ty
::Region
<'tcx
>>, Span
)>,
30 /// A list of trait bounds. So if you had `T: Debug` this would be
31 /// `T: Debug`. Note that the self-type is explicit here.
32 pub trait_bounds
: Vec
<(ty
::PolyTraitRef
<'tcx
>, Span
, ty
::BoundConstness
)>,
34 /// A list of projection equality bounds. So if you had `T:
35 /// Iterator<Item = u32>` this would include `<T as
36 /// Iterator>::Item => u32`. Note that the self-type is explicit
38 pub projection_bounds
: Vec
<(ty
::PolyProjectionPredicate
<'tcx
>, Span
)>,
40 /// `Some` if there is *no* `?Sized` predicate. The `span`
41 /// is the location in the source of the `T` declaration which can
42 /// be cited as the source of the `T: Sized` requirement.
43 pub implicitly_sized
: Option
<Span
>,
46 impl<'tcx
> Bounds
<'tcx
> {
47 /// Converts a bounds list into a flat set of predicates (like
48 /// where-clauses). Because some of our bounds listings (e.g.,
49 /// regions) don't include the self-type, you must supply the
50 /// self-type here (the `param_ty` parameter).
51 pub fn predicates
<'out
, 's
>(
55 // the output must live shorter than the duration of the borrow of self and 'tcx.
56 ) -> impl Iterator
<Item
= (ty
::Predicate
<'tcx
>, Span
)> + 'out
61 // If it could be sized, and is, add the `Sized` predicate.
62 let sized_predicate
= self.implicitly_sized
.and_then(|span
| {
63 tcx
.lang_items().sized_trait().map(move |sized
| {
64 let trait_ref
= ty
::Binder
::dummy(ty
::TraitRef
{
66 substs
: tcx
.mk_substs_trait(param_ty
, &[]),
68 (trait_ref
.without_const().to_predicate(tcx
), span
)
72 let region_preds
= self.region_bounds
.iter().map(move |&(region_bound
, span
)| {
73 let pred
= region_bound
74 .map_bound(|region_bound
| ty
::OutlivesPredicate(param_ty
, region_bound
))
79 self.trait_bounds
.iter().map(move |&(bound_trait_ref
, span
, constness
)| {
80 let predicate
= bound_trait_ref
.with_constness(constness
).to_predicate(tcx
);
83 let projection_bounds
= self
86 .map(move |&(projection
, span
)| (projection
.to_predicate(tcx
), span
));
88 sized_predicate
.into_iter().chain(region_preds
).chain(trait_bounds
).chain(projection_bounds
)