diff options
Diffstat (limited to 'library/core')
| -rw-r--r-- | library/core/src/array/mod.rs | 6 | ||||
| -rw-r--r-- | library/core/src/ops/try_trait.rs | 4 | ||||
| -rw-r--r-- | library/core/src/ptr/const_ptr.rs | 38 | ||||
| -rw-r--r-- | library/core/src/slice/raw.rs | 33 |
4 files changed, 60 insertions, 21 deletions
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 05874ab6c4c..2569ce23707 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -533,11 +533,9 @@ impl<T, const N: usize> [T; N] { /// assert_eq!(c, Some(a)); /// ``` #[unstable(feature = "array_try_map", issue = "79711")] - pub fn try_map<F, R>(self, f: F) -> ChangeOutputType<R, [R::Output; N]> + pub fn try_map<R>(self, f: impl FnMut(T) -> R) -> ChangeOutputType<R, [R::Output; N]> where - F: FnMut(T) -> R, - R: Try, - R::Residual: Residual<[R::Output; N]>, + R: Try<Residual: Residual<[R::Output; N]>>, { drain_array_with(self, |iter| try_from_trusted_iterator(iter.map(f))) } diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 483f55b2070..cd444c86ed0 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -363,7 +363,9 @@ pub trait Residual<O> { } #[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")] -pub(crate) type ChangeOutputType<T, V> = <<T as Try>::Residual as Residual<V>>::TryType; +#[allow(type_alias_bounds)] +pub(crate) type ChangeOutputType<T: Try<Residual: Residual<V>>, V> = + <T::Residual as Residual<V>>::TryType; /// An adapter for implementing non-try methods via the `Try` implementation. /// diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 8c02aee8bfb..b1f94caed35 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -330,7 +330,7 @@ impl<T: ?Sized> *const T { /// /// unsafe { /// if let Some(val_back) = ptr.as_ref() { - /// println!("We got back the value: {val_back}!"); + /// assert_eq!(val_back, &10); /// } /// } /// ``` @@ -346,7 +346,7 @@ impl<T: ?Sized> *const T { /// /// unsafe { /// let val_back = &*ptr; - /// println!("We got back the value: {val_back}!"); + /// assert_eq!(val_back, &10); /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] @@ -393,7 +393,7 @@ impl<T: ?Sized> *const T { /// let ptr: *const u8 = &10u8 as *const u8; /// /// unsafe { - /// println!("We got back the value: {}!", ptr.as_ref_unchecked()); + /// assert_eq!(ptr.as_ref_unchecked(), &10); /// } /// ``` // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. @@ -439,7 +439,7 @@ impl<T: ?Sized> *const T { /// /// unsafe { /// if let Some(val_back) = ptr.as_uninit_ref() { - /// println!("We got back the value: {}!", val_back.assume_init()); + /// assert_eq!(val_back.assume_init(), 10); /// } /// } /// ``` @@ -501,8 +501,8 @@ impl<T: ?Sized> *const T { /// let ptr: *const u8 = s.as_ptr(); /// /// unsafe { - /// println!("{}", *ptr.offset(1) as char); - /// println!("{}", *ptr.offset(2) as char); + /// assert_eq!(*ptr.offset(1) as char, '2'); + /// assert_eq!(*ptr.offset(2) as char, '3'); /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -573,19 +573,21 @@ impl<T: ?Sized> *const T { /// # Examples /// /// ``` + /// # use std::fmt::Write; /// // Iterate using a raw pointer in increments of two elements /// let data = [1u8, 2, 3, 4, 5]; /// let mut ptr: *const u8 = data.as_ptr(); /// let step = 2; /// let end_rounded_up = ptr.wrapping_offset(6); /// - /// // This loop prints "1, 3, 5, " + /// let mut out = String::new(); /// while ptr != end_rounded_up { /// unsafe { - /// print!("{}, ", *ptr); + /// write!(&mut out, "{}, ", *ptr).unwrap(); /// } /// ptr = ptr.wrapping_offset(step); /// } + /// assert_eq!(out.as_str(), "1, 3, 5, "); /// ``` #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")] #[must_use = "returns a new pointer rather than modifying its argument"] @@ -988,8 +990,8 @@ impl<T: ?Sized> *const T { /// let ptr: *const u8 = s.as_ptr(); /// /// unsafe { - /// println!("{}", *ptr.add(1) as char); - /// println!("{}", *ptr.add(2) as char); + /// assert_eq!(*ptr.add(1), b'2'); + /// assert_eq!(*ptr.add(2), b'3'); /// } /// ``` #[stable(feature = "pointer_methods", since = "1.26.0")] @@ -1073,8 +1075,8 @@ impl<T: ?Sized> *const T { /// /// unsafe { /// let end: *const u8 = s.as_ptr().add(3); - /// println!("{}", *end.sub(1) as char); - /// println!("{}", *end.sub(2) as char); + /// assert_eq!(*end.sub(1), b'3'); + /// assert_eq!(*end.sub(2), b'2'); /// } /// ``` #[stable(feature = "pointer_methods", since = "1.26.0")] @@ -1155,19 +1157,21 @@ impl<T: ?Sized> *const T { /// # Examples /// /// ``` + /// # use std::fmt::Write; /// // Iterate using a raw pointer in increments of two elements /// let data = [1u8, 2, 3, 4, 5]; /// let mut ptr: *const u8 = data.as_ptr(); /// let step = 2; /// let end_rounded_up = ptr.wrapping_add(6); /// - /// // This loop prints "1, 3, 5, " + /// let mut out = String::new(); /// while ptr != end_rounded_up { /// unsafe { - /// print!("{}, ", *ptr); + /// write!(&mut out, "{}, ", *ptr).unwrap(); /// } /// ptr = ptr.wrapping_add(step); /// } + /// assert_eq!(out, "1, 3, 5, "); /// ``` #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] @@ -1234,19 +1238,21 @@ impl<T: ?Sized> *const T { /// # Examples /// /// ``` + /// # use std::fmt::Write; /// // Iterate using a raw pointer in increments of two elements (backwards) /// let data = [1u8, 2, 3, 4, 5]; /// let mut ptr: *const u8 = data.as_ptr(); /// let start_rounded_down = ptr.wrapping_sub(2); /// ptr = ptr.wrapping_add(4); /// let step = 2; - /// // This loop prints "5, 3, 1, " + /// let mut out = String::new(); /// while ptr != start_rounded_down { /// unsafe { - /// print!("{}, ", *ptr); + /// write!(&mut out, "{}, ", *ptr).unwrap(); /// } /// ptr = ptr.wrapping_sub(step); /// } + /// assert_eq!(out, "5, 3, 1, "); /// ``` #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 3f4305866e6..280aead270e 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -82,6 +82,39 @@ use crate::ub_checks; /// } /// ``` /// +/// ### FFI: Handling null pointers +/// +/// In languages such as C++, pointers to empty collections are not guaranteed to be non-null. +/// When accepting such pointers, they have to be checked for null-ness to avoid undefined +/// behavior. +/// +/// ``` +/// use std::slice; +/// +/// /// Sum the elements of an FFI slice. +/// /// +/// /// # Safety +/// /// +/// /// If ptr is not NULL, it must be correctly aligned and +/// /// point to `len` initialized items of type `f32`. +/// unsafe extern "C" fn sum_slice(ptr: *const f32, len: usize) -> f32 { +/// let data = if ptr.is_null() { +/// // `len` is assumed to be 0. +/// &[] +/// } else { +/// // SAFETY: see function docstring. +/// unsafe { slice::from_raw_parts(ptr, len) } +/// }; +/// data.into_iter().sum() +/// } +/// +/// // This could be the result of C++'s std::vector::data(): +/// let ptr = std::ptr::null(); +/// // And this could be std::vector::size(): +/// let len = 0; +/// assert_eq!(unsafe { sum_slice(ptr, len) }, 0.0); +/// ``` +/// /// [valid]: ptr#safety /// [`NonNull::dangling()`]: ptr::NonNull::dangling #[inline] |
