@@ -111,16 +111,35 @@ fn is_cast_from_const_to_mut<'tcx>(
111
111
cx : & LateContext < ' tcx > ,
112
112
orig_expr : & ' tcx Expr < ' tcx > ,
113
113
) -> Option < bool > {
114
- let mut need_check_freeze = false ;
115
- let mut e = orig_expr;
116
-
117
114
let end_ty = cx. typeck_results ( ) . node_type ( orig_expr. hir_id ) ;
118
115
119
116
// Bail out early if the end type is **not** a mutable pointer.
120
117
if !matches ! ( end_ty. kind( ) , ty:: RawPtr ( TypeAndMut { ty: _, mutbl: Mutability :: Mut } ) ) {
121
118
return None ;
122
119
}
123
120
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
+
124
143
loop {
125
144
e = e. peel_blocks ( ) ;
126
145
// <expr> as ...
@@ -145,27 +164,13 @@ fn is_cast_from_const_to_mut<'tcx>(
145
164
)
146
165
{
147
166
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 ;
149
168
}
150
169
arg
151
170
} else {
152
171
break ;
153
172
} ;
154
173
}
155
174
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)
171
176
}
0 commit comments