@@ -104,99 +104,57 @@ 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 had_at_least_one_cast = false ;
109
+ let mut need_check_freeze = false ;
110
+ let mut e = orig_expr;
109
111
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()
112
+ let end_ty = cx. typeck_results ( ) . node_type ( orig_expr. hir_id ) ;
113
+
114
+ // Bail out early if the end type is **not** a mutable pointer.
115
+ if !matches ! ( end_ty. kind( ) , ty:: RawPtr ( TypeAndMut { ty: _, mutbl: Mutability :: Mut } ) ) {
116
+ return false ;
117
+ }
118
+
119
+ loop {
120
+ e = e. peel_blocks ( ) ;
121
+ // <expr> as ...
122
+ e = if let ExprKind :: Cast ( expr, _) = e. kind {
123
+ had_at_least_one_cast = true ;
124
+ expr
125
+ // <expr>.cast(), <expr>.cast_mut() or <expr>.cast_const()
120
126
} else if let ExprKind :: MethodCall ( _, expr, [ ] , _) = e. kind
121
127
&& 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) {
128
+ && matches ! (
129
+ cx. tcx. get_diagnostic_name( def_id) ,
130
+ Some ( sym:: ptr_cast | sym:: const_ptr_cast | sym:: ptr_cast_mut | sym:: ptr_cast_const)
131
+ )
132
+ {
133
+ had_at_least_one_cast = true ;
123
134
expr
124
- // UnsafeCell::raw_get(<expr>)
135
+ // ptr::from_ref(<expr>), UnsafeCell::raw_get(<expr>) or mem::transmute<_, _> (<expr>)
125
136
} else if let ExprKind :: Call ( path, [ arg] ) = e. kind
126
137
&& let ExprKind :: Path ( ref qpath) = path. kind
127
138
&& 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)
139
+ && matches ! (
140
+ cx. tcx. get_diagnostic_name( def_id) ,
141
+ Some ( sym:: ptr_from_ref | sym:: unsafe_cell_raw_get | sym:: transmute)
142
+ )
129
143
{
130
- * need_check_freeze = true ;
144
+ if cx. tcx . is_diagnostic_item ( sym:: unsafe_cell_raw_get, def_id) {
145
+ need_check_freeze = true ;
146
+ }
147
+ had_at_least_one_cast = true ;
131
148
arg
149
+ } else if had_at_least_one_cast {
150
+ break ;
132
151
} else {
133
- return None ;
152
+ return false ;
134
153
} ;
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
154
}
174
155
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 ( ) {
156
+ let start_ty = cx. typeck_results ( ) . node_type ( e. hir_id ) ;
157
+ if let ty:: Ref ( _, inner_ty, Mutability :: Not ) = start_ty. kind ( ) {
200
158
// If an UnsafeCell method is involved we need to additionaly check the
201
159
// inner type for the presence of the Freeze trait (ie does NOT contain
202
160
// an UnsafeCell), since in that case we would incorrectly lint on valid casts.
0 commit comments