libs-team: std::slice::from_raw_parts alternative that would accept a null pointer if len == 0 by returning an empty slice
Proposal
Problem statement
Currently, it’s not allowed to pass a NULL pointer to std::slice::from_raw_parts, but
I have a pointer that comes from a C function that can be either:
A) A non-NULL with a len > 0 B) A NULL with a len == 0
Solution sketch
It would be neat if it was possible to just write something like:
let values = unsafe { std::slice::from_raw_parts_or_empty(c_ptr_to_values, len) }; // Still panic if c_ptr_to_values == NULL and len > 0.
for value in values {
// This can be skipped if values is an empty slice when c_ptr_to_values == NULL and len == 0.
// Or values can be iterated when c_ptr_to_values != NULL and len > 0.
}
About this issue
- Original URL
- State: open
- Created 4 months ago
- Reactions: 10
- Comments: 16 (11 by maintainers)
I suppose – but at the very least, it should not be solely based on
len == 0like https://github.com/rust-lang/libs-team/issues/350#issuecomment-1987137744. If given a non-null pointer, regardless of length, that should be preserved.I feel really wary of having
slice::from_raw_partsthat would not round-trip withas_mut_ptr, but it seems less concerning with the_or_emptyversion to indicate that it’s not just the raw values.This briefly came up in the libs-api meeting. We thought it’d probably be useful to do a perf run to see the impact a check in
std::slice::from_raw_partswould have on rustc.@cuviper Nice catch, indeed I didn’t think of that, I updated the code…
but currently
std::slice::from_raw_parts(null(), 0)(notstd::ptr::from_raw_parts) is undefined behavior according to the doc (&[T]must be non-null), so it not round-tripping with.as_mut_ptr()for the null case is certainly allowed 🙃I don’t think we should be touching the existing functions simply because of how widely used they are in the ecosystem. Even adding a simple check there could have a large performance impact.
Pondering: is there a reasonable way we could have a takes-
NonNullversion offrom_raw_parts(and the_mutone)? If so, that one could be the one without the check for null – after all, there’s a type proof it’s not null – and we could change the existing method to always check for null-and-zero-length, returning<&[_]>::default()in those cases.I don’t know if that’s a good idea, though. I don’t know how to weight the tradeoff between fixing any broken unsafe code that’s trying to do this today vs the potential cost of either the extra extraneous check or people migrating.
Actually, maybe it’s completely fine, since if a parameter is
ptr noundef nonnull, LLVM seems perfectly capable of removing the extra null check: https://rust.godbolt.org/z/PbY1recY3