@@ -1137,21 +1137,38 @@ impl<'tcx> InteriorMut<'tcx> {
11371137
11381138 /// Check if given type has interior mutability such as [`std::cell::Cell`] or
11391139 /// [`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.
11411142 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+
11421156 match self . tys . entry ( ty) {
11431157 Entry :: Occupied ( o) => return * o. get ( ) ,
11441158 // Temporarily insert a `None` to break cycles
11451159 Entry :: Vacant ( v) => v. insert ( None ) ,
11461160 } ;
1161+ let depth = depth + 1 ;
11471162
11481163 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 ) ,
11511166 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 )
11531168 } ,
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) ) ,
11551172 ty:: Adt ( def, _) if def. is_unsafe_cell ( ) => Some ( ty:: List :: empty ( ) ) ,
11561173 ty:: Adt ( def, args) => {
11571174 let is_std_collection = matches ! (
@@ -1171,16 +1188,17 @@ impl<'tcx> InteriorMut<'tcx> {
11711188
11721189 if is_std_collection || def. is_box ( ) {
11731190 // 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) )
11751193 } else if self . ignored_def_ids . contains ( & def. did ( ) ) || def. is_phantom_data ( ) {
11761194 None
11771195 } else {
11781196 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 ) )
11801198 }
11811199 } ,
11821200 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 ) ,
11841202 _ => None ,
11851203 } ,
11861204 _ => None ,
@@ -1342,7 +1360,8 @@ pub fn has_non_owning_mutable_access<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'
13421360 mutability. is_mut ( ) || !pointee_ty. is_freeze ( cx. tcx , cx. typing_env ( ) )
13431361 } ,
13441362 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) )
13461365 } ,
13471366 ty:: Tuple ( tuple_args) => tuple_args
13481367 . iter ( )
0 commit comments