Skip to content

Commit 8c319e2

Browse files
committed
cast_slice_from_raw_parts: check for implicit cast to raw slice pointer
changelog: [`cast_slice_from_raw_parts`]: check for implicit cast to raw slice pointer Signed-off-by: Zihan <[email protected]>
1 parent 264bc97 commit 8c319e2

File tree

5 files changed

+92
-8
lines changed

5 files changed

+92
-8
lines changed

clippy_lints/src/casts/cast_slice_from_raw_parts.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::get_parent_expr;
23
use clippy_utils::msrvs::{self, Msrv};
34
use clippy_utils::source::snippet_with_context;
45
use rustc_errors::Applicability;
56
use rustc_hir::def_id::DefId;
67
use rustc_hir::{Expr, ExprKind};
78
use rustc_lint::LateContext;
9+
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
810
use rustc_middle::ty::{self, Ty};
911
use rustc_span::sym;
1012

@@ -53,3 +55,40 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
5355
);
5456
}
5557
}
58+
59+
/// Checks for implicit cast from slice reference to raw slice pointer.
60+
pub(super) fn check_implicit_cast(cx: &LateContext<'_>, expr: &Expr<'_>) {
61+
if let ExprKind::Call(fun, [ptr_arg, len_arg]) = expr.peel_blocks().kind
62+
&& let ExprKind::Path(ref qpath) = fun.kind
63+
&& let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
64+
&& let Some(rpk) = raw_parts_kind(cx, fun_def_id)
65+
&& !matches!(get_parent_expr(cx, expr).map(|e| e.kind), Some(ExprKind::Cast(..)))
66+
&& let [deref, borrow] = cx.typeck_results().expr_adjustments(expr)
67+
&& matches!(deref.kind, Adjust::Deref(..))
68+
&& let Adjustment {
69+
kind: Adjust::Borrow(AutoBorrow::RawPtr(..)),
70+
target,
71+
} = borrow
72+
&& let ty::RawPtr(pointee_ty, _) = target.kind()
73+
&& pointee_ty.is_slice()
74+
&& !expr.span.from_expansion()
75+
{
76+
let func = match rpk {
77+
RawPartsKind::Immutable => "from_raw_parts",
78+
RawPartsKind::Mutable => "from_raw_parts_mut",
79+
};
80+
let mut applicability = Applicability::MachineApplicable;
81+
let ctxt = expr.span.ctxt();
82+
let ptr = snippet_with_context(cx, ptr_arg.span, ctxt, "ptr", &mut applicability).0;
83+
let len = snippet_with_context(cx, len_arg.span, ctxt, "len", &mut applicability).0;
84+
span_lint_and_sugg(
85+
cx,
86+
CAST_SLICE_FROM_RAW_PARTS,
87+
expr.span,
88+
format!("implicitly casting the result of `{func}` to `{target}`"),
89+
"replace_with",
90+
format!("core::ptr::slice_{func}({ptr}, {len})"),
91+
applicability,
92+
);
93+
}
94+
}

clippy_lints/src/casts/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,9 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
910910
if self.msrv.meets(cx, msrvs::RAW_REF_OP) {
911911
borrow_as_ptr::check_implicit_cast(cx, expr);
912912
}
913+
if self.msrv.meets(cx, msrvs::PTR_SLICE_RAW_PARTS) {
914+
cast_slice_from_raw_parts::check_implicit_cast(cx, expr);
915+
}
913916
cast_ptr_alignment::check(cx, expr);
914917
char_lit_as_u8::check(cx, expr);
915918
ptr_as_ptr::check(cx, expr, self.msrv);

tests/ui/cast_raw_slice_pointer_cast.fixed

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![warn(clippy::cast_slice_from_raw_parts)]
22

3+
fn require_raw_slice_ptr<T>(_: *const [T]) {}
4+
35
#[allow(unused_imports, unused_unsafe)]
46
fn main() {
57
let mut vec = vec![0u8; 1];
@@ -27,4 +29,14 @@ fn main() {
2729
let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1);
2830
//~^ cast_slice_from_raw_parts
2931
}
32+
33+
// implicit cast
34+
{
35+
let _: *const [u8] = unsafe { core::ptr::slice_from_raw_parts(ptr, 1) };
36+
//~^ cast_slice_from_raw_parts
37+
let _: *mut [u8] = unsafe { core::ptr::slice_from_raw_parts_mut(mptr, 1) };
38+
//~^ cast_slice_from_raw_parts
39+
require_raw_slice_ptr(unsafe { core::ptr::slice_from_raw_parts(ptr, 1) });
40+
//~^ cast_slice_from_raw_parts
41+
}
3042
}

tests/ui/cast_raw_slice_pointer_cast.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![warn(clippy::cast_slice_from_raw_parts)]
22

3+
fn require_raw_slice_ptr<T>(_: *const [T]) {}
4+
35
#[allow(unused_imports, unused_unsafe)]
46
fn main() {
57
let mut vec = vec![0u8; 1];
@@ -27,4 +29,14 @@ fn main() {
2729
let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8];
2830
//~^ cast_slice_from_raw_parts
2931
}
32+
33+
// implicit cast
34+
{
35+
let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) };
36+
//~^ cast_slice_from_raw_parts
37+
let _: *mut [u8] = unsafe { std::slice::from_raw_parts_mut(mptr, 1) };
38+
//~^ cast_slice_from_raw_parts
39+
require_raw_slice_ptr(unsafe { std::slice::from_raw_parts(ptr, 1) });
40+
//~^ cast_slice_from_raw_parts
41+
}
3042
}
Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: casting the result of `from_raw_parts` to *const [u8]
2-
--> tests/ui/cast_raw_slice_pointer_cast.rs:8:35
2+
--> tests/ui/cast_raw_slice_pointer_cast.rs:10:35
33
|
44
LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) as *const [u8] };
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)`
@@ -8,40 +8,58 @@ LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) as *co
88
= help: to override `-D warnings` add `#[allow(clippy::cast_slice_from_raw_parts)]`
99

1010
error: casting the result of `from_raw_parts_mut` to *mut [u8]
11-
--> tests/ui/cast_raw_slice_pointer_cast.rs:10:35
11+
--> tests/ui/cast_raw_slice_pointer_cast.rs:12:35
1212
|
1313
LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts_mut(mptr, 1) as *mut [u8] };
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts_mut(mptr, 1)`
1515

1616
error: casting the result of `from_raw_parts` to *const [u8]
17-
--> tests/ui/cast_raw_slice_pointer_cast.rs:12:26
17+
--> tests/ui/cast_raw_slice_pointer_cast.rs:14:26
1818
|
1919
LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) } as *const [u8];
2020
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)`
2121

2222
error: casting the result of `from_raw_parts` to *const [u8]
23-
--> tests/ui/cast_raw_slice_pointer_cast.rs:16:30
23+
--> tests/ui/cast_raw_slice_pointer_cast.rs:18:30
2424
|
2525
LL | let _: *const [u8] = unsafe { slice::from_raw_parts(ptr, 1) } as *const [u8];
2626
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)`
2727

2828
error: casting the result of `from_raw_parts` to *const [u8]
29-
--> tests/ui/cast_raw_slice_pointer_cast.rs:19:30
29+
--> tests/ui/cast_raw_slice_pointer_cast.rs:21:30
3030
|
3131
LL | let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8];
3232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)`
3333

3434
error: casting the result of `from_raw_parts` to *const [u8]
35-
--> tests/ui/cast_raw_slice_pointer_cast.rs:24:30
35+
--> tests/ui/cast_raw_slice_pointer_cast.rs:26:30
3636
|
3737
LL | let _: *const [u8] = unsafe { slice::from_raw_parts(ptr, 1) } as *const [u8];
3838
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)`
3939

4040
error: casting the result of `from_raw_parts` to *const [u8]
41-
--> tests/ui/cast_raw_slice_pointer_cast.rs:27:30
41+
--> tests/ui/cast_raw_slice_pointer_cast.rs:29:30
4242
|
4343
LL | let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8];
4444
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)`
4545

46-
error: aborting due to 7 previous errors
46+
error: implicitly casting the result of `from_raw_parts` to `*const [u8]`
47+
--> tests/ui/cast_raw_slice_pointer_cast.rs:35:39
48+
|
49+
LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) };
50+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `core::ptr::slice_from_raw_parts(ptr, 1)`
51+
52+
error: implicitly casting the result of `from_raw_parts_mut` to `*mut [u8]`
53+
--> tests/ui/cast_raw_slice_pointer_cast.rs:37:37
54+
|
55+
LL | let _: *mut [u8] = unsafe { std::slice::from_raw_parts_mut(mptr, 1) };
56+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `core::ptr::slice_from_raw_parts_mut(mptr, 1)`
57+
58+
error: implicitly casting the result of `from_raw_parts` to `*const [u8]`
59+
--> tests/ui/cast_raw_slice_pointer_cast.rs:39:40
60+
|
61+
LL | require_raw_slice_ptr(unsafe { std::slice::from_raw_parts(ptr, 1) });
62+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `core::ptr::slice_from_raw_parts(ptr, 1)`
63+
64+
error: aborting due to 10 previous errors
4765

0 commit comments

Comments
 (0)