@@ -104,99 +104,51 @@ fn is_operation_we_care_about<'tcx>(
104
104
deref_assign_or_addr_of ( e) . or_else ( || ptr_write ( cx, e) )
105
105
}
106
106
107
- fn is_cast_from_const_to_mut < ' tcx > ( cx : & LateContext < ' tcx > , e : & ' tcx Expr < ' tcx > ) -> bool {
108
- let e = e. peel_blocks ( ) ;
107
+ fn is_cast_from_const_to_mut < ' tcx > ( cx : & LateContext < ' tcx > , orig_expr : & ' tcx Expr < ' tcx > ) -> bool {
108
+ let mut need_check_freeze = false ;
109
+ let mut e = orig_expr;
109
110
110
- fn from_casts < ' tcx > (
111
- cx : & LateContext < ' tcx > ,
112
- e : & ' tcx Expr < ' tcx > ,
113
- need_check_freeze : & mut bool ,
114
- ) -> Option < & ' tcx Expr < ' tcx > > {
115
- // <expr> as *mut ...
116
- let mut e = if let ExprKind :: Cast ( e, t) = e. kind
117
- && let ty:: RawPtr ( TypeAndMut { mutbl : Mutability :: Mut , .. } ) = cx. typeck_results ( ) . node_type ( t. hir_id ) . kind ( ) {
118
- e
119
- // <expr>.cast_mut()
111
+ let end_ty = cx. typeck_results ( ) . node_type ( orig_expr. hir_id ) ;
112
+
113
+ // Bail out early if the end type is **not** a mutable pointer.
114
+ if !matches ! ( end_ty. kind( ) , ty:: RawPtr ( TypeAndMut { ty: _, mutbl: Mutability :: Mut } ) ) {
115
+ return false ;
116
+ }
117
+
118
+ loop {
119
+ e = e. peel_blocks ( ) ;
120
+ // <expr> as ...
121
+ e = if let ExprKind :: Cast ( expr, _) = e. kind {
122
+ expr
123
+ // <expr>.cast(), <expr>.cast_mut() or <expr>.cast_const()
120
124
} else if let ExprKind :: MethodCall ( _, expr, [ ] , _) = e. kind
121
125
&& let Some ( def_id) = cx. typeck_results ( ) . type_dependent_def_id ( e. hir_id )
122
- && cx. tcx . is_diagnostic_item ( sym:: ptr_cast_mut, def_id) {
126
+ && matches ! (
127
+ cx. tcx. get_diagnostic_name( def_id) ,
128
+ Some ( sym:: ptr_cast | sym:: const_ptr_cast | sym:: ptr_cast_mut | sym:: ptr_cast_const)
129
+ )
130
+ {
123
131
expr
124
- // UnsafeCell::raw_get(<expr>)
132
+ // ptr::from_ref(<expr>), UnsafeCell::raw_get(<expr>) or mem::transmute<_, _> (<expr>)
125
133
} else if let ExprKind :: Call ( path, [ arg] ) = e. kind
126
134
&& let ExprKind :: Path ( ref qpath) = path. kind
127
135
&& let Some ( def_id) = cx. qpath_res ( qpath, path. hir_id ) . opt_def_id ( )
128
- && cx. tcx . is_diagnostic_item ( sym:: unsafe_cell_raw_get, def_id)
136
+ && matches ! (
137
+ cx. tcx. get_diagnostic_name( def_id) ,
138
+ Some ( sym:: ptr_from_ref | sym:: unsafe_cell_raw_get | sym:: transmute)
139
+ )
129
140
{
130
- * need_check_freeze = true ;
141
+ if cx. tcx . is_diagnostic_item ( sym:: unsafe_cell_raw_get, def_id) {
142
+ need_check_freeze = true ;
143
+ }
131
144
arg
132
145
} else {
133
- return None ;
146
+ break ;
134
147
} ;
135
-
136
- let mut had_at_least_one_cast = false ;
137
- loop {
138
- e = e. peel_blocks ( ) ;
139
- // <expr> as *mut/const ... or <expr> as <uint>
140
- e = if let ExprKind :: Cast ( expr, t) = e. kind
141
- && matches ! ( cx. typeck_results( ) . node_type( t. hir_id) . kind( ) , ty:: RawPtr ( _) | ty:: Uint ( _) ) {
142
- had_at_least_one_cast = true ;
143
- expr
144
- // <expr>.cast(), <expr>.cast_mut() or <expr>.cast_const()
145
- } else if let ExprKind :: MethodCall ( _, expr, [ ] , _) = e. kind
146
- && let Some ( def_id) = cx. typeck_results ( ) . type_dependent_def_id ( e. hir_id )
147
- && matches ! (
148
- cx. tcx. get_diagnostic_name( def_id) ,
149
- Some ( sym:: ptr_cast | sym:: const_ptr_cast | sym:: ptr_cast_mut | sym:: ptr_cast_const)
150
- )
151
- {
152
- had_at_least_one_cast = true ;
153
- expr
154
- // ptr::from_ref(<expr>) or UnsafeCell::raw_get(<expr>)
155
- } else if let ExprKind :: Call ( path, [ arg] ) = e. kind
156
- && let ExprKind :: Path ( ref qpath) = path. kind
157
- && let Some ( def_id) = cx. qpath_res ( qpath, path. hir_id ) . opt_def_id ( )
158
- && matches ! (
159
- cx. tcx. get_diagnostic_name( def_id) ,
160
- Some ( sym:: ptr_from_ref | sym:: unsafe_cell_raw_get)
161
- )
162
- {
163
- if cx. tcx . is_diagnostic_item ( sym:: unsafe_cell_raw_get, def_id) {
164
- * need_check_freeze = true ;
165
- }
166
- return Some ( arg) ;
167
- } else if had_at_least_one_cast {
168
- return Some ( e) ;
169
- } else {
170
- return None ;
171
- } ;
172
- }
173
148
}
174
149
175
- fn from_transmute < ' tcx > (
176
- cx : & LateContext < ' tcx > ,
177
- e : & ' tcx Expr < ' tcx > ,
178
- ) -> Option < & ' tcx Expr < ' tcx > > {
179
- // mem::transmute::<_, *mut _>(<expr>)
180
- if let ExprKind :: Call ( path, [ arg] ) = e. kind
181
- && let ExprKind :: Path ( ref qpath) = path. kind
182
- && let Some ( def_id) = cx. qpath_res ( qpath, path. hir_id ) . opt_def_id ( )
183
- && cx. tcx . is_diagnostic_item ( sym:: transmute, def_id)
184
- && let ty:: RawPtr ( TypeAndMut { mutbl : Mutability :: Mut , .. } ) = cx. typeck_results ( ) . node_type ( e. hir_id ) . kind ( ) {
185
- Some ( arg)
186
- } else {
187
- None
188
- }
189
- }
190
-
191
- let mut need_check_freeze = false ;
192
- let Some ( e) = from_casts ( cx, e, & mut need_check_freeze) . or_else ( || from_transmute ( cx, e) )
193
- else {
194
- return false ;
195
- } ;
196
-
197
- let e = e. peel_blocks ( ) ;
198
- let node_type = cx. typeck_results ( ) . node_type ( e. hir_id ) ;
199
- if let ty:: Ref ( _, inner_ty, Mutability :: Not ) = node_type. kind ( ) {
150
+ let start_ty = cx. typeck_results ( ) . node_type ( e. hir_id ) ;
151
+ if let ty:: Ref ( _, inner_ty, Mutability :: Not ) = start_ty. kind ( ) {
200
152
// If an UnsafeCell method is involved we need to additionaly check the
201
153
// inner type for the presence of the Freeze trait (ie does NOT contain
202
154
// an UnsafeCell), since in that case we would incorrectly lint on valid casts.
0 commit comments