diff --git a/CHANGELOG.md b/CHANGELOG.md index bf49ddfbd741..cc966972939a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5380,6 +5380,7 @@ Released 2018-09-13 [`arc_with_non_send_sync`]: https://rust-lang.github.io/rust-clippy/master/index.html#arc_with_non_send_sync [`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects [`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions +[`as_pointer_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_pointer_underscore [`as_ptr_cast_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_ptr_cast_mut [`as_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_underscore [`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants diff --git a/clippy_lints/src/casts/as_pointer_underscore.rs b/clippy_lints/src/casts/as_pointer_underscore.rs new file mode 100644 index 000000000000..536126fd02b3 --- /dev/null +++ b/clippy_lints/src/casts/as_pointer_underscore.rs @@ -0,0 +1,19 @@ +use rustc_errors::Applicability; +use rustc_lint::LateContext; +use rustc_middle::ty::Ty; + +pub fn check<'tcx>(cx: &LateContext<'tcx>, ty_into: Ty<'_>, cast_to_hir: &'tcx rustc_hir::Ty<'tcx>) { + if let rustc_hir::TyKind::Ptr(rustc_hir::MutTy { ty, .. }) = cast_to_hir.kind + && matches!(ty.kind, rustc_hir::TyKind::Infer) + { + clippy_utils::diagnostics::span_lint_and_sugg( + cx, + super::AS_POINTER_UNDERSCORE, + cast_to_hir.span, + "using inferred pointer cast", + "use explicit type", + ty_into.to_string(), + Applicability::MachineApplicable, + ); + } +} diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 84fab9cb75f8..c64c0e15144d 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -1,3 +1,4 @@ +mod as_pointer_underscore; mod as_ptr_cast_mut; mod as_underscore; mod borrow_as_ptr; @@ -726,6 +727,33 @@ declare_clippy_lint! { "using `as` to cast a reference to pointer" } +declare_clippy_lint! { + /// ### What it does + /// Checks for the usage of `as *const _` or `as *mut _` conversion using inferred type. + /// + /// ### Why restrict this? + /// The conversion might include a dangerous cast that might go undetected due to the type being inferred. + /// + /// ### Example + /// ```no_run + /// fn as_usize(t: &T) -> usize { + /// // BUG: `t` is already a reference, so we will here + /// // return a dangling pointer to a temporary value instead + /// &t as *const _ as usize + /// } + /// ``` + /// Use instead: + /// ```no_run + /// fn as_usize(t: &T) -> usize { + /// t as *const T as usize + /// } + /// ``` + #[clippy::version = "1.81.0"] + pub AS_POINTER_UNDERSCORE, + restriction, + "detects `as *mut _` and `as *const _` conversion" +} + pub struct Casts { msrv: Msrv, } @@ -763,6 +791,7 @@ impl_lint_pass!(Casts => [ CAST_NAN_TO_INT, ZERO_PTR, REF_AS_PTR, + AS_POINTER_UNDERSCORE, ]); impl<'tcx> LateLintPass<'tcx> for Casts { @@ -805,6 +834,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts { } as_underscore::check(cx, expr, cast_to_hir); + as_pointer_underscore::check(cx, cast_to, cast_to_hir); let was_borrow_as_ptr_emitted = if self.msrv.meets(msrvs::BORROW_AS_PTR) { borrow_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir, &self.msrv) diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 1dcf3a874491..304622afe530 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -75,6 +75,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::cargo::NEGATIVE_FEATURE_NAMES_INFO, crate::cargo::REDUNDANT_FEATURE_NAMES_INFO, crate::cargo::WILDCARD_DEPENDENCIES_INFO, + crate::casts::AS_POINTER_UNDERSCORE_INFO, crate::casts::AS_PTR_CAST_MUT_INFO, crate::casts::AS_UNDERSCORE_INFO, crate::casts::BORROW_AS_PTR_INFO, diff --git a/tests/ui/as_pointer_underscore.fixed b/tests/ui/as_pointer_underscore.fixed new file mode 100644 index 000000000000..db06486ecb04 --- /dev/null +++ b/tests/ui/as_pointer_underscore.fixed @@ -0,0 +1,15 @@ +#![warn(clippy::as_pointer_underscore)] +#![crate_type = "lib"] +#![no_std] + +struct S; + +fn f(s: &S) -> usize { + &s as *const &S as usize + //~^ ERROR: using inferred pointer cast +} + +fn g(s: &mut S) -> usize { + s as *mut S as usize + //~^ ERROR: using inferred pointer cast +} diff --git a/tests/ui/as_pointer_underscore.rs b/tests/ui/as_pointer_underscore.rs new file mode 100644 index 000000000000..955c702ccc99 --- /dev/null +++ b/tests/ui/as_pointer_underscore.rs @@ -0,0 +1,15 @@ +#![warn(clippy::as_pointer_underscore)] +#![crate_type = "lib"] +#![no_std] + +struct S; + +fn f(s: &S) -> usize { + &s as *const _ as usize + //~^ ERROR: using inferred pointer cast +} + +fn g(s: &mut S) -> usize { + s as *mut _ as usize + //~^ ERROR: using inferred pointer cast +} diff --git a/tests/ui/as_pointer_underscore.stderr b/tests/ui/as_pointer_underscore.stderr new file mode 100644 index 000000000000..270056f36454 --- /dev/null +++ b/tests/ui/as_pointer_underscore.stderr @@ -0,0 +1,17 @@ +error: using inferred pointer cast + --> tests/ui/as_pointer_underscore.rs:8:11 + | +LL | &s as *const _ as usize + | ^^^^^^^^ help: use explicit type: `*const &S` + | + = note: `-D clippy::as-pointer-underscore` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::as_pointer_underscore)]` + +error: using inferred pointer cast + --> tests/ui/as_pointer_underscore.rs:13:10 + | +LL | s as *mut _ as usize + | ^^^^^^ help: use explicit type: `*mut S` + +error: aborting due to 2 previous errors +