@@ -16,28 +16,32 @@ use ty::{self, Ty, TypeFoldable};
16
16
use ty:: outlives:: Component ;
17
17
use ty:: wf;
18
18
19
- /// Implied bounds are region relationships that we deduce
20
- /// automatically. The idea is that (e.g.) a caller must check that a
21
- /// function's argument types are well-formed immediately before
22
- /// calling that fn, and hence the *callee* can assume that its
23
- /// argument types are well-formed. This may imply certain relationships
24
- /// between generic parameters. For example:
25
- ///
26
- /// fn foo<'a,T>(x: &'a T)
27
- ///
28
- /// can only be called with a `'a` and `T` such that `&'a T` is WF.
29
- /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
19
+ /// Outlives bounds are relationships between generic parameters,
20
+ /// whether they both be regions (`'a: 'b`) or whether types are
21
+ /// involved (`T: 'a`). These relationships can be extracted from the
22
+ /// full set of predicates we understand or also from types (in which
23
+ /// case they are called implied bounds). They are fed to the
24
+ /// `OutlivesEnv` which in turn is supplied to the region checker and
25
+ /// other parts of the inference system.
30
26
#[ derive( Debug ) ]
31
- pub enum ImpliedBound < ' tcx > {
27
+ pub enum OutlivesBound < ' tcx > {
32
28
RegionSubRegion ( ty:: Region < ' tcx > , ty:: Region < ' tcx > ) ,
33
29
RegionSubParam ( ty:: Region < ' tcx > , ty:: ParamTy ) ,
34
30
RegionSubProjection ( ty:: Region < ' tcx > , ty:: ProjectionTy < ' tcx > ) ,
35
31
}
36
32
37
33
impl < ' cx , ' gcx , ' tcx > InferCtxt < ' cx , ' gcx , ' tcx > {
38
- /// Compute the implied bounds that a callee/impl can assume based on
39
- /// the fact that caller/projector has ensured that `ty` is WF. See
40
- /// the `ImpliedBound` type for more details.
34
+ /// Implied bounds are region relationships that we deduce
35
+ /// automatically. The idea is that (e.g.) a caller must check that a
36
+ /// function's argument types are well-formed immediately before
37
+ /// calling that fn, and hence the *callee* can assume that its
38
+ /// argument types are well-formed. This may imply certain relationships
39
+ /// between generic parameters. For example:
40
+ ///
41
+ /// fn foo<'a,T>(x: &'a T)
42
+ ///
43
+ /// can only be called with a `'a` and `T` such that `&'a T` is WF.
44
+ /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
41
45
///
42
46
/// # Parameters
43
47
///
@@ -48,13 +52,13 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
48
52
/// - `ty`, the type that we are supposed to assume is WF.
49
53
/// - `span`, a span to use when normalizing, hopefully not important,
50
54
/// might be useful if a `bug!` occurs.
51
- pub fn implied_bounds (
55
+ pub fn implied_outlives_bounds (
52
56
& self ,
53
57
param_env : ty:: ParamEnv < ' tcx > ,
54
58
body_id : ast:: NodeId ,
55
59
ty : Ty < ' tcx > ,
56
60
span : Span ,
57
- ) -> Vec < ImpliedBound < ' tcx > > {
61
+ ) -> Vec < OutlivesBound < ' tcx > > {
58
62
let tcx = self . tcx ;
59
63
60
64
// Sometimes when we ask what it takes for T: WF, we get back that
@@ -76,8 +80,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
76
80
// than the ultimate set. (Note: normally there won't be
77
81
// unresolved inference variables here anyway, but there might be
78
82
// during typeck under some circumstances.)
79
- let obligations =
80
- wf:: obligations ( self , param_env, body_id, ty, span) . unwrap_or ( vec ! [ ] ) ;
83
+ let obligations = wf:: obligations ( self , param_env, body_id, ty, span) . unwrap_or ( vec ! [ ] ) ;
81
84
82
85
// NB: All of these predicates *ought* to be easily proven
83
86
// true. In fact, their correctness is (mostly) implied by
@@ -105,7 +108,8 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
105
108
obligations
106
109
. iter ( )
107
110
. filter ( |o| o. predicate . has_infer_types ( ) )
108
- . cloned ( ) ) ;
111
+ . cloned ( ) ,
112
+ ) ;
109
113
110
114
// From the full set of obligations, just filter down to the
111
115
// region relationships.
@@ -125,25 +129,21 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
125
129
vec ! [ ]
126
130
}
127
131
128
- ty:: Predicate :: RegionOutlives ( ref data) => {
129
- match data. no_late_bound_regions ( ) {
130
- None => vec ! [ ] ,
131
- Some ( ty:: OutlivesPredicate ( r_a, r_b) ) => {
132
- vec ! [ ImpliedBound :: RegionSubRegion ( r_b, r_a) ]
133
- }
132
+ ty:: Predicate :: RegionOutlives ( ref data) => match data. no_late_bound_regions ( ) {
133
+ None => vec ! [ ] ,
134
+ Some ( ty:: OutlivesPredicate ( r_a, r_b) ) => {
135
+ vec ! [ OutlivesBound :: RegionSubRegion ( r_b, r_a) ]
134
136
}
135
- }
137
+ } ,
136
138
137
- ty:: Predicate :: TypeOutlives ( ref data) => {
138
- match data. no_late_bound_regions ( ) {
139
- None => vec ! [ ] ,
140
- Some ( ty:: OutlivesPredicate ( ty_a, r_b) ) => {
141
- let ty_a = self . resolve_type_vars_if_possible ( & ty_a) ;
142
- let components = tcx. outlives_components ( ty_a) ;
143
- Self :: implied_bounds_from_components ( r_b, components)
144
- }
139
+ ty:: Predicate :: TypeOutlives ( ref data) => match data. no_late_bound_regions ( ) {
140
+ None => vec ! [ ] ,
141
+ Some ( ty:: OutlivesPredicate ( ty_a, r_b) ) => {
142
+ let ty_a = self . resolve_type_vars_if_possible ( & ty_a) ;
143
+ let components = tcx. outlives_components ( ty_a) ;
144
+ Self :: implied_bounds_from_components ( r_b, components)
145
145
}
146
- }
146
+ } ,
147
147
}
148
148
} ) ) ;
149
149
}
@@ -165,17 +165,17 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
165
165
fn implied_bounds_from_components (
166
166
sub_region : ty:: Region < ' tcx > ,
167
167
sup_components : Vec < Component < ' tcx > > ,
168
- ) -> Vec < ImpliedBound < ' tcx > > {
168
+ ) -> Vec < OutlivesBound < ' tcx > > {
169
169
sup_components
170
170
. into_iter ( )
171
171
. flat_map ( |component| {
172
172
match component {
173
173
Component :: Region ( r) =>
174
- vec ! [ ImpliedBound :: RegionSubRegion ( sub_region, r) ] ,
174
+ vec ! [ OutlivesBound :: RegionSubRegion ( sub_region, r) ] ,
175
175
Component :: Param ( p) =>
176
- vec ! [ ImpliedBound :: RegionSubParam ( sub_region, p) ] ,
176
+ vec ! [ OutlivesBound :: RegionSubParam ( sub_region, p) ] ,
177
177
Component :: Projection ( p) =>
178
- vec ! [ ImpliedBound :: RegionSubProjection ( sub_region, p) ] ,
178
+ vec ! [ OutlivesBound :: RegionSubProjection ( sub_region, p) ] ,
179
179
Component :: EscapingProjection ( _) =>
180
180
// If the projection has escaping regions, don't
181
181
// try to infer any implied bounds even for its
@@ -193,3 +193,26 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
193
193
. collect ( )
194
194
}
195
195
}
196
+
197
+ pub fn explicit_outlives_bounds < ' tcx > (
198
+ param_env : ty:: ParamEnv < ' tcx > ,
199
+ ) -> impl Iterator < Item = OutlivesBound < ' tcx > > + ' tcx {
200
+ debug ! ( "explicit_outlives_bounds()" ) ;
201
+ param_env
202
+ . caller_bounds
203
+ . into_iter ( )
204
+ . filter_map ( move |predicate| match predicate {
205
+ ty:: Predicate :: Projection ( ..) |
206
+ ty:: Predicate :: Trait ( ..) |
207
+ ty:: Predicate :: Equate ( ..) |
208
+ ty:: Predicate :: Subtype ( ..) |
209
+ ty:: Predicate :: WellFormed ( ..) |
210
+ ty:: Predicate :: ObjectSafe ( ..) |
211
+ ty:: Predicate :: ClosureKind ( ..) |
212
+ ty:: Predicate :: TypeOutlives ( ..) |
213
+ ty:: Predicate :: ConstEvaluatable ( ..) => None ,
214
+ ty:: Predicate :: RegionOutlives ( ref data) => data. no_late_bound_regions ( ) . map (
215
+ |ty:: OutlivesPredicate ( r_a, r_b) | OutlivesBound :: RegionSubRegion ( r_b, r_a) ,
216
+ ) ,
217
+ } )
218
+ }
0 commit comments