]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/bounds.rs
Rustdoc render public underscore_imports as Re-exports
[rust.git] / compiler / rustc_typeck / src / bounds.rs
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::Constness;
5 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
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 forgotten 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     /// A list of region bounds on the (implicit) self type. So if you
27     /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
28     /// the `T` is not explicitly included).
29     pub region_bounds: Vec<(ty::Binder<ty::Region<'tcx>>, Span)>,
30
31     /// A list of trait bounds. So if you had `T: Debug` this would be
32     /// `T: Debug`. Note that the self-type is explicit here.
33     pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, Constness)>,
34
35     /// A list of projection equality bounds. So if you had `T:
36     /// Iterator<Item = u32>` this would include `<T as
37     /// Iterator>::Item => u32`. Note that the self-type is explicit
38     /// here.
39     pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
40
41     /// `Some` if there is *no* `?Sized` predicate. The `span`
42     /// is the location in the source of the `T` declaration which can
43     /// be cited as the source of the `T: Sized` requirement.
44     pub implicitly_sized: Option<Span>,
45 }
46
47 impl<'tcx> Bounds<'tcx> {
48     /// Converts a bounds list into a flat set of predicates (like
49     /// where-clauses). Because some of our bounds listings (e.g.,
50     /// regions) don't include the self-type, you must supply the
51     /// self-type here (the `param_ty` parameter).
52     pub fn predicates(
53         &self,
54         tcx: TyCtxt<'tcx>,
55         param_ty: Ty<'tcx>,
56     ) -> Vec<(ty::Predicate<'tcx>, Span)> {
57         // If it could be sized, and is, add the `Sized` predicate.
58         let sized_predicate = self.implicitly_sized.and_then(|span| {
59             tcx.lang_items().sized_trait().map(|sized| {
60                 let trait_ref = ty::Binder::bind(ty::TraitRef {
61                     def_id: sized,
62                     substs: tcx.mk_substs_trait(param_ty, &[]),
63                 });
64                 (trait_ref.without_const().to_predicate(tcx), span)
65             })
66         });
67
68         sized_predicate
69             .into_iter()
70             .chain(self.region_bounds.iter().map(|&(region_bound, span)| {
71                 (
72                     region_bound
73                         .map_bound(|region_bound| ty::OutlivesPredicate(param_ty, region_bound))
74                         .to_predicate(tcx),
75                     span,
76                 )
77             }))
78             .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
79                 let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
80                 (predicate, span)
81             }))
82             .chain(
83                 self.projection_bounds
84                     .iter()
85                     .map(|&(projection, span)| (projection.to_predicate(tcx), span)),
86             )
87             .collect()
88     }
89 }