@@ -111,16 +111,35 @@ fn is_cast_from_const_to_mut<'tcx>(
111111 cx : & LateContext < ' tcx > ,
112112 orig_expr : & ' tcx Expr < ' tcx > ,
113113) -> Option < bool > {
114- let mut need_check_freeze = false ;
115- let mut e = orig_expr;
116-
117114 let end_ty = cx. typeck_results ( ) . node_type ( orig_expr. hir_id ) ;
118115
119116 // Bail out early if the end type is **not** a mutable pointer.
120117 if !matches ! ( end_ty. kind( ) , ty:: RawPtr ( TypeAndMut { ty: _, mutbl: Mutability :: Mut } ) ) {
121118 return None ;
122119 }
123120
121+ let ( e, need_check_freeze) = peel_casts ( cx, orig_expr) ;
122+
123+ let start_ty = cx. typeck_results ( ) . node_type ( e. hir_id ) ;
124+ if let ty:: Ref ( _, inner_ty, Mutability :: Not ) = start_ty. kind ( ) {
125+ // If an UnsafeCell method is involved we need to additionally check the
126+ // inner type for the presence of the Freeze trait (ie does NOT contain
127+ // an UnsafeCell), since in that case we would incorrectly lint on valid casts.
128+ //
129+ // We also consider non concrete skeleton types (ie generics)
130+ // to be an issue since there is no way to make it safe for abitrary types.
131+ let inner_ty_has_interior_mutability =
132+ !inner_ty. is_freeze ( cx. tcx , cx. param_env ) && inner_ty. has_concrete_skeleton ( ) ;
133+ ( !need_check_freeze || !inner_ty_has_interior_mutability)
134+ . then_some ( inner_ty_has_interior_mutability)
135+ } else {
136+ None
137+ }
138+ }
139+
140+ fn peel_casts < ' tcx > ( cx : & LateContext < ' tcx > , mut e : & ' tcx Expr < ' tcx > ) -> ( & ' tcx Expr < ' tcx > , bool ) {
141+ let mut gone_trough_unsafe_cell_raw_get = false ;
142+
124143 loop {
125144 e = e. peel_blocks ( ) ;
126145 // <expr> as ...
@@ -145,27 +164,13 @@ fn is_cast_from_const_to_mut<'tcx>(
145164 )
146165 {
147166 if cx. tcx . is_diagnostic_item ( sym:: unsafe_cell_raw_get, def_id) {
148- need_check_freeze = true ;
167+ gone_trough_unsafe_cell_raw_get = true ;
149168 }
150169 arg
151170 } else {
152171 break ;
153172 } ;
154173 }
155174
156- let start_ty = cx. typeck_results ( ) . node_type ( e. hir_id ) ;
157- if let ty:: Ref ( _, inner_ty, Mutability :: Not ) = start_ty. kind ( ) {
158- // If an UnsafeCell method is involved we need to additionally check the
159- // inner type for the presence of the Freeze trait (ie does NOT contain
160- // an UnsafeCell), since in that case we would incorrectly lint on valid casts.
161- //
162- // We also consider non concrete skeleton types (ie generics)
163- // to be an issue since there is no way to make it safe for abitrary types.
164- let inner_ty_has_interior_mutability =
165- !inner_ty. is_freeze ( cx. tcx , cx. param_env ) && inner_ty. has_concrete_skeleton ( ) ;
166- ( !need_check_freeze || !inner_ty_has_interior_mutability)
167- . then_some ( inner_ty_has_interior_mutability)
168- } else {
169- None
170- }
175+ ( e, gone_trough_unsafe_cell_raw_get)
171176}
0 commit comments