Auto merge of #126319 - workingjubilee:rollup-lendnud, r=workingjubilee
Rollup of 16 pull requests Successful merges: - #123374 (DOC: Add FFI example for slice::from_raw_parts()) - #124514 (Recommend to never display zero disambiguators when demangling v0 symbols) - #125978 (Cleanup: HIR ty lowering: Consolidate the places that do assoc item probing & access checking) - #125980 (Nvptx remove direct passmode) - #126187 (For E0277 suggest adding `Result` return type for function when using QuestionMark `?` in the body.) - #126210 (docs(core): make more const_ptr doctests assert instead of printing) - #126249 (Simplify `[T; N]::try_map` signature) - #126256 (Add {{target}} substitution to compiletest) - #126263 (Make issue-122805.rs big endian compatible) - #126281 (set_env: State the conclusion upfront) - #126286 (Make `storage-live.rs` robust against rustc internal changes.) - #126287 (Update a cranelift patch file for formatting changes.) - #126301 (Use `tidy` to sort crate attributes for all compiler crates.) - #126305 (Make PathBuf less Ok with adding UTF-16 then `into_string`) - #126310 (Migrate run make prefer rlib) - #126314 (fix RELEASES: we do not support upcasting to auto traits) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
@@ -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)))
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
///
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user