From c922bb9443993df9f32ebf25bed76195cfab11f2 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Mon, 18 Apr 2022 22:19:34 -0400 Subject: [PATCH 1/4] fix ICE --- .../src/casts/cast_slice_different_sizes.rs | 2 +- tests/ui/cast_slice_different_sizes.rs | 31 +++++++++++ tests/ui/cast_slice_different_sizes.stderr | 53 ++++++++++++++++++- 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs index 3608c1654d5..ff03f416d0b 100644 --- a/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -59,7 +59,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Option cast_expr, _ => unreachable!("expr should be a cast as checked by expr_cast_chain_tys"), }; diff --git a/tests/ui/cast_slice_different_sizes.rs b/tests/ui/cast_slice_different_sizes.rs index 57270fcf52b..7ec137cc5b2 100644 --- a/tests/ui/cast_slice_different_sizes.rs +++ b/tests/ui/cast_slice_different_sizes.rs @@ -39,3 +39,34 @@ fn main() { let long_chain_restore = r_x as *const [i32] as *const [u32] as *const [u16] as *const [i8] as *const [u8] as *const [u32]; } + +// foo and foo2 should not fire, they're the same size +fn foo(x: *mut [u8]) -> *mut [u8] { + x as *mut [u8] +} + +fn foo2(x: *mut [u8]) -> *mut [u8] { + x as *mut _ +} + +// Test that casts as part of function returns work +fn bar(x: *mut [u16]) -> *mut [u8] { + x as *mut [u8] +} + +fn uwu(x: *mut [u16]) -> *mut [u8] { + x as *mut _ +} + +fn bar2(x: *mut [u16]) -> *mut [u8] { + x as _ +} + +// function returns plus blocks +fn blocks(x: *mut [u16]) -> *mut [u8] { + ({ x }) as _ +} + +fn more_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 993e93c2bf3..0e018b62e60 100644 --- a/tests/ui/cast_slice_different_sizes.stderr +++ b/tests/ui/cast_slice_different_sizes.stderr @@ -48,5 +48,56 @@ error: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (elem 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, ..)` -error: aborting due to 6 previous errors +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: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, ..)` + +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: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, ..)` + +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: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, ..)` + +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:66: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, ..)` + +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 + | +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, ..)` + +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 + | +LL | { ({ x }) as _ } + | ^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(({ x }) as *mut mut u8, ..)` + +error: aborting due to 12 previous errors From af9dfa36921a66116e2cbd4a2aeb8f8f7e0082e9 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Sat, 23 Apr 2022 12:49:40 -0400 Subject: [PATCH 2/4] 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 --- .../src/casts/cast_slice_different_sizes.rs | 145 +++++++++++------- tests/ui/cast_slice_different_sizes.rs | 10 ++ tests/ui/cast_slice_different_sizes.stderr | 50 ++++-- 3 files changed, 131 insertions(+), 74 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,6 +8,63 @@ use rustc_semver::RustcVersion; use super::CAST_SLICE_DIFFERENT_SIZES; +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Option) { + // suggestion is invalid if `ptr::slice_from_raw_parts` does not exist + if !meets_msrv(msrv.as_ref(), &msrvs::PTR_SLICE_RAW_PARTS) { + return; + } + + // if this cast is the child of another cast expression then don't emit something for it, the full + // chain will be analyzed + if is_child_of_cast(cx, expr) { + return; + } + + 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 { + span_lint_and_then( + cx, + CAST_SLICE_DIFFERENT_SIZES, + expr.span, + &format!( + "casting between raw pointers to `[{}]` (element size {}) and `[{}]` (element size {}) does not adjust the count", + start_ty.ty, from_size, end_ty.ty, to_size, + ), + |diag| { + let ptr_snippet = snippet_opt(cx, left_cast.span).unwrap(); + + 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} {}, ..)", + // 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( + expr.span, + &format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"), + sugg, + rustc_errors::Applicability::HasPlaceholders, + ); + }, + ); + } + } + } +} + fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let map = cx.tcx.hir(); if_chain! { @@ -33,59 +90,6 @@ fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { } } -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Option) { - // suggestion is invalid if `ptr::slice_from_raw_parts` does not exist - if !meets_msrv(msrv.as_ref(), &msrvs::PTR_SLICE_RAW_PARTS) { - return; - } - - // if this cast is the child of another cast expression then don't emit something for it, the full - // chain will be analyzed - if is_child_of_cast(cx, expr) { - 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)) { - 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 { - span_lint_and_then( - cx, - CAST_SLICE_DIFFERENT_SIZES, - 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, - ), - |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 (mutbl_fn_str, mutbl_ptr_str) = match to_slice_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}, ..)" - ); - - diag.span_suggestion( - expr.span, - &format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"), - sugg, - rustc_errors::Applicability::HasPlaceholders, - ); - }, - ); - } - } - } -} - /// 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> { @@ -98,18 +102,43 @@ fn get_raw_slice_ty_mut(ty: Ty<'_>) -> Option> { } } -/// 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> { 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 From cf99f504fde3cab40e4b961281e53bbe18858829 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Sun, 24 Apr 2022 19:41:43 -0400 Subject: [PATCH 3/4] remove extra lifetime --- clippy_lints/src/casts/cast_slice_different_sizes.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs index 893af60db2c..16c9e49ff11 100644 --- a/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -8,7 +8,7 @@ use rustc_semver::RustcVersion; use super::CAST_SLICE_DIFFERENT_SIZES; -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Option) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Option) { // suggestion is invalid if `ptr::slice_from_raw_parts` does not exist if !meets_msrv(msrv.as_ref(), &msrvs::PTR_SLICE_RAW_PARTS) { return; @@ -102,21 +102,20 @@ fn get_raw_slice_ty_mut(ty: Ty<'_>) -> Option> { } } -struct CastChainInfo<'expr, 'tcx> { +struct CastChainInfo<'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>, + left_cast: &'tcx Expr<'tcx>, /// 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, 'expr>(cx: &LateContext<'tcx>, expr: &Expr<'expr>) -> Option> { +fn expr_cast_chain_tys<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option> { 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)?; From 8f8fc9f71752e8df80152a402b992bdd819be7f3 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Thu, 28 Apr 2022 21:27:32 -0400 Subject: [PATCH 4/4] use non-panicking snippet, use struct update syntax and add comment --- .../src/casts/cast_slice_different_sizes.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs index 16c9e49ff11..2238668abca 100644 --- a/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -1,4 +1,4 @@ -use clippy_utils::{diagnostics::span_lint_and_then, meets_msrv, msrvs, source::snippet_opt}; +use clippy_utils::{diagnostics::span_lint_and_then, meets_msrv, msrvs, source}; use if_chain::if_chain; use rustc_ast::Mutability; use rustc_hir::{Expr, ExprKind, Node}; @@ -39,7 +39,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Opti start_ty.ty, from_size, end_ty.ty, to_size, ), |diag| { - let ptr_snippet = snippet_opt(cx, left_cast.span).unwrap(); + let ptr_snippet = source::snippet(cx, left_cast.span, ".."); let (mutbl_fn_str, mutbl_ptr_str) = match end_ty.mutbl { Mutability::Mut => ("_mut", "mut"), @@ -119,16 +119,14 @@ fn expr_cast_chain_tys<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Optio 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(CastChainInfo { - left_cast, - start_ty, - end_ty: _, - }) = expr_cast_chain_tys(cx, cast_expr) - { + + // If the expression that makes up the source of this cast is itself a cast, recursively + // call `expr_cast_chain_tys` and update the end type with the final tartet type. + // Otherwise, this cast is not immediately nested, just construct the info for this cast + if let Some(prev_info) = expr_cast_chain_tys(cx, cast_expr) { Some(CastChainInfo { - left_cast, - start_ty, end_ty: to_slice_ty, + ..prev_info }) } else { let cast_from = cx.typeck_results().expr_ty(cast_expr);