Skip to content

Commit 6b8fb7c

Browse files
authored
Rollup merge of #71082 - NeoRaider:ptr_slice_len, r=oli-obk,SimonSapin
ptr: introduce len() method on raw slices It is already possible to extract the pointer part of a raw slice by a simple cast, but retrieving the length is not possible without relying on the representation of the raw slice when it is not valid to convert the raw slice into a slice reference (i.e. the pointer is null or unaligned). ~Introduce a new function ptr::slice_len() to add this missing feature.~ Introduce a len() method on raw slices to add this missing feature.
2 parents 119e32b + dfd6844 commit 6b8fb7c

File tree

6 files changed

+93
-4
lines changed

6 files changed

+93
-4
lines changed

src/libcore/ptr/const_ptr.rs

+28
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,34 @@ impl<T: ?Sized> *const T {
706706
}
707707
}
708708

709+
#[cfg(not(bootstrap))]
710+
#[lang = "const_slice_ptr"]
711+
impl<T> *const [T] {
712+
/// Returns the length of a raw slice.
713+
///
714+
/// The returned value is the number of **elements**, not the number of bytes.
715+
///
716+
/// This function is safe, even when the raw slice cannot be cast to a slice
717+
/// reference because the pointer is null or unaligned.
718+
///
719+
/// # Examples
720+
///
721+
/// ```rust
722+
/// #![feature(slice_ptr_len)]
723+
///
724+
/// use std::ptr;
725+
///
726+
/// let slice: *const [i8] = ptr::slice_from_raw_parts(ptr::null(), 3);
727+
/// assert_eq!(slice.len(), 3);
728+
/// ```
729+
#[inline]
730+
#[unstable(feature = "slice_ptr_len", issue = "71146")]
731+
#[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
732+
pub const fn len(self) -> usize {
733+
unsafe { Repr { rust: self }.raw }.len
734+
}
735+
}
736+
709737
// Equality for pointers
710738
#[stable(feature = "rust1", since = "1.0.0")]
711739
impl<T: ?Sized> PartialEq for *const T {

src/libcore/ptr/mut_ptr.rs

+28
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,34 @@ impl<T: ?Sized> *mut T {
894894
}
895895
}
896896

897+
#[cfg(not(bootstrap))]
898+
#[lang = "mut_slice_ptr"]
899+
impl<T> *mut [T] {
900+
/// Returns the length of a raw slice.
901+
///
902+
/// The returned value is the number of **elements**, not the number of bytes.
903+
///
904+
/// This function is safe, even when the raw slice cannot be cast to a slice
905+
/// reference because the pointer is null or unaligned.
906+
///
907+
/// # Examples
908+
///
909+
/// ```rust
910+
/// #![feature(slice_ptr_len)]
911+
///
912+
/// use std::ptr;
913+
///
914+
/// let slice: *mut [i8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 3);
915+
/// assert_eq!(slice.len(), 3);
916+
/// ```
917+
#[inline]
918+
#[unstable(feature = "slice_ptr_len", issue = "71146")]
919+
#[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
920+
pub const fn len(self) -> usize {
921+
unsafe { Repr { rust_mut: self }.raw }.len
922+
}
923+
}
924+
897925
// Equality for pointers
898926
#[stable(feature = "rust1", since = "1.0.0")]
899927
impl<T: ?Sized> PartialEq for *mut T {

src/librustc_hir/lang_items.rs

+2
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ language_item_table! {
135135
SliceU8AllocImplItem, "slice_u8_alloc", slice_u8_alloc_impl, Target::Impl;
136136
ConstPtrImplItem, "const_ptr", const_ptr_impl, Target::Impl;
137137
MutPtrImplItem, "mut_ptr", mut_ptr_impl, Target::Impl;
138+
ConstSlicePtrImplItem, "const_slice_ptr", const_slice_ptr_impl, Target::Impl;
139+
MutSlicePtrImplItem, "mut_slice_ptr", mut_slice_ptr_impl, Target::Impl;
138140
I8ImplItem, "i8", i8_impl, Target::Impl;
139141
I16ImplItem, "i16", i16_impl, Target::Impl;
140142
I32ImplItem, "i32", i32_impl, Target::Impl;

src/librustc_typeck/check/method/probe.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -649,11 +649,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
649649
}
650650
}
651651
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl }) => {
652-
let lang_def_id = match mutbl {
653-
hir::Mutability::Not => lang_items.const_ptr_impl(),
654-
hir::Mutability::Mut => lang_items.mut_ptr_impl(),
652+
let (lang_def_id1, lang_def_id2) = match mutbl {
653+
hir::Mutability::Not => {
654+
(lang_items.const_ptr_impl(), lang_items.const_slice_ptr_impl())
655+
}
656+
hir::Mutability::Mut => {
657+
(lang_items.mut_ptr_impl(), lang_items.mut_slice_ptr_impl())
658+
}
655659
};
656-
self.assemble_inherent_impl_for_primitive(lang_def_id);
660+
self.assemble_inherent_impl_for_primitive(lang_def_id1);
661+
self.assemble_inherent_impl_for_primitive(lang_def_id2);
657662
}
658663
ty::Int(i) => {
659664
let lang_def_id = match i {

src/librustc_typeck/coherence/inherent_impls.rs

+24
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,30 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
112112
item.span,
113113
);
114114
}
115+
ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not })
116+
if matches!(inner.kind, ty::Slice(_)) =>
117+
{
118+
self.check_primitive_impl(
119+
def_id,
120+
lang_items.const_slice_ptr_impl(),
121+
None,
122+
"const_slice_ptr",
123+
"*const [T]",
124+
item.span,
125+
);
126+
}
127+
ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut })
128+
if matches!(inner.kind, ty::Slice(_)) =>
129+
{
130+
self.check_primitive_impl(
131+
def_id,
132+
lang_items.mut_slice_ptr_impl(),
133+
None,
134+
"mut_slice_ptr",
135+
"*mut [T]",
136+
item.span,
137+
);
138+
}
115139
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
116140
self.check_primitive_impl(
117141
def_id,

src/librustdoc/passes/collect_trait_impls.rs

+2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
6262
lang_items.slice_u8_alloc_impl(),
6363
lang_items.const_ptr_impl(),
6464
lang_items.mut_ptr_impl(),
65+
lang_items.const_slice_ptr_impl(),
66+
lang_items.mut_slice_ptr_impl(),
6567
];
6668

6769
for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {

0 commit comments

Comments
 (0)