diff options
| author | Philipp Krones <hello@philkrones.com> | 2023-06-02 11:41:57 +0200 |
|---|---|---|
| committer | Philipp Krones <hello@philkrones.com> | 2023-06-02 11:41:57 +0200 |
| commit | e6dc0efc0076690c0dcae05541fec771795ca84c (patch) | |
| tree | 18b4bc307f398c6599d89f70859315a678554b76 /clippy_lints/src/casts | |
| parent | ec2c6155aacbb92e2dba046e1560d9f28a61f077 (diff) | |
| download | rust-e6dc0efc0076690c0dcae05541fec771795ca84c.tar.gz rust-e6dc0efc0076690c0dcae05541fec771795ca84c.zip | |
Merge commit '30448e8cf98d4754350db0c959644564f317bc0f' into clippyup
Diffstat (limited to 'clippy_lints/src/casts')
| -rw-r--r-- | clippy_lints/src/casts/mod.rs | 33 | ||||
| -rw-r--r-- | clippy_lints/src/casts/ptr_cast_constness.rs | 44 |
2 files changed, 76 insertions, 1 deletions
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 0c175372aab..b90dab07a27 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -17,6 +17,7 @@ mod fn_to_numeric_cast; mod fn_to_numeric_cast_any; mod fn_to_numeric_cast_with_truncation; mod ptr_as_ptr; +mod ptr_cast_constness; mod unnecessary_cast; mod utils; @@ -363,7 +364,7 @@ declare_clippy_lint! { /// namely `*const T` to `*const U` and `*mut T` to `*mut U`. /// /// ### Why is this bad? - /// Though `as` casts between raw pointers is not terrible, `pointer::cast` is safer because + /// Though `as` casts between raw pointers are not terrible, `pointer::cast` is safer because /// it cannot accidentally change the pointer's mutability nor cast the pointer to other types like `usize`. /// /// ### Example @@ -388,6 +389,34 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does + /// Checks for `as` casts between raw pointers which change its constness, namely `*const T` to + /// `*mut T` and `*mut T` to `*const T`. + /// + /// ### Why is this bad? + /// Though `as` casts between raw pointers are not terrible, `pointer::cast_mut` and + /// `pointer::cast_const` are safer because they cannot accidentally cast the pointer to another + /// type. + /// + /// ### Example + /// ```rust + /// let ptr: *const u32 = &42_u32; + /// let mut_ptr = ptr as *mut u32; + /// let ptr = mut_ptr as *const u32; + /// ``` + /// Use instead: + /// ```rust + /// let ptr: *const u32 = &42_u32; + /// let mut_ptr = ptr.cast_mut(); + /// let ptr = mut_ptr.cast_const(); + /// ``` + #[clippy::version = "1.71.0"] + pub PTR_CAST_CONSTNESS, + pedantic, + "casting using `as` from and to raw pointers to change constness when specialized methods apply" +} + +declare_clippy_lint! { + /// ### What it does /// Checks for casts from an enum type to an integral type which will definitely truncate the /// value. /// @@ -652,6 +681,7 @@ impl_lint_pass!(Casts => [ FN_TO_NUMERIC_CAST_WITH_TRUNCATION, CHAR_LIT_AS_U8, PTR_AS_PTR, + PTR_CAST_CONSTNESS, CAST_ENUM_TRUNCATION, CAST_ENUM_CONSTRUCTOR, CAST_ABS_TO_UNSIGNED, @@ -685,6 +715,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts { return; } cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, &self.msrv); + ptr_cast_constness::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv); as_ptr_cast_mut::check(cx, expr, cast_expr, cast_to); fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to); fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to); diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs new file mode 100644 index 00000000000..ab015f8822e --- /dev/null +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -0,0 +1,44 @@ +use clippy_utils::msrvs::POINTER_CAST_CONSTNESS; +use clippy_utils::sugg::Sugg; +use clippy_utils::{diagnostics::span_lint_and_sugg, msrvs::Msrv}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{Expr, Mutability}; +use rustc_lint::LateContext; +use rustc_middle::ty::{self, Ty, TypeAndMut}; + +use super::PTR_CAST_CONSTNESS; + +pub(super) fn check( + cx: &LateContext<'_>, + expr: &Expr<'_>, + cast_expr: &Expr<'_>, + cast_from: Ty<'_>, + cast_to: Ty<'_>, + msrv: &Msrv, +) { + if_chain! { + if msrv.meets(POINTER_CAST_CONSTNESS); + if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind(); + if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind(); + if matches!((from_mutbl, to_mutbl), + (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not)); + then { + let sugg = Sugg::hir(cx, cast_expr, "_"); + let constness = match *to_mutbl { + Mutability::Not => "const", + Mutability::Mut => "mut", + }; + + span_lint_and_sugg( + cx, + PTR_CAST_CONSTNESS, + expr.span, + "`as` casting between raw pointers while changing its constness", + &format!("try `pointer::cast_{constness}`, a safer alternative"), + format!("{}.cast_{constness}()", sugg.maybe_par()), + Applicability::MachineApplicable, + ); + } + } +} |
