]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_typeck/src/bounds.rs
New upstream version 1.49.0~beta.4+dfsg1
[rustc.git] / compiler / rustc_typeck / src / bounds.rs
CommitLineData
3dfed10e
XL
1//! Bounds are restrictions applied to some types after they've been converted into the
2//! `ty` form from the HIR.
3
4use rustc_hir::Constness;
5use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
6use 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)]
25pub 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::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
47impl<'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(
71 self.region_bounds
72 .iter()
73 .map(|&(region_bound, span)| {
3dfed10e
XL
74 let outlives = ty::OutlivesPredicate(param_ty, region_bound);
75 (ty::Binder::bind(outlives).to_predicate(tcx), span)
76 })
77 .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
78 let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
79 (predicate, span)
80 }))
81 .chain(
82 self.projection_bounds
83 .iter()
84 .map(|&(projection, span)| (projection.to_predicate(tcx), span)),
85 ),
86 )
87 .collect()
88 }
89}