From 10ae85f527ee98c0f6fd812fd96bd2821c25b0d2 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 13 Apr 2020 20:52:06 +0200 Subject: [PATCH 1/5] rustc: add lang items "const_slice_ptr" and "mut_slice_ptr" Add lang items for methods on raw slices. --- src/librustc_hir/lang_items.rs | 2 ++ src/librustc_typeck/check/method/probe.rs | 13 ++++++---- .../coherence/inherent_impls.rs | 24 +++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs index 5a3a9cabeb4..53f72804a84 100644 --- a/src/librustc_hir/lang_items.rs +++ b/src/librustc_hir/lang_items.rs @@ -135,6 +135,8 @@ language_item_table! { SliceU8AllocImplItem, "slice_u8_alloc", slice_u8_alloc_impl, Target::Impl; ConstPtrImplItem, "const_ptr", const_ptr_impl, Target::Impl; MutPtrImplItem, "mut_ptr", mut_ptr_impl, Target::Impl; + ConstSlicePtrImplItem, "const_slice_ptr", const_slice_ptr_impl, Target::Impl; + MutSlicePtrImplItem, "mut_slice_ptr", mut_slice_ptr_impl, Target::Impl; I8ImplItem, "i8", i8_impl, Target::Impl; I16ImplItem, "i16", i16_impl, Target::Impl; I32ImplItem, "i32", i32_impl, Target::Impl; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index b5d3f7b5502..9b1c8b9a9c8 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -649,11 +649,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } ty::RawPtr(ty::TypeAndMut { ty: _, mutbl }) => { - let lang_def_id = match mutbl { - hir::Mutability::Not => lang_items.const_ptr_impl(), - hir::Mutability::Mut => lang_items.mut_ptr_impl(), + let (lang_def_id1, lang_def_id2) = match mutbl { + hir::Mutability::Not => { + (lang_items.const_ptr_impl(), lang_items.const_slice_ptr_impl()) + } + hir::Mutability::Mut => { + (lang_items.mut_ptr_impl(), lang_items.mut_slice_ptr_impl()) + } }; - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(lang_def_id1); + self.assemble_inherent_impl_for_primitive(lang_def_id2); } ty::Int(i) => { let lang_def_id = match i { diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index 9ace9f424b7..2e841734770 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -112,6 +112,30 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { item.span, ); } + ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not }) + if matches!(inner.kind, ty::Slice(_)) => + { + self.check_primitive_impl( + def_id, + lang_items.const_slice_ptr_impl(), + None, + "const_slice_ptr", + "*const [T]", + item.span, + ); + } + ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut }) + if matches!(inner.kind, ty::Slice(_)) => + { + self.check_primitive_impl( + def_id, + lang_items.mut_slice_ptr_impl(), + None, + "mut_slice_ptr", + "*mut [T]", + item.span, + ); + } ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => { self.check_primitive_impl( def_id, From 0c17b3f4f4ad973694f31c027d44c73f3577fd07 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 13 Apr 2020 21:00:32 +0200 Subject: [PATCH 2/5] rustdoc: add "const_slice_ptr" and "mut_slice_ptr" trait impls --- src/librustdoc/passes/collect_trait_impls.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index da0e97f1075..c80967a4b33 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -62,6 +62,8 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { lang_items.slice_u8_alloc_impl(), lang_items.const_ptr_impl(), lang_items.mut_ptr_impl(), + lang_items.const_slice_ptr_impl(), + lang_items.mut_slice_ptr_impl(), ]; for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) { From 43612e21a61bf6cd4bf741ffce64d7dd3b8ee19f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 13 Apr 2020 20:57:35 +0200 Subject: [PATCH 3/5] ptr: implement "const_slice_ptr" and "mut_slice_ptr" lang items --- src/libcore/ptr/const_ptr.rs | 4 ++++ src/libcore/ptr/mut_ptr.rs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index 52e224d2a02..00bd985114a 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -706,6 +706,10 @@ impl *const T { } } +#[cfg(not(bootstrap))] +#[lang = "const_slice_ptr"] +impl *const [T] {} + // Equality for pointers #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for *const T { diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 9f85d781d69..00084456839 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -894,6 +894,10 @@ impl *mut T { } } +#[cfg(not(bootstrap))] +#[lang = "mut_slice_ptr"] +impl *mut [T] {} + // Equality for pointers #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for *mut T { From 2a29f8f89deb34356e767e3c0fb9fdd6d4fdbc27 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 13 Apr 2020 20:58:23 +0200 Subject: [PATCH 4/5] 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 len() method on raw slices to add this missing feature. --- src/libcore/ptr/const_ptr.rs | 26 +++++++++++++++++++++++++- src/libcore/ptr/mut_ptr.rs | 26 +++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index 00bd985114a..33c9e0b5315 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -708,7 +708,31 @@ impl *const T { #[cfg(not(bootstrap))] #[lang = "const_slice_ptr"] -impl *const [T] {} +impl *const [T] { + /// Returns the length of a raw slice. + /// + /// The returned value is the number of **elements**, not the number of bytes. + /// + /// This function is safe, even when the raw slice cannot be cast to a slice + /// reference because the pointer is null or unaligned. + /// + /// # Examples + /// + /// ```rust + /// #![feature(slice_ptr_len)] + /// + /// use std::ptr; + /// + /// let slice: *const [i8] = ptr::slice_from_raw_parts(ptr::null(), 3); + /// assert_eq!(slice.len(), 3); + /// ``` + #[inline] + #[unstable(feature = "slice_ptr_len", issue = "none")] + #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "none")] + pub const fn len(self) -> usize { + unsafe { Repr { rust: self }.raw }.len + } +} // Equality for pointers #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 00084456839..89475973675 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -896,7 +896,31 @@ impl *mut T { #[cfg(not(bootstrap))] #[lang = "mut_slice_ptr"] -impl *mut [T] {} +impl *mut [T] { + /// Returns the length of a raw slice. + /// + /// The returned value is the number of **elements**, not the number of bytes. + /// + /// This function is safe, even when the raw slice cannot be cast to a slice + /// reference because the pointer is null or unaligned. + /// + /// # Examples + /// + /// ```rust + /// #![feature(slice_ptr_len)] + /// + /// use std::ptr; + /// + /// let slice: *mut [i8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 3); + /// assert_eq!(slice.len(), 3); + /// ``` + #[inline] + #[unstable(feature = "slice_ptr_len", issue = "none")] + #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "none")] + pub const fn len(self) -> usize { + unsafe { Repr { rust_mut: self }.raw }.len + } +} // Equality for pointers #[stable(feature = "rust1", since = "1.0.0")] From dfd68441beba4db959697974949bc7f613a13e2e Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 14 Apr 2020 21:34:27 +0200 Subject: [PATCH 5/5] ptr: add tracking issue for len() method on raw slices --- src/libcore/ptr/const_ptr.rs | 4 ++-- src/libcore/ptr/mut_ptr.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index 33c9e0b5315..729e0b897c0 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -727,8 +727,8 @@ impl *const [T] { /// assert_eq!(slice.len(), 3); /// ``` #[inline] - #[unstable(feature = "slice_ptr_len", issue = "none")] - #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "none")] + #[unstable(feature = "slice_ptr_len", issue = "71146")] + #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] pub const fn len(self) -> usize { unsafe { Repr { rust: self }.raw }.len } diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 89475973675..3b7e83bf37f 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -915,8 +915,8 @@ impl *mut [T] { /// assert_eq!(slice.len(), 3); /// ``` #[inline] - #[unstable(feature = "slice_ptr_len", issue = "none")] - #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "none")] + #[unstable(feature = "slice_ptr_len", issue = "71146")] + #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] pub const fn len(self) -> usize { unsafe { Repr { rust_mut: self }.raw }.len }