about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-04-14 23:29:56 +0200
committerGitHub <noreply@github.com>2020-04-14 23:29:56 +0200
commit6b8fb7c48a05241a6f7e8e8ee4ea656739f87a80 (patch)
tree6549050378c51a896a15704e0f85e806d792b76e
parent119e32bca17873c018faf4e0351819311f84aafb (diff)
parentdfd68441beba4db959697974949bc7f613a13e2e (diff)
downloadrust-6b8fb7c48a05241a6f7e8e8ee4ea656739f87a80.tar.gz
rust-6b8fb7c48a05241a6f7e8e8ee4ea656739f87a80.zip
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.
-rw-r--r--src/libcore/ptr/const_ptr.rs28
-rw-r--r--src/libcore/ptr/mut_ptr.rs28
-rw-r--r--src/librustc_hir/lang_items.rs2
-rw-r--r--src/librustc_typeck/check/method/probe.rs13
-rw-r--r--src/librustc_typeck/coherence/inherent_impls.rs24
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs2
6 files changed, 93 insertions, 4 deletions
diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs
index 52e224d2a02..729e0b897c0 100644
--- a/src/libcore/ptr/const_ptr.rs
+++ b/src/libcore/ptr/const_ptr.rs
@@ -706,6 +706,34 @@ impl<T: ?Sized> *const T {
     }
 }
 
+#[cfg(not(bootstrap))]
+#[lang = "const_slice_ptr"]
+impl<T> *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 = "71146")]
+    #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw }.len
+    }
+}
+
 // Equality for pointers
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> PartialEq for *const T {
diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs
index 9f85d781d69..3b7e83bf37f 100644
--- a/src/libcore/ptr/mut_ptr.rs
+++ b/src/libcore/ptr/mut_ptr.rs
@@ -894,6 +894,34 @@ impl<T: ?Sized> *mut T {
     }
 }
 
+#[cfg(not(bootstrap))]
+#[lang = "mut_slice_ptr"]
+impl<T> *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 = "71146")]
+    #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust_mut: self }.raw }.len
+    }
+}
+
 // Equality for pointers
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> PartialEq for *mut T {
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,
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) {