@@ -3,6 +3,7 @@ use crate::infer::{GenericKind, VerifyBound};
3
3
use rustc_data_structures:: captures:: Captures ;
4
4
use rustc_hir:: def_id:: DefId ;
5
5
use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , Subst } ;
6
+ use rustc_middle:: ty:: walk:: MiniSet ;
6
7
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
7
8
8
9
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
@@ -31,16 +32,23 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
31
32
/// Returns a "verify bound" that encodes what we know about
32
33
/// `generic` and the regions it outlives.
33
34
pub fn generic_bound ( & self , generic : GenericKind < ' tcx > ) -> VerifyBound < ' tcx > {
35
+ let mut visited = MiniSet :: new ( ) ;
34
36
match generic {
35
37
GenericKind :: Param ( param_ty) => self . param_bound ( param_ty) ,
36
- GenericKind :: Projection ( projection_ty) => self . projection_bound ( projection_ty) ,
38
+ GenericKind :: Projection ( projection_ty) => {
39
+ self . projection_bound ( projection_ty, & mut visited)
40
+ }
37
41
}
38
42
}
39
43
40
- fn type_bound ( & self , ty : Ty < ' tcx > ) -> VerifyBound < ' tcx > {
44
+ fn type_bound (
45
+ & self ,
46
+ ty : Ty < ' tcx > ,
47
+ visited : & mut MiniSet < GenericArg < ' tcx > > ,
48
+ ) -> VerifyBound < ' tcx > {
41
49
match ty. kind {
42
50
ty:: Param ( p) => self . param_bound ( p) ,
43
- ty:: Projection ( data) => self . projection_bound ( data) ,
51
+ ty:: Projection ( data) => self . projection_bound ( data, visited ) ,
44
52
ty:: FnDef ( _, substs) => {
45
53
// HACK(eddyb) ignore lifetimes found shallowly in `substs`.
46
54
// This is inconsistent with `ty::Adt` (including all substs),
@@ -50,9 +58,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
50
58
let mut bounds = substs
51
59
. iter ( )
52
60
. filter_map ( |child| match child. unpack ( ) {
53
- GenericArgKind :: Type ( ty) => Some ( self . type_bound ( ty) ) ,
61
+ GenericArgKind :: Type ( ty) => Some ( self . type_bound ( ty, visited ) ) ,
54
62
GenericArgKind :: Lifetime ( _) => None ,
55
- GenericArgKind :: Const ( _) => Some ( self . recursive_bound ( child) ) ,
63
+ GenericArgKind :: Const ( _) => Some ( self . recursive_bound ( child, visited ) ) ,
56
64
} )
57
65
. filter ( |bound| {
58
66
// Remove bounds that must hold, since they are not interesting.
@@ -66,7 +74,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
66
74
) ,
67
75
}
68
76
}
69
- _ => self . recursive_bound ( ty. into ( ) ) ,
77
+ _ => self . recursive_bound ( ty. into ( ) , visited ) ,
70
78
}
71
79
}
72
80
@@ -137,7 +145,11 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
137
145
self . declared_projection_bounds_from_trait ( projection_ty)
138
146
}
139
147
140
- pub fn projection_bound ( & self , projection_ty : ty:: ProjectionTy < ' tcx > ) -> VerifyBound < ' tcx > {
148
+ pub fn projection_bound (
149
+ & self ,
150
+ projection_ty : ty:: ProjectionTy < ' tcx > ,
151
+ visited : & mut MiniSet < GenericArg < ' tcx > > ,
152
+ ) -> VerifyBound < ' tcx > {
141
153
debug ! ( "projection_bound(projection_ty={:?})" , projection_ty) ;
142
154
143
155
let projection_ty_as_ty =
@@ -166,21 +178,25 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
166
178
167
179
// see the extensive comment in projection_must_outlive
168
180
let ty = self . tcx . mk_projection ( projection_ty. item_def_id , projection_ty. substs ) ;
169
- let recursive_bound = self . recursive_bound ( ty. into ( ) ) ;
181
+ let recursive_bound = self . recursive_bound ( ty. into ( ) , visited ) ;
170
182
171
183
VerifyBound :: AnyBound ( env_bounds. chain ( trait_bounds) . collect ( ) ) . or ( recursive_bound)
172
184
}
173
185
174
- fn recursive_bound ( & self , parent : GenericArg < ' tcx > ) -> VerifyBound < ' tcx > {
186
+ fn recursive_bound (
187
+ & self ,
188
+ parent : GenericArg < ' tcx > ,
189
+ visited : & mut MiniSet < GenericArg < ' tcx > > ,
190
+ ) -> VerifyBound < ' tcx > {
175
191
let mut bounds = parent
176
- . walk_shallow ( )
192
+ . walk_shallow ( visited )
177
193
. filter_map ( |child| match child. unpack ( ) {
178
- GenericArgKind :: Type ( ty) => Some ( self . type_bound ( ty) ) ,
194
+ GenericArgKind :: Type ( ty) => Some ( self . type_bound ( ty, visited ) ) ,
179
195
GenericArgKind :: Lifetime ( lt) => {
180
196
// Ignore late-bound regions.
181
197
if !lt. is_late_bound ( ) { Some ( VerifyBound :: OutlivedBy ( lt) ) } else { None }
182
198
}
183
- GenericArgKind :: Const ( _) => Some ( self . recursive_bound ( child) ) ,
199
+ GenericArgKind :: Const ( _) => Some ( self . recursive_bound ( child, visited ) ) ,
184
200
} )
185
201
. filter ( |bound| {
186
202
// Remove bounds that must hold, since they are not interesting.
0 commit comments