@@ -69,50 +69,66 @@ pub fn contains_adt_constructor<'tcx>(ty: Ty<'tcx>, adt: AdtDef<'tcx>) -> bool {
6969/// This method also recurses into opaque type predicates, so call it with `impl Trait<U>` and `U`
7070/// will also return `true`.
7171pub 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+ }
7783
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+ }
8192
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+ {
103105 return true ;
104106 }
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+ }
108119 }
109120 }
110- }
111121
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)
116132}
117133
118134/// Resolves `<T as Iterator>::Item` for `T`
0 commit comments