Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clippy_lints/src/casts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -919,5 +919,6 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
cast_ptr_alignment::check_cast_method(cx, expr);
cast_slice_different_sizes::check(cx, expr, self.msrv);
ptr_cast_constness::check_null_ptr_cast_method(cx, expr);
ptr_cast_constness::check_implicit_cast_from_mut(cx, expr, self.msrv);
}
}
25 changes: 24 additions & 1 deletion clippy_lints/src/casts/ptr_cast_constness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
use clippy_utils::{std_or_core, sym};
use clippy_utils::{get_parent_expr, std_or_core, sym};
use rustc_errors::Applicability;
use rustc_hir::{self as hir, Expr, ExprKind, QPath};
use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::{Adjust, PointerCoercion};
use rustc_middle::ty::{self, Ty, TypeVisitableExt};

use super::PTR_CAST_CONSTNESS;
Expand Down Expand Up @@ -102,3 +103,25 @@ pub(super) fn check_null_ptr_cast_method(cx: &LateContext<'_>, expr: &Expr<'_>)
);
}
}

pub(super) fn check_implicit_cast_from_mut(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Msrv) {
if msrv.meets(cx, msrvs::POINTER_CAST_CONSTNESS)
&& let ty::RawPtr(..) = cx.typeck_results().expr_ty(expr).kind()
&& !matches!(get_parent_expr(cx, expr).map(|e| e.kind), Some(ExprKind::Cast(..)))
&& let [coercion] = cx.typeck_results().expr_adjustments(expr)
&& let Adjust::Pointer(PointerCoercion::MutToConstPointer) = coercion.kind
&& !expr.span.from_expansion()
{
let mut app = Applicability::MachineApplicable;
let sugg = Sugg::hir_with_applicability(cx, expr, "_", &mut app);
span_lint_and_sugg(
cx,
PTR_CAST_CONSTNESS,
expr.span,
"implicit casting from mut pointer to const pointer",
"try `pointer::cast_const`, a safer alternative",
format!("{}.cast_const()", sugg.maybe_paren()),
app,
);
}
}
13 changes: 13 additions & 0 deletions tests/ui/ptr_cast_constness.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,16 @@ fn issue11317() {
let _ptr: *mut u32 = (r as *const u32).cast_mut();
//~^ ptr_cast_constness
}

/// Checks for implicit mut pointer to const pointer coercion
fn issue13667() {
fn expect_const_ptr<T>(_: *const T) {}

let p = &mut 0 as *mut i32;
let _: *const i32 = p.cast_const();
//~^ ptr_cast_constness
expect_const_ptr(p.cast_const());
//~^ ptr_cast_constness
let _: *const u8 = (p as *mut u8).cast_const();
//~^ ptr_cast_constness
}
13 changes: 13 additions & 0 deletions tests/ui/ptr_cast_constness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,16 @@ fn issue11317() {
let _ptr: *mut u32 = r as *const _ as *mut _;
//~^ ptr_cast_constness
}

/// Checks for implicit mut pointer to const pointer coercion
fn issue13667() {
fn expect_const_ptr<T>(_: *const T) {}

let p = &mut 0 as *mut i32;
let _: *const i32 = p;
//~^ ptr_cast_constness
expect_const_ptr(p);
//~^ ptr_cast_constness
let _: *const u8 = p as *mut u8;
//~^ ptr_cast_constness
}
20 changes: 19 additions & 1 deletion tests/ui/ptr_cast_constness.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,23 @@ error: `as` casting between raw pointers while changing only its constness
LL | let _ptr: *mut u32 = r as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(r as *const u32).cast_mut()`

error: aborting due to 15 previous errors
error: implicit casting from mut pointer to const pointer
--> tests/ui/ptr_cast_constness.rs:121:25
|
LL | let _: *const i32 = p;
| ^ help: try `pointer::cast_const`, a safer alternative: `p.cast_const()`

error: implicit casting from mut pointer to const pointer
--> tests/ui/ptr_cast_constness.rs:123:22
|
LL | expect_const_ptr(p);
| ^ help: try `pointer::cast_const`, a safer alternative: `p.cast_const()`

error: implicit casting from mut pointer to const pointer
--> tests/ui/ptr_cast_constness.rs:125:24
|
LL | let _: *const u8 = p as *mut u8;
| ^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `(p as *mut u8).cast_const()`

error: aborting due to 18 previous errors

Loading