@@ -1137,21 +1137,38 @@ impl<'tcx> InteriorMut<'tcx> {
1137
1137
1138
1138
/// Check if given type has interior mutability such as [`std::cell::Cell`] or
1139
1139
/// [`std::cell::RefCell`] etc. and if it does, returns a chain of types that causes
1140
- /// this type to be interior mutable
1140
+ /// this type to be interior mutable. False negatives may be expected for infinitely recursive
1141
+ /// types, and `None` will be returned there.
1141
1142
pub fn interior_mut_ty_chain ( & mut self , cx : & LateContext < ' tcx > , ty : Ty < ' tcx > ) -> Option < & ' tcx ty:: List < Ty < ' tcx > > > {
1143
+ self . interior_mut_ty_chain_inner ( cx, ty, 0 )
1144
+ }
1145
+
1146
+ fn interior_mut_ty_chain_inner (
1147
+ & mut self ,
1148
+ cx : & LateContext < ' tcx > ,
1149
+ ty : Ty < ' tcx > ,
1150
+ depth : usize ,
1151
+ ) -> Option < & ' tcx ty:: List < Ty < ' tcx > > > {
1152
+ if !cx. tcx . recursion_limit ( ) . value_within_limit ( depth) {
1153
+ return None ;
1154
+ }
1155
+
1142
1156
match self . tys . entry ( ty) {
1143
1157
Entry :: Occupied ( o) => return * o. get ( ) ,
1144
1158
// Temporarily insert a `None` to break cycles
1145
1159
Entry :: Vacant ( v) => v. insert ( None ) ,
1146
1160
} ;
1161
+ let depth = depth + 1 ;
1147
1162
1148
1163
let chain = match * ty. kind ( ) {
1149
- ty:: RawPtr ( inner_ty, _) if !self . ignore_pointers => self . interior_mut_ty_chain ( cx, inner_ty) ,
1150
- ty:: Ref ( _, inner_ty, _) | ty:: Slice ( inner_ty) => self . interior_mut_ty_chain ( cx, inner_ty) ,
1164
+ ty:: RawPtr ( inner_ty, _) if !self . ignore_pointers => self . interior_mut_ty_chain_inner ( cx, inner_ty, depth ) ,
1165
+ ty:: Ref ( _, inner_ty, _) | ty:: Slice ( inner_ty) => self . interior_mut_ty_chain_inner ( cx, inner_ty, depth ) ,
1151
1166
ty:: Array ( inner_ty, size) if size. try_to_target_usize ( cx. tcx ) != Some ( 0 ) => {
1152
- self . interior_mut_ty_chain ( cx, inner_ty)
1167
+ self . interior_mut_ty_chain_inner ( cx, inner_ty, depth )
1153
1168
} ,
1154
- ty:: Tuple ( fields) => fields. iter ( ) . find_map ( |ty| self . interior_mut_ty_chain ( cx, ty) ) ,
1169
+ ty:: Tuple ( fields) => fields
1170
+ . iter ( )
1171
+ . find_map ( |ty| self . interior_mut_ty_chain_inner ( cx, ty, depth) ) ,
1155
1172
ty:: Adt ( def, _) if def. is_unsafe_cell ( ) => Some ( ty:: List :: empty ( ) ) ,
1156
1173
ty:: Adt ( def, args) => {
1157
1174
let is_std_collection = matches ! (
@@ -1171,16 +1188,17 @@ impl<'tcx> InteriorMut<'tcx> {
1171
1188
1172
1189
if is_std_collection || def. is_box ( ) {
1173
1190
// Include the types from std collections that are behind pointers internally
1174
- args. types ( ) . find_map ( |ty| self . interior_mut_ty_chain ( cx, ty) )
1191
+ args. types ( )
1192
+ . find_map ( |ty| self . interior_mut_ty_chain_inner ( cx, ty, depth) )
1175
1193
} else if self . ignored_def_ids . contains ( & def. did ( ) ) || def. is_phantom_data ( ) {
1176
1194
None
1177
1195
} else {
1178
1196
def. all_fields ( )
1179
- . find_map ( |f| self . interior_mut_ty_chain ( cx, f. ty ( cx. tcx , args) ) )
1197
+ . find_map ( |f| self . interior_mut_ty_chain_inner ( cx, f. ty ( cx. tcx , args) , depth ) )
1180
1198
}
1181
1199
} ,
1182
1200
ty:: Alias ( ty:: Projection , _) => match cx. tcx . try_normalize_erasing_regions ( cx. typing_env ( ) , ty) {
1183
- Ok ( normalized_ty) if ty != normalized_ty => self . interior_mut_ty_chain ( cx, normalized_ty) ,
1201
+ Ok ( normalized_ty) if ty != normalized_ty => self . interior_mut_ty_chain_inner ( cx, normalized_ty, depth ) ,
1184
1202
_ => None ,
1185
1203
} ,
1186
1204
_ => None ,
@@ -1342,7 +1360,8 @@ pub fn has_non_owning_mutable_access<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'
1342
1360
mutability. is_mut ( ) || !pointee_ty. is_freeze ( cx. tcx , cx. typing_env ( ) )
1343
1361
} ,
1344
1362
ty:: Closure ( _, closure_args) => {
1345
- matches ! ( closure_args. types( ) . next_back( ) , Some ( captures) if has_non_owning_mutable_access_inner( cx, phantoms, captures) )
1363
+ matches ! ( closure_args. types( ) . next_back( ) ,
1364
+ Some ( captures) if has_non_owning_mutable_access_inner( cx, phantoms, captures) )
1346
1365
} ,
1347
1366
ty:: Tuple ( tuple_args) => tuple_args
1348
1367
. iter ( )
0 commit comments