1+ use crate :: infer:: outlives:: components:: { compute_components_recursive, Component } ;
12use crate :: infer:: outlives:: env:: RegionBoundPairs ;
23use crate :: infer:: region_constraints:: VerifyIfEq ;
34use crate :: infer:: { GenericKind , VerifyBound } ;
45use rustc_data_structures:: captures:: Captures ;
56use rustc_data_structures:: sso:: SsoHashSet ;
67use rustc_hir:: def_id:: DefId ;
7- use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , Subst } ;
8+ use rustc_middle:: ty:: subst:: { GenericArg , Subst } ;
89use rustc_middle:: ty:: { self , EarlyBinder , Ty , TyCtxt } ;
910
11+ use smallvec:: smallvec;
12+
1013/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
1114/// obligation into a series of `'a: 'b` constraints and "verifys", as
1215/// described on the module comment. The final constraints are emitted
@@ -47,43 +50,6 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
4750 }
4851 }
4952
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-
8753 fn param_bound ( & self , param_ty : ty:: ParamTy ) -> VerifyBound < ' tcx > {
8854 debug ! ( "param_bound(param_ty={:?})" , param_ty) ;
8955
@@ -188,27 +154,24 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
188154 . map ( |r| VerifyBound :: OutlivedBy ( r) ) ;
189155
190156 // 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+ } ;
193163
194164 VerifyBound :: AnyBound ( env_bounds. chain ( trait_bounds) . collect ( ) ) . or ( recursive_bound)
195165 }
196166
197- fn recursive_bound (
167+ fn bound_from_components (
198168 & self ,
199- parent : GenericArg < ' tcx > ,
169+ components : & [ Component < ' tcx > ] ,
200170 visited : & mut SsoHashSet < GenericArg < ' tcx > > ,
201171 ) -> 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) )
212175 . filter ( |bound| {
213176 // Remove bounds that must hold, since they are not interesting.
214177 !bound. must_hold ( )
@@ -222,6 +185,32 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
222185 }
223186 }
224187
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+
225214 /// Searches the environment for where-clauses like `G: 'a` where
226215 /// `G` is either some type parameter `T` or a projection like
227216 /// `T::Item`. Returns a vector of the `'a` bounds it can find.
0 commit comments