Skip to content

cast_slice_from_raw_parts not triggered for equivalent cast-less conversions #15127

Open
@briansmith

Description

@briansmith

Summary

cast_slice_from_raw_parts only looks for problematic cases where there is a cast using as. However, if you follow other advice from Clippy and/or other tools, those as conversions will get rewritten to equivalent conversions that do not use as. But as isn't really the problem; the problem is the construction of a &mut [T] slice when we only want a *mut [T]. Indeed, the rust-lang/rust code that had the bug that motivated the lint uses a cast that could have been written like the convert_slice_from_raw_parts_return_value example below; it just happened to have an unnecessary cast.

I think it would be hard to decide all the different types of conversion operations that should trigger the lint. However, I think at least the case of implicit conversions from reference to pointer should trigger it.

I include only examples for &mut T as those are the ones that are actually problematic--it seems the &T case for the lint is really only done for symmetry--but the analogous &T cases have the same issue.

Lint Name

cast_slice_from_raw_parts

Reproducer

I tried this code:

#![no_std]
#![allow(dead_code)]
#![deny(clippy::cast_slice_from_raw_parts)]

fn convert_slice_from_raw_parts_return_value(slice: &mut [u8]) -> *mut [u8] {
    let (ptr, len) = (slice.as_mut_ptr(), slice.len());
    // Clippy notes cast_slice_from_raw_parts with this unnecessary cast:
    // (unsafe { std::slice::from_raw_parts_mut(ptr, len) }) as *mut [u8] 
    // But not this equivalent:
    unsafe { core::slice::from_raw_parts_mut(ptr, len) }
}

fn convert_slice_from_raw_parts_local() {
    let slice: &mut [u8] = &mut [0];
    let (ptr, len) = (slice.as_mut_ptr(), slice.len());
    // Clippy notes cast_slice_from_raw_parts with this unnecessary cast:
    // let _: *mut [u8] = unsafe { core::slice::from_raw_parts_mut(ptr, len) } as *mut [u8];
    // But not this equivalent:
    let _: *mut [u8] = unsafe { core::slice::from_raw_parts_mut(ptr, len) };
}

fn from_mut_slice_from_raw_parts_return_value(slice: &mut [u8]) -> *mut [u8] {
    let (ptr, len) = (slice.as_mut_ptr(), slice.len());
    // Clippy notes cast_slice_from_raw_parts with this unnecessary cast:
    // (unsafe { core::slice::from_raw_parts_mut(ptr, len) }) as *mut [u8] 
    // But not this equivalent:
    core::ptr::from_mut(unsafe { core::slice::from_raw_parts_mut(ptr, len) })
}

fn from_mut_slice_from_raw_parts_local() {
    let slice: &mut [u8] = &mut [0];
    let (ptr, len) = (slice.as_mut_ptr(), slice.len());
    // Clippy notes cast_slice_from_raw_parts with this unnecessary cast:
    // let _: *mut [u8] = unsafe { core::slice::from_raw_parts_mut(ptr, len) } as *mut [u8];
    // But not this equivalent:
    let _: *mut [u8] = core::ptr::from_mut(unsafe { core::slice::from_raw_parts_mut(ptr, len) });
}

I expected to see this happen:
Four cast_slice_from_raw_parts warnings treated as errors.

Instead, this happened:
No errors or warnings.

Version

Nightly channel
Build using the Nightly version: 1.90.0-nightly
(2025-06-23 706f244db581212cabf2)

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: Clippy is not doing the correct thingI-false-negativeIssue: The lint should have been triggered on code, but wasn't

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions