@@ -119,41 +119,49 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> {
119
119
self . cx . typeck_results ( ) . expr_ty ( ex)
120
120
}
121
121
122
- fn has_seen_type ( & mut self , ty : Ty < ' tcx > ) -> bool {
123
- !self . seen_types . insert ( ty)
122
+ fn has_sig_drop_attr ( & mut self , cx : & LateContext < ' tcx > , ty : Ty < ' tcx > ) -> bool {
123
+ self . seen_types . clear ( ) ;
124
+ self . has_sig_drop_attr_impl ( cx, ty)
124
125
}
125
126
126
- fn has_sig_drop_attr ( & mut self , cx : & LateContext < ' tcx > , ty : Ty < ' tcx > ) -> bool {
127
+ fn has_sig_drop_attr_impl ( & mut self , cx : & LateContext < ' tcx > , ty : Ty < ' tcx > ) -> bool {
127
128
if let Some ( adt) = ty. ty_adt_def ( ) {
128
129
if get_attr ( cx. sess ( ) , cx. tcx . get_attrs_unchecked ( adt. did ( ) ) , "has_significant_drop" ) . count ( ) > 0 {
129
130
return true ;
130
131
}
131
132
}
132
133
133
- match ty. kind ( ) {
134
- rustc_middle:: ty:: Adt ( a, b) => {
135
- for f in a. all_fields ( ) {
136
- let ty = f. ty ( cx. tcx , b) ;
137
- if !self . has_seen_type ( ty) && self . has_sig_drop_attr ( cx, ty) {
138
- return true ;
139
- }
140
- }
134
+ if !self . seen_types . insert ( ty) {
135
+ return false ;
136
+ }
141
137
142
- for generic_arg in * b {
143
- if let GenericArgKind :: Type ( ty) = generic_arg. unpack ( ) {
144
- if self . has_sig_drop_attr ( cx, ty) {
145
- return true ;
146
- }
147
- }
148
- }
149
- false
138
+ let result = match ty. kind ( ) {
139
+ rustc_middle:: ty:: Adt ( adt, args) => {
140
+ // if some field has significant drop,
141
+ adt. all_fields ( )
142
+ . map ( |field| field. ty ( cx. tcx , args) )
143
+ . any ( |ty| self . has_sig_drop_attr ( cx, ty) )
144
+ // or if there is no generic lifetime and..
145
+ // (to avoid false positive on `Ref<'a, MutexGuard<Foo>>`)
146
+ || ( args
147
+ . iter ( )
148
+ . all ( |arg| !matches ! ( arg. unpack( ) , GenericArgKind :: Lifetime ( _) ) )
149
+ // some generic parameter has significant drop
150
+ // (to avoid false negative on `Box<MutexGuard<Foo>>`)
151
+ && args
152
+ . iter ( )
153
+ . filter_map ( |arg| match arg. unpack ( ) {
154
+ GenericArgKind :: Type ( ty) => Some ( ty) ,
155
+ _ => None ,
156
+ } )
157
+ . any ( |ty| self . has_sig_drop_attr ( cx, ty) ) )
150
158
} ,
151
- rustc_middle:: ty:: Array ( ty, _)
152
- | rustc_middle:: ty:: RawPtr ( ty, _)
153
- | rustc_middle:: ty:: Ref ( _, ty, _)
154
- | rustc_middle:: ty:: Slice ( ty) => self . has_sig_drop_attr ( cx, * ty) ,
159
+ rustc_middle:: ty:: Tuple ( tys) => tys. iter ( ) . any ( |ty| self . has_sig_drop_attr ( cx, ty) ) ,
160
+ rustc_middle:: ty:: Array ( ty, _) | rustc_middle:: ty:: Slice ( ty) => self . has_sig_drop_attr ( cx, * ty) ,
155
161
_ => false ,
156
- }
162
+ } ;
163
+
164
+ result
157
165
}
158
166
}
159
167
0 commit comments