@@ -3,11 +3,9 @@ use crate::infer::{GenericKind, VerifyBound};
33use crate :: traits;
44use rustc_data_structures:: captures:: Captures ;
55use rustc_hir:: def_id:: DefId ;
6- use rustc_middle:: ty:: subst:: { InternalSubsts , Subst } ;
6+ use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , InternalSubsts , Subst } ;
77use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
88
9- use smallvec:: smallvec;
10-
119/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
1210/// obligation into a series of `'a: 'b` constraints and "verifys", as
1311/// described on the module comment. The final constraints are emitted
@@ -44,7 +42,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
4442 match ty. kind {
4543 ty:: Param ( p) => self . param_bound ( p) ,
4644 ty:: Projection ( data) => self . projection_bound ( data) ,
47- _ => self . recursive_type_bound ( ty) ,
45+ _ => self . recursive_bound ( ty. into ( ) ) ,
4846 }
4947 }
5048
@@ -144,25 +142,33 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
144142
145143 // see the extensive comment in projection_must_outlive
146144 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 ( ) ) ;
148146
149147 VerifyBound :: AnyBound ( env_bounds. chain ( trait_bounds) . collect ( ) ) . or ( recursive_bound)
150148 }
151149
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+ } ) ;
164165
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+ }
166172 }
167173
168174 /// Searches the environment for where-clauses like `G: 'a` where
0 commit comments