Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
014a33e
Add target-specific NaN payloads for the missing tier 2 targets
beetrees Mar 23, 2025
5d44bfa
Implement Default for raw pointers
ChrisDenton Apr 6, 2025
34c490a
Implement `pin!()` using `super let`.
m-ou-se Mar 27, 2025
c7c402d
fix incorrect type in cstr `to_string_lossy()` docs
jnqnfe Apr 16, 2025
6130899
std: Use fstatat() on illumos
pfmooney Apr 18, 2025
1f202b0
Sort Unix env constants alphabetically by target_os
thaliaarchi Apr 15, 2025
0411c52
Combine env consts into std::sys::env_consts
thaliaarchi Apr 15, 2025
05ebb95
Handle unsupported fallback
thaliaarchi Apr 15, 2025
913b8f5
Auto merge of #139114 - m-ou-se:super-let-pin, r=davidtwco
bors Apr 19, 2025
6b3d1e9
add next_index to Enumerate
jogru0 Apr 8, 2025
f5e95cb
added doctest for Enumerate::next_index
jogru0 Apr 19, 2025
f89b8ee
added test for Enumerate::next_index on empty iterator
jogru0 Apr 19, 2025
efd7912
Rollup merge of #139535 - ChrisDenton:default-ptr, r=tgross35
ChrisDenton Apr 19, 2025
cfa1b2a
Rollup merge of #139922 - jnqnfe:cstr_doc_fix, r=jhpratt
ChrisDenton Apr 19, 2025
e3adc21
Rollup merge of #140016 - pfmooney:illumos-fstatat, r=jhpratt
ChrisDenton Apr 19, 2025
b9cfe06
Rollup merge of #139868 - thaliaarchi:move-env-consts-pal, r=joboet
ChrisDenton Apr 19, 2025
9bff288
Rollup merge of #139533 - jogru0:130711, r=Mark-Simulacrum
ChrisDenton Apr 19, 2025
d0721d4
Auto merge of #140043 - ChrisDenton:rollup-vwf0s9j, r=ChrisDenton
bors Apr 20, 2025
2ab28f3
Rollup merge of #138870 - beetrees:tier-2-nans, r=RalfJung
ChrisDenton Apr 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion alloc/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,7 @@ impl CStr {
/// with the corresponding <code>&[str]</code> slice. Otherwise, it will
/// replace any invalid UTF-8 sequences with
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
/// <code>[Cow]::[Owned]\(&[str])</code> with the result.
/// <code>[Cow]::[Owned]\([String])</code> with the result.
///
/// [str]: prim@str "str"
/// [Borrowed]: Cow::Borrowed
Expand Down
33 changes: 33 additions & 0 deletions core/src/iter/adapters/enumerate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,39 @@ impl<I> Enumerate<I> {
pub(in crate::iter) fn new(iter: I) -> Enumerate<I> {
Enumerate { iter, count: 0 }
}

/// Retrieve the current position of the iterator.
///
/// If the iterator has not advanced, the position returned will be 0.
///
/// The position may also exceed the bounds of the iterator to allow for calculating
/// the displacement of the iterator from following calls to [`Iterator::next`].
///
/// # Examples
///
/// ```
/// #![feature(next_index)]
///
/// let arr = ['a', 'b'];
///
/// let mut iter = arr.iter().enumerate();
///
/// assert_eq!(iter.next_index(), 0);
/// assert_eq!(iter.next(), Some((0, &'a')));
///
/// assert_eq!(iter.next_index(), 1);
/// assert_eq!(iter.next_index(), 1);
/// assert_eq!(iter.next(), Some((1, &'b')));
///
/// assert_eq!(iter.next_index(), 2);
/// assert_eq!(iter.next(), None);
/// assert_eq!(iter.next_index(), 2);
/// ```
#[inline]
#[unstable(feature = "next_index", issue = "130711")]
pub fn next_index(&self) -> usize {
self.count
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
137 changes: 35 additions & 102 deletions core/src/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,24 +1092,15 @@ pub use self::unsafe_pinned::UnsafePinned;
#[rustc_pub_transparent]
#[derive(Copy, Clone)]
pub struct Pin<Ptr> {
// FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to:
// - deter downstream users from accessing it (which would be unsound!),
// - let the `pin!` macro access it (such a macro requires using struct
// literal syntax in order to benefit from lifetime extension).
//
// However, if the `Deref` impl exposes a field with the same name as this
// field, then the two will collide, resulting in a confusing error when the
// user attempts to access the field through a `Pin<Ptr>`. Therefore, the
// name `__pointer` is designed to be unlikely to collide with any other
// field. Long-term, macro hygiene is expected to offer a more robust
// alternative, alongside `unsafe` fields.
#[unstable(feature = "unsafe_pin_internals", issue = "none")]
#[doc(hidden)]
pub __pointer: Ptr,
/// Only public for bootstrap.
#[cfg(bootstrap)]
pub pointer: Ptr,
#[cfg(not(bootstrap))]
pointer: Ptr,
}

// The following implementations aren't derived in order to avoid soundness
// issues. `&self.__pointer` should not be accessible to untrusted trait
// issues. `&self.pointer` should not be accessible to untrusted trait
// implementations.
//
// See <https://internals.rust-lang.org/t/unsoundness-in-pin/11311/73> for more details.
Expand Down Expand Up @@ -1223,7 +1214,7 @@ impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> {
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
#[stable(feature = "pin_into_inner", since = "1.39.0")]
pub const fn into_inner(pin: Pin<Ptr>) -> Ptr {
pin.__pointer
pin.pointer
}
}

Expand Down Expand Up @@ -1360,7 +1351,7 @@ impl<Ptr: Deref> Pin<Ptr> {
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
#[stable(feature = "pin", since = "1.33.0")]
pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin<Ptr> {
Pin { __pointer: pointer }
Pin { pointer }
}

/// Gets a shared reference to the pinned value this [`Pin`] points to.
Expand All @@ -1374,7 +1365,7 @@ impl<Ptr: Deref> Pin<Ptr> {
#[inline(always)]
pub fn as_ref(&self) -> Pin<&Ptr::Target> {
// SAFETY: see documentation on this function
unsafe { Pin::new_unchecked(&*self.__pointer) }
unsafe { Pin::new_unchecked(&*self.pointer) }
}
}

Expand Down Expand Up @@ -1418,7 +1409,7 @@ impl<Ptr: DerefMut> Pin<Ptr> {
#[inline(always)]
pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> {
// SAFETY: see documentation on this function
unsafe { Pin::new_unchecked(&mut *self.__pointer) }
unsafe { Pin::new_unchecked(&mut *self.pointer) }
}

/// Gets `Pin<&mut T>` to the underlying pinned value from this nested `Pin`-pointer.
Expand Down Expand Up @@ -1485,7 +1476,7 @@ impl<Ptr: DerefMut> Pin<Ptr> {
where
Ptr::Target: Sized,
{
*(self.__pointer) = value;
*(self.pointer) = value;
}
}

Expand Down Expand Up @@ -1513,7 +1504,7 @@ impl<Ptr: Deref> Pin<Ptr> {
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
#[stable(feature = "pin_into_inner", since = "1.39.0")]
pub const unsafe fn into_inner_unchecked(pin: Pin<Ptr>) -> Ptr {
pin.__pointer
pin.pointer
}
}

Expand All @@ -1539,7 +1530,7 @@ impl<'a, T: ?Sized> Pin<&'a T> {
U: ?Sized,
F: FnOnce(&T) -> &U,
{
let pointer = &*self.__pointer;
let pointer = &*self.pointer;
let new_pointer = func(pointer);

// SAFETY: the safety contract for `new_unchecked` must be
Expand Down Expand Up @@ -1569,7 +1560,7 @@ impl<'a, T: ?Sized> Pin<&'a T> {
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
#[stable(feature = "pin", since = "1.33.0")]
pub const fn get_ref(self) -> &'a T {
self.__pointer
self.pointer
}
}

Expand All @@ -1580,7 +1571,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
#[stable(feature = "pin", since = "1.33.0")]
pub const fn into_ref(self) -> Pin<&'a T> {
Pin { __pointer: self.__pointer }
Pin { pointer: self.pointer }
}

/// Gets a mutable reference to the data inside of this `Pin`.
Expand All @@ -1600,7 +1591,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
where
T: Unpin,
{
self.__pointer
self.pointer
}

/// Gets a mutable reference to the data inside of this `Pin`.
Expand All @@ -1618,7 +1609,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
#[stable(feature = "pin", since = "1.33.0")]
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
pub const unsafe fn get_unchecked_mut(self) -> &'a mut T {
self.__pointer
self.pointer
}

/// Constructs a new pin by mapping the interior value.
Expand Down Expand Up @@ -1705,21 +1696,21 @@ impl<Ptr: LegacyReceiver> LegacyReceiver for Pin<Ptr> {}
#[stable(feature = "pin", since = "1.33.0")]
impl<Ptr: fmt::Debug> fmt::Debug for Pin<Ptr> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.__pointer, f)
fmt::Debug::fmt(&self.pointer, f)
}
}

#[stable(feature = "pin", since = "1.33.0")]
impl<Ptr: fmt::Display> fmt::Display for Pin<Ptr> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.__pointer, f)
fmt::Display::fmt(&self.pointer, f)
}
}

#[stable(feature = "pin", since = "1.33.0")]
impl<Ptr: fmt::Pointer> fmt::Pointer for Pin<Ptr> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.__pointer, f)
fmt::Pointer::fmt(&self.pointer, f)
}
}

Expand Down Expand Up @@ -1945,80 +1936,22 @@ unsafe impl<T: ?Sized> PinCoerceUnsized for *mut T {}
/// constructor.
///
/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin
#[cfg(not(bootstrap))]
#[stable(feature = "pin_macro", since = "1.68.0")]
#[rustc_macro_transparency = "semitransparent"]
#[allow_internal_unstable(unsafe_pin_internals)]
#[rustc_macro_edition_2021]
#[allow_internal_unstable(super_let)]
pub macro pin($value:expr $(,)?) {
// This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's
// review such a hypothetical macro (that any user-code could define):
//
// ```rust
// macro_rules! pin {( $value:expr ) => (
// match &mut { $value } { at_value => unsafe { // Do not wrap `$value` in an `unsafe` block.
// $crate::pin::Pin::<&mut _>::new_unchecked(at_value)
// }}
// )}
// ```
//
// Safety:
// - `type P = &mut _`. There are thus no pathological `Deref{,Mut}` impls
// that would break `Pin`'s invariants.
// - `{ $value }` is braced, making it a _block expression_, thus **moving**
// the given `$value`, and making it _become an **anonymous** temporary_.
// By virtue of being anonymous, it can no longer be accessed, thus
// preventing any attempts to `mem::replace` it or `mem::forget` it, _etc._
//
// This gives us a `pin!` definition that is sound, and which works, but only
// in certain scenarios:
// - If the `pin!(value)` expression is _directly_ fed to a function call:
// `let poll = pin!(fut).poll(cx);`
// - If the `pin!(value)` expression is part of a scrutinee:
// ```rust
// match pin!(fut) { pinned_fut => {
// pinned_fut.as_mut().poll(...);
// pinned_fut.as_mut().poll(...);
// }} // <- `fut` is dropped here.
// ```
// Alas, it doesn't work for the more straight-forward use-case: `let` bindings.
// ```rust
// let pinned_fut = pin!(fut); // <- temporary value is freed at the end of this statement
// pinned_fut.poll(...) // error[E0716]: temporary value dropped while borrowed
// // note: consider using a `let` binding to create a longer lived value
// ```
// - Issues such as this one are the ones motivating https://github.com/rust-lang/rfcs/pull/66
//
// This makes such a macro incredibly unergonomic in practice, and the reason most macros
// out there had to take the path of being a statement/binding macro (_e.g._, `pin!(future);`)
// instead of featuring the more intuitive ergonomics of an expression macro.
//
// Luckily, there is a way to avoid the problem. Indeed, the problem stems from the fact that a
// temporary is dropped at the end of its enclosing statement when it is part of the parameters
// given to function call, which has precisely been the case with our `Pin::new_unchecked()`!
// For instance,
// ```rust
// let p = Pin::new_unchecked(&mut <temporary>);
// ```
// becomes:
// ```rust
// let p = { let mut anon = <temporary>; &mut anon };
// ```
//
// However, when using a literal braced struct to construct the value, references to temporaries
// can then be taken. This makes Rust change the lifespan of such temporaries so that they are,
// instead, dropped _at the end of the enscoping block_.
// For instance,
// ```rust
// let p = Pin { __pointer: &mut <temporary> };
// ```
// becomes:
// ```rust
// let mut anon = <temporary>;
// let p = Pin { __pointer: &mut anon };
// ```
// which is *exactly* what we want.
//
// See https://doc.rust-lang.org/1.58.1/reference/destructors.html#temporary-lifetime-extension
// for more info.
$crate::pin::Pin::<&mut _> { __pointer: &mut { $value } }
{
super let mut pinned = $value;
// SAFETY: The value is pinned: it is the local above which cannot be named outside this macro.
unsafe { $crate::pin::Pin::new_unchecked(&mut pinned) }
}
}

/// Only for bootstrap.
#[cfg(bootstrap)]
#[stable(feature = "pin_macro", since = "1.68.0")]
#[rustc_macro_transparency = "semitransparent"]
pub macro pin($value:expr $(,)?) {
$crate::pin::Pin::<&mut _> { pointer: &mut { $value } }
}
8 changes: 5 additions & 3 deletions core/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1307,10 +1307,12 @@ mod prim_f16 {}
// FIXME: Is there a better place to put this?
///
/// | `target_arch` | Extra payloads possible on this platform |
/// |---------------|---------|
/// | `x86`, `x86_64`, `arm`, `aarch64`, `riscv32`, `riscv64` | None |
/// |---------------|------------------------------------------|
// Sorted alphabetically
/// | `aarch64`, `arm`, `arm64ec`, `loongarch64`, `powerpc` (except when `target_abi = "spe"`), `powerpc64`, `riscv32`, `riscv64`, `s390x`, `x86`, `x86_64` | None |
/// | `nvptx64` | All payloads |
/// | `sparc`, `sparc64` | The all-one payload |
/// | `wasm32`, `wasm64` | If all input NaNs are quiet with all-zero payload: None.<br> Otherwise: all possible payloads. |
/// | `wasm32`, `wasm64` | If all input NaNs are quiet with all-zero payload: None.<br> Otherwise: all payloads. |
///
/// For targets not in this table, all payloads are possible.
///
Expand Down
8 changes: 8 additions & 0 deletions core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1739,3 +1739,11 @@ impl<T: ?Sized> PartialOrd for *const T {
*self >= *other
}
}

#[stable(feature = "raw_ptr_default", since = "CURRENT_RUSTC_VERSION")]
impl<T: ?Sized + Thin> Default for *const T {
/// Returns the default value of [`null()`][crate::ptr::null].
fn default() -> Self {
crate::ptr::null()
}
}
8 changes: 8 additions & 0 deletions core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2156,3 +2156,11 @@ impl<T: ?Sized> PartialOrd for *mut T {
*self >= *other
}
}

#[stable(feature = "raw_ptr_default", since = "CURRENT_RUSTC_VERSION")]
impl<T: ?Sized + Thin> Default for *mut T {
/// Returns the default value of [`null_mut()`][crate::ptr::null_mut].
fn default() -> Self {
crate::ptr::null_mut()
}
}
10 changes: 10 additions & 0 deletions coretests/tests/iter/adapters/enumerate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,13 @@ fn test_double_ended_enumerate() {
assert_eq!(it.next_back(), Some((2, 3)));
assert_eq!(it.next(), None);
}

#[test]
fn test_empty_iterator_enumerate_next_index() {
let mut it = empty::<i32>().enumerate();
assert_eq!(it.next_index(), 0);
assert_eq!(it.next_index(), 0);
assert_eq!(it.next(), None);
assert_eq!(it.next_index(), 0);
assert_eq!(it.next_index(), 0);
}
1 change: 1 addition & 0 deletions coretests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
#![feature(maybe_uninit_write_slice)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(next_index)]
#![feature(numfmt)]
#![feature(pattern)]
#![feature(pointer_is_aligned_to)]
Expand Down
1 change: 1 addition & 0 deletions coretests/tests/pin_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ fn rust_2024_expr() {
}

#[test]
#[cfg(not(bootstrap))]
fn temp_lifetime() {
// Check that temporary lifetimes work as in Rust 2021.
// Regression test for https://github.com/rust-lang/rust/issues/138596
Expand Down
17 changes: 17 additions & 0 deletions coretests/tests/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,3 +1020,20 @@ fn test_ptr_swap_nonoverlapping_is_untyped() {
ptr_swap_nonoverlapping_is_untyped_inner();
const { ptr_swap_nonoverlapping_is_untyped_inner() };
}

#[test]
fn test_ptr_default() {
#[derive(Default)]
struct PtrDefaultTest {
ptr: *const u64,
}
let default = PtrDefaultTest::default();
assert!(default.ptr.is_null());

#[derive(Default)]
struct PtrMutDefaultTest {
ptr: *mut u64,
}
let default = PtrMutDefaultTest::default();
assert!(default.ptr.is_null());
}
2 changes: 1 addition & 1 deletion std/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ impl fmt::Debug for ArgsOs {
/// Constants associated with the current target
#[stable(feature = "env", since = "1.0.0")]
pub mod consts {
use crate::sys::env::os;
use crate::sys::env_consts::os;

/// A string describing the architecture of the CPU that is currently in use.
/// An example value may be: `"x86"`, `"arm"` or `"riscv64"`.
Expand Down
Loading