@@ -2240,3 +2240,64 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'
22402240 NestedVisitorMap :: OnlyBodies ( & self . cx . tcx . hir ( ) )
22412241 }
22422242}
2243+
2244+ /// **What it does:** Checks for casts of `&T` to `&mut T` anywhere in the code.
2245+ ///
2246+ /// **Why is this bad?** It’s basically guaranteed to be undefined behaviour.
2247+ /// `UnsafeCell` is the only way to obtain aliasable data that is considered
2248+ /// mutable.
2249+ ///
2250+ /// **Known problems:** None.
2251+ ///
2252+ /// **Example:**
2253+ /// ```rust
2254+ /// fn x(r: &i32) {
2255+ /// unsafe {
2256+ /// *(r as *const _ as *mut _) += 1;
2257+ /// }
2258+ /// }
2259+ /// ```
2260+ ///
2261+ /// Instead consider using interior mutability types.
2262+ ///
2263+ /// ```rust
2264+ /// fn x(r: &UnsafeCell<i32>) {
2265+ /// unsafe {
2266+ /// *r.get() += 1;
2267+ /// }
2268+ /// }
2269+ /// ```
2270+ declare_clippy_lint ! {
2271+ pub CAST_REF_TO_MUT ,
2272+ nursery,
2273+ "a cast of reference to a mutable pointer"
2274+ }
2275+
2276+ pub struct RefToMut ;
2277+
2278+ impl LintPass for RefToMut {
2279+ fn get_lints ( & self ) -> LintArray {
2280+ lint_array ! ( CAST_REF_TO_MUT )
2281+ }
2282+ }
2283+
2284+ impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for RefToMut {
2285+ fn check_expr ( & mut self , cx : & LateContext < ' a , ' tcx > , expr : & ' tcx Expr ) {
2286+ if_chain ! {
2287+ if let ExprKind :: Unary ( UnOp :: UnDeref , e) = & expr. node;
2288+ if let ExprKind :: Cast ( e, t) = & e. node;
2289+ if let TyKind :: Ptr ( MutTy { mutbl: Mutability :: MutMutable , .. } ) = t. node;
2290+ if let ExprKind :: Cast ( e, t) = & e. node;
2291+ if let TyKind :: Ptr ( MutTy { mutbl: Mutability :: MutImmutable , .. } ) = t. node;
2292+ if let ty:: TyKind :: Ref ( ..) = cx. tables. node_id_to_type( e. hir_id) . sty;
2293+ then {
2294+ span_lint(
2295+ cx,
2296+ CAST_REF_TO_MUT ,
2297+ expr. span,
2298+ "casting immutable reference to a mutable reference"
2299+ ) ;
2300+ }
2301+ }
2302+ }
2303+ }
0 commit comments