1
1
use crate :: infer:: outlives:: env:: RegionBoundPairs ;
2
+ use crate :: infer:: region_constraints:: VerifyIfEq ;
2
3
use crate :: infer:: { GenericKind , VerifyBound } ;
3
4
use rustc_data_structures:: captures:: Captures ;
4
5
use rustc_data_structures:: sso:: SsoHashSet ;
@@ -82,25 +83,39 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
82
83
debug ! ( "param_bound(param_ty={:?})" , param_ty) ;
83
84
84
85
// 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
+ }
88
100
89
101
// Add in the default bound of fn body that applies to all in
90
102
// 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
+ }
94
106
95
- if any_bounds . is_empty ( ) {
107
+ if param_bounds . is_empty ( ) {
96
108
// We know that all types `T` outlive `'empty`, so if we
97
109
// can find no other bound, then check that the region
98
110
// being tested is `'empty`.
99
111
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 ( )
100
115
} else {
101
116
// If we can find any other bound `R` such that `T: R`, then
102
117
// we don't need to check for `'empty`, because `R: 'empty`.
103
- VerifyBound :: AnyBound ( any_bounds )
118
+ VerifyBound :: AnyBound ( param_bounds )
104
119
}
105
120
}
106
121
@@ -120,7 +135,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
120
135
pub fn projection_approx_declared_bounds_from_env (
121
136
& self ,
122
137
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 > > > > {
124
139
let projection_ty = GenericKind :: Projection ( projection_ty) . to_ty ( self . tcx ) ;
125
140
let erased_projection_ty = self . tcx . erase_regions ( projection_ty) ;
126
141
self . declared_generic_bounds_from_env_for_erased_ty ( erased_projection_ty)
@@ -150,14 +165,15 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
150
165
let env_bounds = self
151
166
. projection_approx_declared_bounds_from_env ( projection_ty)
152
167
. 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 {
155
170
// Micro-optimize if this is an exact match (this
156
171
// occurs often when there are no region variables
157
172
// involved).
158
173
VerifyBound :: OutlivedBy ( r)
159
174
} 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)
161
177
}
162
178
} ) ;
163
179
@@ -210,7 +226,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
210
226
fn declared_generic_bounds_from_env (
211
227
& self ,
212
228
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 > > > > {
214
230
let generic_ty = param_ty. to_ty ( self . tcx ) ;
215
231
self . declared_generic_bounds_from_env_for_erased_ty ( generic_ty)
216
232
}
@@ -229,7 +245,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
229
245
fn declared_generic_bounds_from_env_for_erased_ty (
230
246
& self ,
231
247
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 > > > > {
233
249
let tcx = self . tcx ;
234
250
235
251
// To start, collect bounds from user environment. Note that
@@ -259,7 +275,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
259
275
) ;
260
276
let p_ty = p. to_ty ( tcx) ;
261
277
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) ) )
263
280
} ) ;
264
281
265
282
param_bounds
@@ -348,11 +365,17 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
348
365
& self ,
349
366
erased_ty : Ty < ' tcx > ,
350
367
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
+ {
352
370
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
+ } )
357
380
}
358
381
}
0 commit comments