11use crate :: infer:: outlives:: env:: RegionBoundPairs ;
2+ use crate :: infer:: region_constraints:: VerifyIfEq ;
23use crate :: infer:: { GenericKind , VerifyBound } ;
34use rustc_data_structures:: captures:: Captures ;
45use rustc_data_structures:: sso:: SsoHashSet ;
@@ -82,25 +83,39 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
8283 debug ! ( "param_bound(param_ty={:?})" , param_ty) ;
8384
8485 // Start with anything like `T: 'a` we can scrape from the
85- // environment
86- let param_bounds =
87- self . declared_generic_bounds_from_env ( param_ty) . into_iter ( ) . map ( |outlives| outlives. 1 ) ;
86+ // environment. If the environment contains something like
87+ // `for<'a> T: 'a`, then we know that `T` outlives everything.
88+ let declared_bounds_from_env = self . declared_generic_bounds_from_env ( param_ty) ;
89+ let mut param_bounds = vec ! [ ] ;
90+ for declared_bound in declared_bounds_from_env {
91+ let bound_region = declared_bound. map_bound ( |outlives| outlives. 1 ) ;
92+ if let Some ( region) = bound_region. no_bound_vars ( ) {
93+ // This is `T: 'a` for some free region `'a`.
94+ param_bounds. push ( VerifyBound :: OutlivedBy ( region) ) ;
95+ } else {
96+ // This is `for<'a> T: 'a`. This means that `T` outlives everything! All done here.
97+ return VerifyBound :: AllBounds ( vec ! [ ] ) ;
98+ }
99+ }
88100
89101 // Add in the default bound of fn body that applies to all in
90102 // scope type parameters:
91- let param_bounds = param_bounds . chain ( self . implicit_region_bound ) ;
92-
93- let any_bounds : Vec < _ > = param_bounds . map ( |r| VerifyBound :: OutlivedBy ( r ) ) . collect ( ) ;
103+ if let Some ( r ) = self . implicit_region_bound {
104+ param_bounds . push ( VerifyBound :: OutlivedBy ( r ) ) ;
105+ }
94106
95- if any_bounds . is_empty ( ) {
107+ if param_bounds . is_empty ( ) {
96108 // We know that all types `T` outlive `'empty`, so if we
97109 // can find no other bound, then check that the region
98110 // being tested is `'empty`.
99111 VerifyBound :: IsEmpty
112+ } else if param_bounds. len ( ) == 1 {
113+ // Micro-opt: no need to store the vector if it's just len 1
114+ param_bounds. pop ( ) . unwrap ( )
100115 } else {
101116 // If we can find any other bound `R` such that `T: R`, then
102117 // we don't need to check for `'empty`, because `R: 'empty`.
103- VerifyBound :: AnyBound ( any_bounds )
118+ VerifyBound :: AnyBound ( param_bounds )
104119 }
105120 }
106121
@@ -120,7 +135,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
120135 pub fn projection_approx_declared_bounds_from_env (
121136 & self ,
122137 projection_ty : ty:: ProjectionTy < ' tcx > ,
123- ) -> Vec < ty:: OutlivesPredicate < Ty < ' tcx > , ty:: Region < ' tcx > > > {
138+ ) -> Vec < ty:: Binder < ' tcx , ty :: OutlivesPredicate < Ty < ' tcx > , ty:: Region < ' tcx > > > > {
124139 let projection_ty = GenericKind :: Projection ( projection_ty) . to_ty ( self . tcx ) ;
125140 let erased_projection_ty = self . tcx . erase_regions ( projection_ty) ;
126141 self . declared_generic_bounds_from_env_for_erased_ty ( erased_projection_ty)
@@ -150,14 +165,15 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
150165 let env_bounds = self
151166 . projection_approx_declared_bounds_from_env ( projection_ty)
152167 . into_iter ( )
153- . map ( |ty :: OutlivesPredicate ( ty , r ) | {
154- if ty == projection_ty_as_ty {
168+ . map ( |binder | {
169+ if let Some ( ty :: OutlivesPredicate ( ty , r ) ) = binder . no_bound_vars ( ) && ty == projection_ty_as_ty {
155170 // Micro-optimize if this is an exact match (this
156171 // occurs often when there are no region variables
157172 // involved).
158173 VerifyBound :: OutlivedBy ( r)
159174 } else {
160- VerifyBound :: IfEq ( ty, r)
175+ let verify_if_eq_b = binder. map_bound ( |ty:: OutlivesPredicate ( ty, bound) | VerifyIfEq { ty, bound } ) ;
176+ VerifyBound :: IfEqBound ( verify_if_eq_b)
161177 }
162178 } ) ;
163179
@@ -210,7 +226,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
210226 fn declared_generic_bounds_from_env (
211227 & self ,
212228 param_ty : ty:: ParamTy ,
213- ) -> Vec < ty:: OutlivesPredicate < Ty < ' tcx > , ty:: Region < ' tcx > > > {
229+ ) -> Vec < ty:: Binder < ' tcx , ty :: OutlivesPredicate < Ty < ' tcx > , ty:: Region < ' tcx > > > > {
214230 let generic_ty = param_ty. to_ty ( self . tcx ) ;
215231 self . declared_generic_bounds_from_env_for_erased_ty ( generic_ty)
216232 }
@@ -229,7 +245,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
229245 fn declared_generic_bounds_from_env_for_erased_ty (
230246 & self ,
231247 erased_ty : Ty < ' tcx > ,
232- ) -> Vec < ty:: OutlivesPredicate < Ty < ' tcx > , ty:: Region < ' tcx > > > {
248+ ) -> Vec < ty:: Binder < ' tcx , ty :: OutlivesPredicate < Ty < ' tcx > , ty:: Region < ' tcx > > > > {
233249 let tcx = self . tcx ;
234250
235251 // To start, collect bounds from user environment. Note that
@@ -259,7 +275,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
259275 ) ;
260276 let p_ty = p. to_ty ( tcx) ;
261277 let erased_p_ty = self . tcx . erase_regions ( p_ty) ;
262- ( erased_p_ty == erased_ty) . then_some ( ty:: OutlivesPredicate ( p. to_ty ( tcx) , r) )
278+ ( erased_p_ty == erased_ty)
279+ . then_some ( ty:: Binder :: dummy ( ty:: OutlivesPredicate ( p. to_ty ( tcx) , r) ) )
263280 } ) ;
264281
265282 param_bounds
@@ -348,11 +365,17 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
348365 & self ,
349366 erased_ty : Ty < ' tcx > ,
350367 predicates : impl Iterator < Item = ty:: Predicate < ' tcx > > ,
351- ) -> impl Iterator < Item = ty:: OutlivesPredicate < Ty < ' tcx > , ty:: Region < ' tcx > > > {
368+ ) -> impl Iterator < Item = ty:: Binder < ' tcx , ty:: OutlivesPredicate < Ty < ' tcx > , ty:: Region < ' tcx > > > >
369+ {
352370 let tcx = self . tcx ;
353- predicates
354- . filter_map ( |p| p. to_opt_type_outlives ( ) )
355- . filter_map ( |p| p. no_bound_vars ( ) )
356- . filter ( move |p| tcx. erase_regions ( p. 0 ) == erased_ty)
371+ let param_env = self . param_env ;
372+ predicates. filter_map ( |p| p. to_opt_type_outlives ( ) ) . filter ( move |outlives_predicate| {
373+ super :: test_type_match:: can_match_erased_ty (
374+ tcx,
375+ param_env,
376+ * outlives_predicate,
377+ erased_ty,
378+ )
379+ } )
357380 }
358381}
0 commit comments