Skip to content

Commit cec69cd

Browse files
committed
ptr_cast_constness: check for implicit mut to const pointer coercion
changelog: [`ptr_cast_constness`]: check for implicit mut to const pointer coercion Signed-off-by: Zihan <[email protected]>
1 parent 7a95605 commit cec69cd

File tree

5 files changed

+70
-2
lines changed

5 files changed

+70
-2
lines changed

clippy_lints/src/casts/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,5 +919,6 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
919919
cast_ptr_alignment::check_cast_method(cx, expr);
920920
cast_slice_different_sizes::check(cx, expr, self.msrv);
921921
ptr_cast_constness::check_null_ptr_cast_method(cx, expr);
922+
ptr_cast_constness::check_implicit_cast_from_mut(cx, expr, self.msrv);
922923
}
923924
}

clippy_lints/src/casts/ptr_cast_constness.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::msrvs::{self, Msrv};
33
use clippy_utils::source::snippet_with_applicability;
44
use clippy_utils::sugg::Sugg;
5-
use clippy_utils::{std_or_core, sym};
5+
use clippy_utils::{get_parent_expr, std_or_core, sym};
66
use rustc_errors::Applicability;
77
use rustc_hir::{self as hir, Expr, ExprKind, QPath};
88
use rustc_lint::LateContext;
9+
use rustc_middle::ty::adjustment::{Adjust, PointerCoercion};
910
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
1011

1112
use super::PTR_CAST_CONSTNESS;
@@ -102,3 +103,25 @@ pub(super) fn check_null_ptr_cast_method(cx: &LateContext<'_>, expr: &Expr<'_>)
102103
);
103104
}
104105
}
106+
107+
pub(super) fn check_implicit_cast_from_mut(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Msrv) {
108+
if msrv.meets(cx, msrvs::POINTER_CAST_CONSTNESS)
109+
&& let ty::RawPtr(..) = cx.typeck_results().expr_ty(expr).kind()
110+
&& !matches!(get_parent_expr(cx, expr).map(|e| e.kind), Some(ExprKind::Cast(..)))
111+
&& let [coercion] = cx.typeck_results().expr_adjustments(expr)
112+
&& let Adjust::Pointer(PointerCoercion::MutToConstPointer) = coercion.kind
113+
&& !expr.span.from_expansion()
114+
{
115+
let mut app = Applicability::MachineApplicable;
116+
let sugg = Sugg::hir_with_applicability(cx, expr, "_", &mut app);
117+
span_lint_and_sugg(
118+
cx,
119+
PTR_CAST_CONSTNESS,
120+
expr.span,
121+
"implicit casting from mut pointer to const pointer",
122+
"try `pointer::cast_const`, a safer alternative",
123+
format!("{}.cast_const()", sugg.maybe_paren()),
124+
app,
125+
);
126+
}
127+
}

tests/ui/ptr_cast_constness.fixed

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,16 @@ fn issue11317() {
112112
let _ptr: *mut u32 = (r as *const u32).cast_mut();
113113
//~^ ptr_cast_constness
114114
}
115+
116+
/// Checks for implicit mut pointer to const pointer coercion
117+
fn issue13667() {
118+
fn expect_const_ptr<T>(_: *const T) {}
119+
120+
let p = &mut 0 as *mut i32;
121+
let _: *const i32 = p.cast_const();
122+
//~^ ptr_cast_constness
123+
expect_const_ptr(p.cast_const());
124+
//~^ ptr_cast_constness
125+
let _: *const u8 = (p as *mut u8).cast_const();
126+
//~^ ptr_cast_constness
127+
}

tests/ui/ptr_cast_constness.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,16 @@ fn issue11317() {
112112
let _ptr: *mut u32 = r as *const _ as *mut _;
113113
//~^ ptr_cast_constness
114114
}
115+
116+
/// Checks for implicit mut pointer to const pointer coercion
117+
fn issue13667() {
118+
fn expect_const_ptr<T>(_: *const T) {}
119+
120+
let p = &mut 0 as *mut i32;
121+
let _: *const i32 = p;
122+
//~^ ptr_cast_constness
123+
expect_const_ptr(p);
124+
//~^ ptr_cast_constness
125+
let _: *const u8 = p as *mut u8;
126+
//~^ ptr_cast_constness
127+
}

tests/ui/ptr_cast_constness.stderr

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,23 @@ error: `as` casting between raw pointers while changing only its constness
9595
LL | let _ptr: *mut u32 = r as *const _ as *mut _;
9696
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(r as *const u32).cast_mut()`
9797

98-
error: aborting due to 15 previous errors
98+
error: implicit casting from mut pointer to const pointer
99+
--> tests/ui/ptr_cast_constness.rs:121:25
100+
|
101+
LL | let _: *const i32 = p;
102+
| ^ help: try `pointer::cast_const`, a safer alternative: `p.cast_const()`
103+
104+
error: implicit casting from mut pointer to const pointer
105+
--> tests/ui/ptr_cast_constness.rs:123:22
106+
|
107+
LL | expect_const_ptr(p);
108+
| ^ help: try `pointer::cast_const`, a safer alternative: `p.cast_const()`
109+
110+
error: implicit casting from mut pointer to const pointer
111+
--> tests/ui/ptr_cast_constness.rs:125:24
112+
|
113+
LL | let _: *const u8 = p as *mut u8;
114+
| ^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `(p as *mut u8).cast_const()`
115+
116+
error: aborting due to 18 previous errors
99117

0 commit comments

Comments
 (0)