@@ -69,50 +69,66 @@ pub fn contains_adt_constructor<'tcx>(ty: Ty<'tcx>, adt: AdtDef<'tcx>) -> bool {
69
69
/// This method also recurses into opaque type predicates, so call it with `impl Trait<U>` and `U`
70
70
/// will also return `true`.
71
71
pub fn contains_ty_adt_constructor_opaque < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' tcx > , needle : Ty < ' tcx > ) -> bool {
72
- ty. walk ( ) . any ( |inner| match inner. unpack ( ) {
73
- GenericArgKind :: Type ( inner_ty) => {
74
- if inner_ty == needle {
75
- return true ;
76
- }
72
+ fn contains_ty_adt_constructor_opaque_inner < ' tcx > (
73
+ cx : & LateContext < ' tcx > ,
74
+ ty : Ty < ' tcx > ,
75
+ needle : Ty < ' tcx > ,
76
+ seen : & mut FxHashSet < DefId > ,
77
+ ) -> bool {
78
+ ty. walk ( ) . any ( |inner| match inner. unpack ( ) {
79
+ GenericArgKind :: Type ( inner_ty) => {
80
+ if inner_ty == needle {
81
+ return true ;
82
+ }
77
83
78
- if inner_ty. ty_adt_def ( ) == needle. ty_adt_def ( ) {
79
- return true ;
80
- }
84
+ if inner_ty. ty_adt_def ( ) == needle. ty_adt_def ( ) {
85
+ return true ;
86
+ }
87
+
88
+ if let ty:: Opaque ( def_id, _) = * inner_ty. kind ( ) {
89
+ if !seen. insert ( def_id) {
90
+ return false ;
91
+ }
81
92
82
- if let ty:: Opaque ( def_id, _) = * inner_ty. kind ( ) {
83
- for & ( predicate, _span) in cx. tcx . explicit_item_bounds ( def_id) {
84
- match predicate. kind ( ) . skip_binder ( ) {
85
- // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
86
- // and check substituions to find `U`.
87
- ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( trait_predicate) ) => {
88
- if trait_predicate
89
- . trait_ref
90
- . substs
91
- . types ( )
92
- . skip ( 1 ) // Skip the implicit `Self` generic parameter
93
- . any ( |ty| contains_ty_adt_constructor_opaque ( cx, ty, needle) )
94
- {
95
- return true ;
96
- }
97
- } ,
98
- // For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
99
- // so we check the term for `U`.
100
- ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( projection_predicate) ) => {
101
- if let ty:: TermKind :: Ty ( ty) = projection_predicate. term . unpack ( ) {
102
- if contains_ty_adt_constructor_opaque ( cx, ty, needle) {
93
+ for & ( predicate, _span) in cx. tcx . explicit_item_bounds ( def_id) {
94
+ match predicate. kind ( ) . skip_binder ( ) {
95
+ // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
96
+ // and check substituions to find `U`.
97
+ ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( trait_predicate) ) => {
98
+ if trait_predicate
99
+ . trait_ref
100
+ . substs
101
+ . types ( )
102
+ . skip ( 1 ) // Skip the implicit `Self` generic parameter
103
+ . any ( |ty| contains_ty_adt_constructor_opaque_inner ( cx, ty, needle, seen) )
104
+ {
103
105
return true ;
104
106
}
105
- } ;
106
- } ,
107
- _ => ( ) ,
107
+ } ,
108
+ // For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
109
+ // so we check the term for `U`.
110
+ ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( projection_predicate) ) => {
111
+ if let ty:: TermKind :: Ty ( ty) = projection_predicate. term . unpack ( ) {
112
+ if contains_ty_adt_constructor_opaque_inner ( cx, ty, needle, seen) {
113
+ return true ;
114
+ }
115
+ } ;
116
+ } ,
117
+ _ => ( ) ,
118
+ }
108
119
}
109
120
}
110
- }
111
121
112
- false
113
- } ,
114
- GenericArgKind :: Lifetime ( _) | GenericArgKind :: Const ( _) => false ,
115
- } )
122
+ false
123
+ } ,
124
+ GenericArgKind :: Lifetime ( _) | GenericArgKind :: Const ( _) => false ,
125
+ } )
126
+ }
127
+
128
+ // A hash set to ensure that the same opaque type (`impl Trait` in RPIT or TAIT) is not
129
+ // visited twice.
130
+ let mut seen = FxHashSet :: default ( ) ;
131
+ contains_ty_adt_constructor_opaque_inner ( cx, ty, needle, & mut seen)
116
132
}
117
133
118
134
/// Resolves `<T as Iterator>::Item` for `T`
0 commit comments