@@ -3,11 +3,9 @@ use crate::infer::{GenericKind, VerifyBound};
3
3
use crate :: traits;
4
4
use rustc_data_structures:: captures:: Captures ;
5
5
use rustc_hir:: def_id:: DefId ;
6
- use rustc_middle:: ty:: subst:: { InternalSubsts , Subst } ;
6
+ use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , InternalSubsts , Subst } ;
7
7
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
8
8
9
- use smallvec:: smallvec;
10
-
11
9
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
12
10
/// obligation into a series of `'a: 'b` constraints and "verifys", as
13
11
/// described on the module comment. The final constraints are emitted
@@ -44,7 +42,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
44
42
match ty. kind {
45
43
ty:: Param ( p) => self . param_bound ( p) ,
46
44
ty:: Projection ( data) => self . projection_bound ( data) ,
47
- _ => self . recursive_type_bound ( ty) ,
45
+ _ => self . recursive_bound ( ty. into ( ) ) ,
48
46
}
49
47
}
50
48
@@ -144,25 +142,33 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
144
142
145
143
// see the extensive comment in projection_must_outlive
146
144
let ty = self . tcx . mk_projection ( projection_ty. item_def_id , projection_ty. substs ) ;
147
- let recursive_bound = self . recursive_type_bound ( ty) ;
145
+ let recursive_bound = self . recursive_bound ( ty. into ( ) ) ;
148
146
149
147
VerifyBound :: AnyBound ( env_bounds. chain ( trait_bounds) . collect ( ) ) . or ( recursive_bound)
150
148
}
151
149
152
- fn recursive_type_bound ( & self , ty : Ty < ' tcx > ) -> VerifyBound < ' tcx > {
153
- let mut bounds = ty. walk_shallow ( ) . map ( |subty| self . type_bound ( subty) ) . collect :: < Vec < _ > > ( ) ;
154
-
155
- let mut regions = smallvec ! [ ] ;
156
- ty. push_regions ( & mut regions) ;
157
- regions. retain ( |r| !r. is_late_bound ( ) ) ; // ignore late-bound regions
158
- bounds. push ( VerifyBound :: AllBounds (
159
- regions. into_iter ( ) . map ( |r| VerifyBound :: OutlivedBy ( r) ) . collect ( ) ,
160
- ) ) ;
161
-
162
- // remove bounds that must hold, since they are not interesting
163
- bounds. retain ( |b| !b. must_hold ( ) ) ;
150
+ fn recursive_bound ( & self , parent : GenericArg < ' tcx > ) -> VerifyBound < ' tcx > {
151
+ let mut bounds = parent
152
+ . walk_shallow ( )
153
+ . filter_map ( |child| match child. unpack ( ) {
154
+ GenericArgKind :: Type ( ty) => Some ( self . type_bound ( ty) ) ,
155
+ GenericArgKind :: Lifetime ( lt) => {
156
+ // Ignore late-bound regions.
157
+ if !lt. is_late_bound ( ) { Some ( VerifyBound :: OutlivedBy ( lt) ) } else { None }
158
+ }
159
+ GenericArgKind :: Const ( _) => Some ( self . recursive_bound ( child) ) ,
160
+ } )
161
+ . filter ( |bound| {
162
+ // Remove bounds that must hold, since they are not interesting.
163
+ !bound. must_hold ( )
164
+ } ) ;
164
165
165
- if bounds. len ( ) == 1 { bounds. pop ( ) . unwrap ( ) } else { VerifyBound :: AllBounds ( bounds) }
166
+ match ( bounds. next ( ) , bounds. next ( ) ) {
167
+ ( Some ( first) , None ) => first,
168
+ ( first, second) => {
169
+ VerifyBound :: AllBounds ( first. into_iter ( ) . chain ( second) . chain ( bounds) . collect ( ) )
170
+ }
171
+ }
166
172
}
167
173
168
174
/// Searches the environment for where-clauses like `G: 'a` where
0 commit comments