diff options
| author | asquared31415 <34665709+asquared31415@users.noreply.github.com> | 2022-04-23 12:49:40 -0400 |
|---|---|---|
| committer | asquared31415 <34665709+asquared31415@users.noreply.github.com> | 2022-04-23 13:07:13 -0400 |
| commit | af9dfa36921a66116e2cbd4a2aeb8f8f7e0082e9 (patch) | |
| tree | 23eb6835408957b9cadbcfbbbdd55c8d307d9db2 | |
| parent | c922bb9443993df9f32ebf25bed76195cfab11f2 (diff) | |
| download | rust-af9dfa36921a66116e2cbd4a2aeb8f8f7e0082e9.tar.gz rust-af9dfa36921a66116e2cbd4a2aeb8f8f7e0082e9.zip | |
fix ICE by using a type to return the info we want and also fix some bugs in displaying an extra mut when a TypeAndMut was wrong
| -rw-r--r-- | clippy_lints/src/casts/cast_slice_different_sizes.rs | 109 | ||||
| -rw-r--r-- | tests/ui/cast_slice_different_sizes.rs | 10 | ||||
| -rw-r--r-- | tests/ui/cast_slice_different_sizes.stderr | 50 |
3 files changed, 113 insertions, 56 deletions
diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs index ff03f416d0b..893af60db2c 100644 --- a/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -8,31 +8,6 @@ use rustc_semver::RustcVersion; use super::CAST_SLICE_DIFFERENT_SIZES; -fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - let map = cx.tcx.hir(); - if_chain! { - if let Some(parent_id) = map.find_parent_node(expr.hir_id); - if let Some(parent) = map.find(parent_id); - then { - let expr = match parent { - Node::Block(block) => { - if let Some(parent_expr) = block.expr { - parent_expr - } else { - return false; - } - }, - Node::Expr(expr) => expr, - _ => return false, - }; - - matches!(expr.kind, ExprKind::Cast(..)) - } else { - false - } - } -} - pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Option<RustcVersion>) { // suggestion is invalid if `ptr::slice_from_raw_parts` does not exist if !meets_msrv(msrv.as_ref(), &msrvs::PTR_SLICE_RAW_PARTS) { @@ -45,8 +20,13 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Option<RustcVe return; } - if let Some((from_slice_ty, to_slice_ty)) = expr_cast_chain_tys(cx, expr) { - if let (Ok(from_layout), Ok(to_layout)) = (cx.layout_of(from_slice_ty.ty), cx.layout_of(to_slice_ty.ty)) { + if let Some(CastChainInfo { + left_cast, + start_ty, + end_ty, + }) = expr_cast_chain_tys(cx, expr) + { + if let (Ok(from_layout), Ok(to_layout)) = (cx.layout_of(start_ty.ty), cx.layout_of(end_ty.ty)) { let from_size = from_layout.size.bytes(); let to_size = to_layout.size.bytes(); if from_size != to_size && from_size != 0 && to_size != 0 { @@ -56,21 +36,20 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Option<RustcVe expr.span, &format!( "casting between raw pointers to `[{}]` (element size {}) and `[{}]` (element size {}) does not adjust the count", - from_slice_ty, from_size, to_slice_ty, to_size, + start_ty.ty, from_size, end_ty.ty, to_size, ), |diag| { - let cast_expr = match expr.peel_blocks().kind { - ExprKind::Cast(cast_expr, ..) => cast_expr, - _ => unreachable!("expr should be a cast as checked by expr_cast_chain_tys"), - }; - let ptr_snippet = snippet_opt(cx, cast_expr.span).unwrap(); + let ptr_snippet = snippet_opt(cx, left_cast.span).unwrap(); - let (mutbl_fn_str, mutbl_ptr_str) = match to_slice_ty.mutbl { + let (mutbl_fn_str, mutbl_ptr_str) = match end_ty.mutbl { Mutability::Mut => ("_mut", "mut"), Mutability::Not => ("", "const"), }; let sugg = format!( - "core::ptr::slice_from_raw_parts{mutbl_fn_str}({ptr_snippet} as *{mutbl_ptr_str} {to_slice_ty}, ..)" + "core::ptr::slice_from_raw_parts{mutbl_fn_str}({ptr_snippet} as *{mutbl_ptr_str} {}, ..)", + // get just the ty from the TypeAndMut so that the printed type isn't something like `mut + // T`, extract just the `T` + end_ty.ty ); diag.span_suggestion( @@ -86,6 +65,31 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Option<RustcVe } } +fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + let map = cx.tcx.hir(); + if_chain! { + if let Some(parent_id) = map.find_parent_node(expr.hir_id); + if let Some(parent) = map.find(parent_id); + then { + let expr = match parent { + Node::Block(block) => { + if let Some(parent_expr) = block.expr { + parent_expr + } else { + return false; + } + }, + Node::Expr(expr) => expr, + _ => return false, + }; + + matches!(expr.kind, ExprKind::Cast(..)) + } else { + false + } + } +} + /// Returns the type T of the pointed to *const [T] or *mut [T] and the mutability of the slice if /// the type is one of those slices fn get_raw_slice_ty_mut(ty: Ty<'_>) -> Option<TypeAndMut<'_>> { @@ -98,18 +102,43 @@ fn get_raw_slice_ty_mut(ty: Ty<'_>) -> Option<TypeAndMut<'_>> { } } -/// Returns the pair (original ptr T, final ptr U) if the expression is composed of casts +struct CastChainInfo<'expr, 'tcx> { + /// The left most part of the cast chain, or in other words, the first cast in the chain + /// Used for diagnostics + left_cast: &'expr Expr<'expr>, + /// The starting type of the cast chain + start_ty: TypeAndMut<'tcx>, + /// The final type of the cast chain + end_ty: TypeAndMut<'tcx>, +} + +// FIXME(asquared31415): unbounded recursion linear with the number of casts in an expression +/// Returns a `CastChainInfo` with the left-most cast in the chain and the original ptr T and final +/// ptr U if the expression is composed of casts. /// Returns None if the expr is not a Cast -fn expr_cast_chain_tys<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option<(TypeAndMut<'tcx>, TypeAndMut<'tcx>)> { +fn expr_cast_chain_tys<'tcx, 'expr>(cx: &LateContext<'tcx>, expr: &Expr<'expr>) -> Option<CastChainInfo<'expr, 'tcx>> { if let ExprKind::Cast(cast_expr, _cast_to_hir_ty) = expr.peel_blocks().kind { let cast_to = cx.typeck_results().expr_ty(expr); let to_slice_ty = get_raw_slice_ty_mut(cast_to)?; - if let Some((inner_from_ty, _inner_to_ty)) = expr_cast_chain_tys(cx, cast_expr) { - Some((inner_from_ty, to_slice_ty)) + if let Some(CastChainInfo { + left_cast, + start_ty, + end_ty: _, + }) = expr_cast_chain_tys(cx, cast_expr) + { + Some(CastChainInfo { + left_cast, + start_ty, + end_ty: to_slice_ty, + }) } else { let cast_from = cx.typeck_results().expr_ty(cast_expr); let from_slice_ty = get_raw_slice_ty_mut(cast_from)?; - Some((from_slice_ty, to_slice_ty)) + Some(CastChainInfo { + left_cast: cast_expr, + start_ty: from_slice_ty, + end_ty: to_slice_ty, + }) } } else { None diff --git a/tests/ui/cast_slice_different_sizes.rs b/tests/ui/cast_slice_different_sizes.rs index 7ec137cc5b2..24d7eb28a19 100644 --- a/tests/ui/cast_slice_different_sizes.rs +++ b/tests/ui/cast_slice_different_sizes.rs @@ -62,6 +62,16 @@ fn bar2(x: *mut [u16]) -> *mut [u8] { x as _ } +// constify +fn bar3(x: *mut [u16]) -> *const [u8] { + x as _ +} + +// unconstify +fn bar4(x: *const [u16]) -> *mut [u8] { + x as _ +} + // function returns plus blocks fn blocks(x: *mut [u16]) -> *mut [u8] { ({ x }) as _ diff --git a/tests/ui/cast_slice_different_sizes.stderr b/tests/ui/cast_slice_different_sizes.stderr index 0e018b62e60..40721dcd05d 100644 --- a/tests/ui/cast_slice_different_sizes.stderr +++ b/tests/ui/cast_slice_different_sizes.stderr @@ -46,58 +46,76 @@ error: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (elem --> $DIR/cast_slice_different_sizes.rs:38:27 | LL | let long_chain_loss = r_x as *const [i32] as *const [u32] as *const [u16] as *const [i8] as *const [u8]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts`: `core::ptr::slice_from_raw_parts(r_x as *const [i32] as *const [u32] as *const [u16] as *const [i8] as *const u8, ..)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts`: `core::ptr::slice_from_raw_parts(r_x as *const [i32] as *const u8, ..)` -error: casting between raw pointers to `[mut u16]` (element size 2) and `[mut u8]` (element size 1) does not adjust the count +error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count --> $DIR/cast_slice_different_sizes.rs:53:36 | LL | fn bar(x: *mut [u16]) -> *mut [u8] { | ____________________________________^ LL | | x as *mut [u8] LL | | } - | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(x as *mut mut u8, ..)` + | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(x as *mut u8, ..)` -error: casting between raw pointers to `[mut u16]` (element size 2) and `[mut u8]` (element size 1) does not adjust the count +error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count --> $DIR/cast_slice_different_sizes.rs:57:36 | LL | fn uwu(x: *mut [u16]) -> *mut [u8] { | ____________________________________^ LL | | x as *mut _ LL | | } - | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(x as *mut mut u8, ..)` + | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(x as *mut u8, ..)` -error: casting between raw pointers to `[mut u16]` (element size 2) and `[mut u8]` (element size 1) does not adjust the count +error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count --> $DIR/cast_slice_different_sizes.rs:61:37 | LL | fn bar2(x: *mut [u16]) -> *mut [u8] { | _____________________________________^ LL | | x as _ LL | | } - | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(x as *mut mut u8, ..)` + | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(x as *mut u8, ..)` -error: casting between raw pointers to `[mut u16]` (element size 2) and `[mut u8]` (element size 1) does not adjust the count +error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count --> $DIR/cast_slice_different_sizes.rs:66:39 | +LL | fn bar3(x: *mut [u16]) -> *const [u8] { + | _______________________________________^ +LL | | x as _ +LL | | } + | |_^ help: replace with `ptr::slice_from_raw_parts`: `core::ptr::slice_from_raw_parts(x as *const u8, ..)` + +error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count + --> $DIR/cast_slice_different_sizes.rs:71:39 + | +LL | fn bar4(x: *const [u16]) -> *mut [u8] { + | _______________________________________^ +LL | | x as _ +LL | | } + | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(x as *mut u8, ..)` + +error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count + --> $DIR/cast_slice_different_sizes.rs:76:39 + | LL | fn blocks(x: *mut [u16]) -> *mut [u8] { | _______________________________________^ LL | | ({ x }) as _ LL | | } - | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(({ x }) as *mut mut u8, ..)` + | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(({ x }) as *mut u8, ..)` -error: casting between raw pointers to `[mut u16]` (element size 2) and `[mut u8]` (element size 1) does not adjust the count - --> $DIR/cast_slice_different_sizes.rs:70:44 +error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count + --> $DIR/cast_slice_different_sizes.rs:80:44 | LL | fn more_blocks(x: *mut [u16]) -> *mut [u8] { | ____________________________________________^ LL | | { ({ x }) as _ } LL | | } - | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(({ x }) as *mut mut u8, ..)` + | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(({ x }) as *mut u8, ..)` -error: casting between raw pointers to `[mut u16]` (element size 2) and `[mut u8]` (element size 1) does not adjust the count - --> $DIR/cast_slice_different_sizes.rs:71:5 +error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count + --> $DIR/cast_slice_different_sizes.rs:81:5 | LL | { ({ x }) as _ } - | ^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(({ x }) as *mut mut u8, ..)` + | ^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(({ x }) as *mut u8, ..)` -error: aborting due to 12 previous errors +error: aborting due to 14 previous errors |
