1
+ use crate :: infer:: outlives:: components:: { compute_components_recursive, Component } ;
1
2
use crate :: infer:: outlives:: env:: RegionBoundPairs ;
2
3
use crate :: infer:: region_constraints:: VerifyIfEq ;
3
4
use crate :: infer:: { GenericKind , VerifyBound } ;
4
5
use rustc_data_structures:: captures:: Captures ;
5
6
use rustc_data_structures:: sso:: SsoHashSet ;
6
7
use rustc_hir:: def_id:: DefId ;
7
- use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , Subst } ;
8
+ use rustc_middle:: ty:: subst:: { GenericArg , Subst } ;
8
9
use rustc_middle:: ty:: { self , EarlyBinder , Ty , TyCtxt } ;
9
10
11
+ use smallvec:: smallvec;
12
+
10
13
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
11
14
/// obligation into a series of `'a: 'b` constraints and "verifys", as
12
15
/// described on the module comment. The final constraints are emitted
@@ -47,43 +50,6 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
47
50
}
48
51
}
49
52
50
- fn type_bound (
51
- & self ,
52
- ty : Ty < ' tcx > ,
53
- visited : & mut SsoHashSet < GenericArg < ' tcx > > ,
54
- ) -> VerifyBound < ' tcx > {
55
- match * ty. kind ( ) {
56
- ty:: Param ( p) => self . param_bound ( p) ,
57
- ty:: Projection ( data) => self . projection_bound ( data, visited) ,
58
- ty:: FnDef ( _, substs) => {
59
- // HACK(eddyb) ignore lifetimes found shallowly in `substs`.
60
- // This is inconsistent with `ty::Adt` (including all substs),
61
- // but consistent with previous (accidental) behavior.
62
- // See https://github.com/rust-lang/rust/issues/70917
63
- // for further background and discussion.
64
- let mut bounds = substs
65
- . iter ( )
66
- . filter_map ( |child| match child. unpack ( ) {
67
- GenericArgKind :: Type ( ty) => Some ( self . type_bound ( ty, visited) ) ,
68
- GenericArgKind :: Lifetime ( _) => None ,
69
- GenericArgKind :: Const ( _) => Some ( self . recursive_bound ( child, visited) ) ,
70
- } )
71
- . filter ( |bound| {
72
- // Remove bounds that must hold, since they are not interesting.
73
- !bound. must_hold ( )
74
- } ) ;
75
-
76
- match ( bounds. next ( ) , bounds. next ( ) ) {
77
- ( Some ( first) , None ) => first,
78
- ( first, second) => VerifyBound :: AllBounds (
79
- first. into_iter ( ) . chain ( second) . chain ( bounds) . collect ( ) ,
80
- ) ,
81
- }
82
- }
83
- _ => self . recursive_bound ( ty. into ( ) , visited) ,
84
- }
85
- }
86
-
87
53
fn param_bound ( & self , param_ty : ty:: ParamTy ) -> VerifyBound < ' tcx > {
88
54
debug ! ( "param_bound(param_ty={:?})" , param_ty) ;
89
55
@@ -188,27 +154,24 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
188
154
. map ( |r| VerifyBound :: OutlivedBy ( r) ) ;
189
155
190
156
// see the extensive comment in projection_must_outlive
191
- let ty = self . tcx . mk_projection ( projection_ty. item_def_id , projection_ty. substs ) ;
192
- let recursive_bound = self . recursive_bound ( ty. into ( ) , visited) ;
157
+ let recursive_bound = {
158
+ let mut components = smallvec ! [ ] ;
159
+ let ty = self . tcx . mk_projection ( projection_ty. item_def_id , projection_ty. substs ) ;
160
+ compute_components_recursive ( self . tcx , ty. into ( ) , & mut components, visited) ;
161
+ self . bound_from_components ( & components, visited)
162
+ } ;
193
163
194
164
VerifyBound :: AnyBound ( env_bounds. chain ( trait_bounds) . collect ( ) ) . or ( recursive_bound)
195
165
}
196
166
197
- fn recursive_bound (
167
+ fn bound_from_components (
198
168
& self ,
199
- parent : GenericArg < ' tcx > ,
169
+ components : & [ Component < ' tcx > ] ,
200
170
visited : & mut SsoHashSet < GenericArg < ' tcx > > ,
201
171
) -> VerifyBound < ' tcx > {
202
- let mut bounds = parent
203
- . walk_shallow ( visited)
204
- . filter_map ( |child| match child. unpack ( ) {
205
- GenericArgKind :: Type ( ty) => Some ( self . type_bound ( ty, visited) ) ,
206
- GenericArgKind :: Lifetime ( lt) => {
207
- // Ignore late-bound regions.
208
- if !lt. is_late_bound ( ) { Some ( VerifyBound :: OutlivedBy ( lt) ) } else { None }
209
- }
210
- GenericArgKind :: Const ( _) => Some ( self . recursive_bound ( child, visited) ) ,
211
- } )
172
+ let mut bounds = components
173
+ . iter ( )
174
+ . map ( |component| self . bound_from_single_component ( component, visited) )
212
175
. filter ( |bound| {
213
176
// Remove bounds that must hold, since they are not interesting.
214
177
!bound. must_hold ( )
@@ -222,6 +185,32 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
222
185
}
223
186
}
224
187
188
+ fn bound_from_single_component (
189
+ & self ,
190
+ component : & Component < ' tcx > ,
191
+ visited : & mut SsoHashSet < GenericArg < ' tcx > > ,
192
+ ) -> VerifyBound < ' tcx > {
193
+ match * component {
194
+ Component :: Region ( lt) => VerifyBound :: OutlivedBy ( lt) ,
195
+ Component :: Param ( param_ty) => self . param_bound ( param_ty) ,
196
+ Component :: Projection ( projection_ty) => self . projection_bound ( projection_ty, visited) ,
197
+ Component :: EscapingProjection ( ref components) => {
198
+ self . bound_from_components ( components, visited)
199
+ }
200
+ Component :: UnresolvedInferenceVariable ( v) => {
201
+ // ignore this, we presume it will yield an error
202
+ // later, since if a type variable is not resolved by
203
+ // this point it never will be
204
+ self . tcx . sess . delay_span_bug (
205
+ rustc_span:: DUMMY_SP ,
206
+ & format ! ( "unresolved inference variable in outlives: {:?}" , v) ,
207
+ ) ;
208
+ // add a bound that never holds
209
+ VerifyBound :: AnyBound ( vec ! [ ] )
210
+ }
211
+ }
212
+ }
213
+
225
214
/// Searches the environment for where-clauses like `G: 'a` where
226
215
/// `G` is either some type parameter `T` or a projection like
227
216
/// `T::Item`. Returns a vector of the `'a` bounds it can find.
0 commit comments