@@ -3,6 +3,7 @@ mod cast_possible_truncation;
3
3
mod cast_possible_wrap;
4
4
mod cast_precision_loss;
5
5
mod cast_ptr_alignment;
6
+ mod cast_ref_to_mut;
6
7
mod cast_sign_loss;
7
8
mod fn_to_numeric_cast;
8
9
mod fn_to_numeric_cast_with_truncation;
@@ -14,7 +15,7 @@ use std::borrow::Cow;
14
15
use if_chain:: if_chain;
15
16
use rustc_ast:: LitKind ;
16
17
use rustc_errors:: Applicability ;
17
- use rustc_hir:: { Expr , ExprKind , MutTy , Mutability , TyKind , UnOp } ;
18
+ use rustc_hir:: { Expr , ExprKind , Mutability , TyKind } ;
18
19
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
19
20
use rustc_middle:: lint:: in_external_macro;
20
21
use rustc_middle:: ty:: { self , TypeAndMut , UintTy } ;
@@ -23,7 +24,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
23
24
24
25
use crate :: utils:: sugg:: Sugg ;
25
26
use crate :: utils:: {
26
- is_hir_ty_cfg_dependant, meets_msrv, snippet_with_applicability, span_lint , span_lint_and_sugg, span_lint_and_then,
27
+ is_hir_ty_cfg_dependant, meets_msrv, snippet_with_applicability, span_lint_and_sugg, span_lint_and_then,
27
28
} ;
28
29
29
30
declare_clippy_lint ! {
@@ -255,12 +256,47 @@ declare_clippy_lint! {
255
256
"casting a function pointer to a numeric type not wide enough to store the address"
256
257
}
257
258
259
+ declare_clippy_lint ! {
260
+ /// **What it does:** Checks for casts of `&T` to `&mut T` anywhere in the code.
261
+ ///
262
+ /// **Why is this bad?** It’s basically guaranteed to be undefined behaviour.
263
+ /// `UnsafeCell` is the only way to obtain aliasable data that is considered
264
+ /// mutable.
265
+ ///
266
+ /// **Known problems:** None.
267
+ ///
268
+ /// **Example:**
269
+ /// ```rust,ignore
270
+ /// fn x(r: &i32) {
271
+ /// unsafe {
272
+ /// *(r as *const _ as *mut _) += 1;
273
+ /// }
274
+ /// }
275
+ /// ```
276
+ ///
277
+ /// Instead consider using interior mutability types.
278
+ ///
279
+ /// ```rust
280
+ /// use std::cell::UnsafeCell;
281
+ ///
282
+ /// fn x(r: &UnsafeCell<i32>) {
283
+ /// unsafe {
284
+ /// *r.get() += 1;
285
+ /// }
286
+ /// }
287
+ /// ```
288
+ pub CAST_REF_TO_MUT ,
289
+ correctness,
290
+ "a cast of reference to a mutable pointer"
291
+ }
292
+
258
293
declare_lint_pass ! ( Casts => [
259
294
CAST_PRECISION_LOSS ,
260
295
CAST_SIGN_LOSS ,
261
296
CAST_POSSIBLE_TRUNCATION ,
262
297
CAST_POSSIBLE_WRAP ,
263
298
CAST_LOSSLESS ,
299
+ CAST_REF_TO_MUT ,
264
300
UNNECESSARY_CAST ,
265
301
CAST_PTR_ALIGNMENT ,
266
302
FN_TO_NUMERIC_CAST ,
@@ -269,6 +305,8 @@ declare_lint_pass!(Casts => [
269
305
270
306
impl < ' tcx > LateLintPass < ' tcx > for Casts {
271
307
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
308
+ cast_ref_to_mut:: check ( cx, expr) ;
309
+
272
310
if expr. span . from_expansion ( ) {
273
311
return ;
274
312
}
@@ -300,63 +338,6 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
300
338
}
301
339
}
302
340
303
- declare_clippy_lint ! {
304
- /// **What it does:** Checks for casts of `&T` to `&mut T` anywhere in the code.
305
- ///
306
- /// **Why is this bad?** It’s basically guaranteed to be undefined behaviour.
307
- /// `UnsafeCell` is the only way to obtain aliasable data that is considered
308
- /// mutable.
309
- ///
310
- /// **Known problems:** None.
311
- ///
312
- /// **Example:**
313
- /// ```rust,ignore
314
- /// fn x(r: &i32) {
315
- /// unsafe {
316
- /// *(r as *const _ as *mut _) += 1;
317
- /// }
318
- /// }
319
- /// ```
320
- ///
321
- /// Instead consider using interior mutability types.
322
- ///
323
- /// ```rust
324
- /// use std::cell::UnsafeCell;
325
- ///
326
- /// fn x(r: &UnsafeCell<i32>) {
327
- /// unsafe {
328
- /// *r.get() += 1;
329
- /// }
330
- /// }
331
- /// ```
332
- pub CAST_REF_TO_MUT ,
333
- correctness,
334
- "a cast of reference to a mutable pointer"
335
- }
336
-
337
- declare_lint_pass ! ( RefToMut => [ CAST_REF_TO_MUT ] ) ;
338
-
339
- impl < ' tcx > LateLintPass < ' tcx > for RefToMut {
340
- fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
341
- if_chain ! {
342
- if let ExprKind :: Unary ( UnOp :: Deref , e) = & expr. kind;
343
- if let ExprKind :: Cast ( e, t) = & e. kind;
344
- if let TyKind :: Ptr ( MutTy { mutbl: Mutability :: Mut , .. } ) = t. kind;
345
- if let ExprKind :: Cast ( e, t) = & e. kind;
346
- if let TyKind :: Ptr ( MutTy { mutbl: Mutability :: Not , .. } ) = t. kind;
347
- if let ty:: Ref ( ..) = cx. typeck_results( ) . node_type( e. hir_id) . kind( ) ;
348
- then {
349
- span_lint(
350
- cx,
351
- CAST_REF_TO_MUT ,
352
- expr. span,
353
- "casting `&T` to `&mut T` may cause undefined behavior, consider instead using an `UnsafeCell`" ,
354
- ) ;
355
- }
356
- }
357
- }
358
- }
359
-
360
341
const PTR_AS_PTR_MSRV : RustcVersion = RustcVersion :: new ( 1 , 38 , 0 ) ;
361
342
362
343
declare_clippy_lint ! {
0 commit comments