@@ -14,6 +14,7 @@ use infer::{GenericKind, VerifyBound};
1414use traits;
1515use ty:: subst:: { Subst , Substs } ;
1616use ty:: { self , Ty , TyCtxt } ;
17+ use util:: captures:: Captures ;
1718
1819/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
1920/// obligation into a series of `'a: 'b` constraints and "verifys", as
@@ -65,21 +66,15 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
6566
6667 // Start with anything like `T: 'a` we can scrape from the
6768 // environment
68- let param_bounds =
69- self . declared_generic_bounds_from_env ( GenericKind :: Param ( param_ty ) )
70- . into_iter ( ) ;
69+ let param_bounds = self . declared_generic_bounds_from_env ( GenericKind :: Param ( param_ty ) )
70+ . into_iter ( )
71+ . map ( |outlives| outlives . 1 ) ;
7172
7273 // Add in the default bound of fn body that applies to all in
7374 // scope type parameters:
74- let param_bounds =
75- param_bounds
76- . chain ( self . implicit_region_bound ) ;
75+ let param_bounds = param_bounds. chain ( self . implicit_region_bound ) ;
7776
78- VerifyBound :: AnyBound (
79- param_bounds
80- . map ( |r| VerifyBound :: OutlivedBy ( r) )
81- . collect ( )
82- )
77+ VerifyBound :: AnyBound ( param_bounds. map ( |r| VerifyBound :: OutlivedBy ( r) ) . collect ( ) )
8378 }
8479
8580 /// Given a projection like `T::Item`, searches the environment
@@ -98,7 +93,7 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
9893 pub fn projection_approx_declared_bounds_from_env (
9994 & self ,
10095 projection_ty : ty:: ProjectionTy < ' tcx > ,
101- ) -> Vec < ty:: Region < ' tcx > > {
96+ ) -> Vec < ty:: OutlivesPredicate < Ty < ' tcx > , ty :: Region < ' tcx > > > {
10297 let projection_ty = GenericKind :: Projection ( projection_ty) . to_ty ( self . tcx ) ;
10398 let erased_projection_ty = self . tcx . erase_regions ( & projection_ty) ;
10499 self . declared_generic_bounds_from_env_with_compare_fn ( |ty| {
@@ -117,31 +112,42 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
117112 pub fn projection_declared_bounds_from_trait (
118113 & self ,
119114 projection_ty : ty:: ProjectionTy < ' tcx > ,
120- ) -> Vec < ty:: Region < ' tcx > > {
115+ ) -> impl Iterator < Item = ty:: Region < ' tcx > > + ' cx + Captures < ' gcx > {
121116 self . declared_projection_bounds_from_trait ( projection_ty)
122117 }
123118
124119 pub fn projection_bound ( & self , projection_ty : ty:: ProjectionTy < ' tcx > ) -> VerifyBound < ' tcx > {
125120 debug ! ( "projection_bound(projection_ty={:?})" , projection_ty) ;
126121
122+ let projection_ty_as_ty =
123+ self . tcx . mk_projection ( projection_ty. item_def_id , projection_ty. substs ) ;
124+
127125 // Search the env for where clauses like `P: 'a`.
128- let env_bounds =
129- self . declared_generic_bounds_from_env ( GenericKind :: Projection ( projection_ty) )
130- . into_iter ( ) ;
126+ let env_bounds = self . projection_approx_declared_bounds_from_env ( projection_ty)
127+ . into_iter ( )
128+ . map ( |ty:: OutlivesPredicate ( ty, r) | {
129+ let vb = VerifyBound :: OutlivedBy ( r) ;
130+ if ty == projection_ty_as_ty {
131+ // Micro-optimize if this is an exact match (this
132+ // occurs often when there are no region variables
133+ // involved).
134+ vb
135+ } else {
136+ VerifyBound :: IfEq ( ty, Box :: new ( vb) )
137+ }
138+ } ) ;
131139
132140 // Extend with bounds that we can find from the trait.
133- let trait_bounds =
134- self . projection_declared_bounds_from_trait ( projection_ty )
135- . into_iter ( ) ;
141+ let trait_bounds = self . projection_declared_bounds_from_trait ( projection_ty )
142+ . into_iter ( )
143+ . map ( |r| VerifyBound :: OutlivedBy ( r ) ) ;
136144
137145 // see the extensive comment in projection_must_outlive
138146 let ty = self . tcx
139147 . mk_projection ( projection_ty. item_def_id , projection_ty. substs ) ;
140148 let recursive_bound = self . recursive_type_bound ( ty) ;
141149
142- VerifyBound :: AnyBound (
143- env_bounds. chain ( trait_bounds) . map ( |r| VerifyBound :: OutlivedBy ( r) ) . collect ( )
144- ) . or ( recursive_bound)
150+ VerifyBound :: AnyBound ( env_bounds. chain ( trait_bounds) . collect ( ) ) . or ( recursive_bound)
145151 }
146152
147153 fn recursive_type_bound ( & self , ty : Ty < ' tcx > ) -> VerifyBound < ' tcx > {
@@ -151,11 +157,12 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
151157
152158 let mut regions = ty. regions ( ) ;
153159 regions. retain ( |r| !r. is_late_bound ( ) ) ; // ignore late-bound regions
154- bounds. push (
155- VerifyBound :: AllBounds (
156- regions. into_iter ( ) . map ( |r| VerifyBound :: OutlivedBy ( r) ) . collect ( )
157- )
158- ) ;
160+ bounds. push ( VerifyBound :: AllBounds (
161+ regions
162+ . into_iter ( )
163+ . map ( |r| VerifyBound :: OutlivedBy ( r) )
164+ . collect ( ) ,
165+ ) ) ;
159166
160167 // remove bounds that must hold, since they are not interesting
161168 bounds. retain ( |b| !b. must_hold ( ) ) ;
@@ -176,15 +183,15 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
176183 fn declared_generic_bounds_from_env (
177184 & self ,
178185 generic : GenericKind < ' tcx > ,
179- ) -> Vec < ty:: Region < ' tcx > > {
186+ ) -> Vec < ty:: OutlivesPredicate < Ty < ' tcx > , ty :: Region < ' tcx > > > {
180187 let generic_ty = generic. to_ty ( self . tcx ) ;
181188 self . declared_generic_bounds_from_env_with_compare_fn ( |ty| ty == generic_ty)
182189 }
183190
184191 fn declared_generic_bounds_from_env_with_compare_fn (
185192 & self ,
186193 compare_ty : impl Fn ( Ty < ' tcx > ) -> bool ,
187- ) -> Vec < ty:: Region < ' tcx > > {
194+ ) -> Vec < ty:: OutlivesPredicate < Ty < ' tcx > , ty :: Region < ' tcx > > > {
188195 let tcx = self . tcx ;
189196
190197 // To start, collect bounds from user environment. Note that
@@ -212,14 +219,23 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
212219 "declared_generic_bounds_from_env_with_compare_fn: region_bound_pair = {:?}" ,
213220 ( r, p)
214221 ) ;
215- if compare_ty ( p. to_ty ( tcx) ) {
216- Some ( r)
222+ let p_ty = p. to_ty ( tcx) ;
223+ if compare_ty ( p_ty) {
224+ Some ( ty:: OutlivesPredicate ( p_ty, r) )
217225 } else {
218226 None
219227 }
220228 } ) ;
221229
222- param_bounds. chain ( from_region_bound_pairs) . collect ( )
230+ param_bounds
231+ . chain ( from_region_bound_pairs)
232+ . inspect ( |bound| {
233+ debug ! (
234+ "declared_generic_bounds_from_env_with_compare_fn: result predicate = {:?}" ,
235+ bound
236+ )
237+ } )
238+ . collect ( )
223239 }
224240
225241 /// Given a projection like `<T as Foo<'x>>::Bar`, returns any bounds
@@ -237,13 +253,11 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
237253 fn declared_projection_bounds_from_trait (
238254 & self ,
239255 projection_ty : ty:: ProjectionTy < ' tcx > ,
240- ) -> Vec < ty:: Region < ' tcx > > {
256+ ) -> impl Iterator < Item = ty:: Region < ' tcx > > + ' cx + Captures < ' gcx > {
241257 debug ! ( "projection_bounds(projection_ty={:?})" , projection_ty) ;
242- let mut bounds = self . region_bounds_declared_on_associated_item ( projection_ty. item_def_id ) ;
243- for r in & mut bounds {
244- * r = r. subst ( self . tcx , projection_ty. substs ) ;
245- }
246- bounds
258+ let tcx = self . tcx ;
259+ self . region_bounds_declared_on_associated_item ( projection_ty. item_def_id )
260+ . map ( move |r| r. subst ( tcx, projection_ty. substs ) )
247261 }
248262
249263 /// Given the def-id of an associated item, returns any region
@@ -279,7 +293,7 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
279293 fn region_bounds_declared_on_associated_item (
280294 & self ,
281295 assoc_item_def_id : DefId ,
282- ) -> Vec < ty:: Region < ' tcx > > {
296+ ) -> impl Iterator < Item = ty:: Region < ' tcx > > + ' cx + Captures < ' gcx > {
283297 let tcx = self . tcx ;
284298 let assoc_item = tcx. associated_item ( assoc_item_def_id) ;
285299 let trait_def_id = assoc_item. container . assert_trait ( ) ;
@@ -289,7 +303,7 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
289303 self . collect_outlives_from_predicate_list (
290304 move |ty| ty == identity_proj,
291305 traits:: elaborate_predicates ( tcx, trait_predicates. predicates ) ,
292- ) . collect ( )
306+ ) . map ( |b| b . 1 )
293307 }
294308
295309 /// Searches through a predicate list for a predicate `T: 'a`.
@@ -302,12 +316,11 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
302316 & self ,
303317 compare_ty : impl Fn ( Ty < ' tcx > ) -> bool ,
304318 predicates : impl IntoIterator < Item = impl AsRef < ty:: Predicate < ' tcx > > > ,
305- ) -> impl Iterator < Item = ty:: Region < ' tcx > > {
319+ ) -> impl Iterator < Item = ty:: OutlivesPredicate < Ty < ' tcx > , ty :: Region < ' tcx > > > {
306320 predicates
307321 . into_iter ( )
308322 . filter_map ( |p| p. as_ref ( ) . to_opt_type_outlives ( ) )
309323 . filter_map ( |p| p. no_late_bound_regions ( ) )
310324 . filter ( move |p| compare_ty ( p. 0 ) )
311- . map ( |p| p. 1 )
312325 }
313326}
0 commit comments