Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
400e687
Bump unicode_data to version 17.0.0
Marcondiro Sep 8, 2025
83a99aa
Bump unicode printable to version 17.0.0
Marcondiro Sep 9, 2025
d834935
Fix atan2 inaccuracy in documentation
DimitriiTrater Sep 11, 2025
d615d2f
std: call WinSock cleanup function directly instead of through its re…
joboet Sep 30, 2025
eba1416
std: improve internal socket functions
joboet Sep 30, 2025
aa1263e
std: add missing unsafe blocks
joboet Sep 30, 2025
3534594
std: merge address family computation
joboet Sep 30, 2025
08b4641
add CloneFromCell and Cell::get_cloned
Qelxiros Aug 20, 2025
99550fb
Return to needs-llvm-components being info-only
workingjubilee Oct 2, 2025
181b302
Move `DirectiveLine` into its own submodule
Zalathar Oct 3, 2025
c368f9a
Allow easy extraction of name/value from a `DirectiveLine`
Zalathar Oct 2, 2025
e73c221
Use new `DirectiveLine` features in directive parsing
Zalathar Oct 2, 2025
1485e78
Document fully-qualified syntax in `as`' keyword doc
fpdotmonkey Jun 18, 2025
a9ab29c
add mem::conjure_zst
Qelxiros Sep 12, 2025
fd96a78
Add documentation about unwinding to wasm targets
alexcrichton Oct 3, 2025
55aeb17
Do not assert that a change in global cache only happens when concurrent
jackh726 Oct 2, 2025
12cfad9
update autodiff batching test
ZuseZ4 Oct 3, 2025
422b914
Fix top level ui tests check in tidy
chenyukang Oct 4, 2025
958d9bb
Avoid to suggest pattern match on the similarly named in fn signature
chenyukang Oct 4, 2025
8ed8815
Rollup merge of #142670 - fpdotmonkey:doc/as-fully-qualified-syntax, …
Zalathar Oct 4, 2025
8d8e743
Rollup merge of #145685 - Qelxiros:cell_get_cloned, r=programmerjake,…
Zalathar Oct 4, 2025
79e39df
Rollup merge of #146330 - Marcondiro:unicode-17, r=Manishearth
Zalathar Oct 4, 2025
4d52fa8
Rollup merge of #146451 - DimitriiTrater:atan2_correctness_docs, r=tg…
Zalathar Oct 4, 2025
ecbfb6c
Rollup merge of #146479 - Qelxiros:mem_conjure_zst, r=scottmcm,tgross35
Zalathar Oct 4, 2025
c29e8cf
Rollup merge of #147190 - joboet:sys-net-cleanup, r=hkBst,tgross35
Zalathar Oct 4, 2025
8f6fb9d
Rollup merge of #147251 - jackh726:global-cache-non-concurrent-change…
Zalathar Oct 4, 2025
cb57183
Rollup merge of #147280 - workingjubilee:you-can-put-your-gcc-in-my-l…
Zalathar Oct 4, 2025
48ad360
Rollup merge of #147288 - Zalathar:directive, r=jieyouxu
Zalathar Oct 4, 2025
a7cc164
Rollup merge of #147309 - alexcrichton:wasm-unwinding-docs, r=jieyouxu
Zalathar Oct 4, 2025
5c62d05
Rollup merge of #147315 - ZuseZ4:fix-ad-batching-test, r=jieyouxu
Zalathar Oct 4, 2025
636a744
Rollup merge of #147320 - chenyukang:yukang-fix-147303-fn-arg, r=jiey…
Zalathar Oct 4, 2025
3118ab9
Rollup merge of #147323 - chenyukang:yukang-fix-tidy-check, r=jieyouxu
Zalathar Oct 4, 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
5 changes: 3 additions & 2 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
from_entry(entry)
}

fn evaluation_is_concurrent(&self) -> bool {
self.sess.threads() > 1
fn assert_evaluation_is_concurrent(&self) {
// Turns out, the assumption for this function isn't perfect.
// See trait-system-refactor-initiative#234.
}

fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, t: T) -> T {
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_passes/src/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1691,7 +1691,10 @@ impl<'tcx> Liveness<'_, 'tcx> {
if ln == self.exit_ln { false } else { self.assigned_on_exit(ln, var) };

let mut typo = None;
for (hir_id, _, span) in &hir_ids_and_spans {
let filtered_hir_ids_and_spans = hir_ids_and_spans.iter().filter(|(hir_id, ..)| {
!matches!(self.ir.tcx.parent_hir_node(*hir_id), hir::Node::Param(_))
});
for (hir_id, _, span) in filtered_hir_ids_and_spans.clone() {
let ty = self.typeck_results.node_type(*hir_id);
if let ty::Adt(adt, _) = ty.peel_refs().kind() {
let name = Symbol::intern(&name);
Expand All @@ -1717,7 +1720,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
}
}
if typo.is_none() {
for (hir_id, _, span) in &hir_ids_and_spans {
for (hir_id, _, span) in filtered_hir_ids_and_spans {
let ty = self.typeck_results.node_type(*hir_id);
// Look for consts of the same type with similar names as well, not just unit
// structs and variants.
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_type_ir/src/interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ pub trait Interner:
from_entry: impl FnOnce(&CanonicalParamEnvCacheEntry<Self>) -> R,
) -> R;

fn evaluation_is_concurrent(&self) -> bool;
/// Useful for testing. If a cache entry is replaced, this should
/// (in theory) only happen when concurrent.
fn assert_evaluation_is_concurrent(&self);

fn expand_abstract_consts<T: TypeFoldable<Self>>(self, t: T) -> T;

Expand Down Expand Up @@ -567,7 +569,7 @@ impl<I: Interner> search_graph::Cx for I {
fn with_global_cache<R>(self, f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R) -> R {
I::with_global_cache(self, f)
}
fn evaluation_is_concurrent(&self) -> bool {
self.evaluation_is_concurrent()
fn assert_evaluation_is_concurrent(&self) {
self.assert_evaluation_is_concurrent()
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_type_ir/src/search_graph/global_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ impl<X: Cx> GlobalCache<X> {
let with_overflow = WithOverflow { nested_goals, result };
let prev = entry.with_overflow.insert(required_depth, with_overflow);
if let Some(prev) = &prev {
assert!(cx.evaluation_is_concurrent());
cx.assert_evaluation_is_concurrent();
assert_eq!(cx.get_tracked(&prev.result), evaluation_result.result);
}
} else {
let prev = entry.success.replace(Success { required_depth, nested_goals, result });
if let Some(prev) = &prev {
assert!(cx.evaluation_is_concurrent());
cx.assert_evaluation_is_concurrent();
assert_eq!(cx.get_tracked(&prev.result), evaluation_result.result);
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_type_ir/src/search_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub trait Cx: Copy {

fn with_global_cache<R>(self, f: impl FnOnce(&mut GlobalCache<Self>) -> R) -> R;

fn evaluation_is_concurrent(&self) -> bool;
fn assert_evaluation_is_concurrent(&self);
}

pub trait Delegate: Sized {
Expand Down
1 change: 1 addition & 0 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
#![feature(bstr)]
#![feature(bstr_internals)]
#![feature(cast_maybe_uninit)]
#![feature(cell_get_cloned)]
#![feature(char_internals)]
#![feature(char_max_len)]
#![feature(clone_to_uninit)]
Expand Down
10 changes: 9 additions & 1 deletion library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@
#![stable(feature = "rust1", since = "1.0.0")]

use core::any::Any;
use core::cell::Cell;
use core::cell::{Cell, CloneFromCell};
#[cfg(not(no_global_oom_handling))]
use core::clone::CloneToUninit;
use core::clone::UseCloned;
Expand Down Expand Up @@ -340,6 +340,10 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Rc<U, A>> for
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T> {}

// SAFETY: `Rc::clone` doesn't access any `Cell`s which could contain the `Rc` being cloned.
#[unstable(feature = "cell_get_cloned", issue = "145329")]
unsafe impl<T: ?Sized> CloneFromCell for Rc<T> {}

impl<T: ?Sized> Rc<T> {
#[inline]
unsafe fn from_inner(ptr: NonNull<RcInner<T>>) -> Self {
Expand Down Expand Up @@ -3013,6 +3017,10 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Weak<U, A>> f
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}

// SAFETY: `Weak::clone` doesn't access any `Cell`s which could contain the `Weak` being cloned.
#[unstable(feature = "cell_get_cloned", issue = "145329")]
unsafe impl<T: ?Sized> CloneFromCell for Weak<T> {}

impl<T> Weak<T> {
/// Constructs a new `Weak<T>`, without allocating any memory.
/// Calling [`upgrade`] on the return value always gives [`None`].
Expand Down
9 changes: 9 additions & 0 deletions library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//! `#[cfg(target_has_atomic = "ptr")]`.

use core::any::Any;
use core::cell::CloneFromCell;
#[cfg(not(no_global_oom_handling))]
use core::clone::CloneToUninit;
use core::clone::UseCloned;
Expand Down Expand Up @@ -281,6 +282,10 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Arc<U, A>> fo
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Arc<U>> for Arc<T> {}

// SAFETY: `Arc::clone` doesn't access any `Cell`s which could contain the `Arc` being cloned.
#[unstable(feature = "cell_get_cloned", issue = "145329")]
unsafe impl<T: ?Sized> CloneFromCell for Arc<T> {}

impl<T: ?Sized> Arc<T> {
unsafe fn from_inner(ptr: NonNull<ArcInner<T>>) -> Self {
unsafe { Self::from_inner_in(ptr, Global) }
Expand Down Expand Up @@ -356,6 +361,10 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Weak<U, A>> f
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}

// SAFETY: `Weak::clone` doesn't access any `Cell`s which could contain the `Weak` being cloned.
#[unstable(feature = "cell_get_cloned", issue = "145329")]
unsafe impl<T: ?Sized> CloneFromCell for Weak<T> {}

#[stable(feature = "arc_weak", since = "1.4.0")]
impl<T: ?Sized, A: Allocator> fmt::Debug for Weak<T, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down
92 changes: 90 additions & 2 deletions library/core/src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,12 @@
use crate::cmp::Ordering;
use crate::fmt::{self, Debug, Display};
use crate::marker::{PhantomData, Unsize};
use crate::mem;
use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn};
use crate::mem::{self, ManuallyDrop};
use crate::ops::{self, CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn};
use crate::panic::const_panic;
use crate::pin::PinCoerceUnsized;
use crate::ptr::{self, NonNull};
use crate::range;

mod lazy;
mod once;
Expand Down Expand Up @@ -713,6 +714,93 @@ impl<T, const N: usize> Cell<[T; N]> {
}
}

/// Types for which cloning `Cell<Self>` is sound.
///
/// # Safety
///
/// Implementing this trait for a type is sound if and only if the following code is sound for T =
/// that type.
///
/// ```
/// #![feature(cell_get_cloned)]
/// # use std::cell::{CloneFromCell, Cell};
/// fn clone_from_cell<T: CloneFromCell>(cell: &Cell<T>) -> T {
/// unsafe { T::clone(&*cell.as_ptr()) }
/// }
/// ```
///
/// Importantly, you can't just implement `CloneFromCell` for any arbitrary `Copy` type, e.g. the
/// following is unsound:
///
/// ```rust
/// #![feature(cell_get_cloned)]
/// # use std::cell::Cell;
///
/// #[derive(Copy, Debug)]
/// pub struct Bad<'a>(Option<&'a Cell<Bad<'a>>>, u8);
///
/// impl Clone for Bad<'_> {
/// fn clone(&self) -> Self {
/// let a: &u8 = &self.1;
/// // when self.0 points to self, we write to self.1 while we have a live `&u8` pointing to
/// // it -- this is UB
/// self.0.unwrap().set(Self(None, 1));
/// dbg!((a, self));
/// Self(None, 0)
/// }
/// }
///
/// // this is not sound
/// // unsafe impl CloneFromCell for Bad<'_> {}
/// ```
#[unstable(feature = "cell_get_cloned", issue = "145329")]
// Allow potential overlapping implementations in user code
#[marker]
pub unsafe trait CloneFromCell: Clone {}

// `CloneFromCell` can be implemented for types that don't have indirection and which don't access
// `Cell`s in their `Clone` implementation. A commonly-used subset is covered here.
#[unstable(feature = "cell_get_cloned", issue = "145329")]
unsafe impl<T: CloneFromCell, const N: usize> CloneFromCell for [T; N] {}
#[unstable(feature = "cell_get_cloned", issue = "145329")]
unsafe impl<T: CloneFromCell> CloneFromCell for Option<T> {}
#[unstable(feature = "cell_get_cloned", issue = "145329")]
unsafe impl<T: CloneFromCell, E: CloneFromCell> CloneFromCell for Result<T, E> {}
#[unstable(feature = "cell_get_cloned", issue = "145329")]
unsafe impl<T: ?Sized> CloneFromCell for PhantomData<T> {}
#[unstable(feature = "cell_get_cloned", issue = "145329")]
unsafe impl<T: CloneFromCell> CloneFromCell for ManuallyDrop<T> {}
#[unstable(feature = "cell_get_cloned", issue = "145329")]
unsafe impl<T: CloneFromCell> CloneFromCell for ops::Range<T> {}
#[unstable(feature = "cell_get_cloned", issue = "145329")]
unsafe impl<T: CloneFromCell> CloneFromCell for range::Range<T> {}

#[unstable(feature = "cell_get_cloned", issue = "145329")]
impl<T: CloneFromCell> Cell<T> {
/// Get a clone of the `Cell` that contains a copy of the original value.
///
/// This allows a cheaply `Clone`-able type like an `Rc` to be stored in a `Cell`, exposing the
/// cheaper `clone()` method.
///
/// # Examples
///
/// ```
/// #![feature(cell_get_cloned)]
///
/// use core::cell::Cell;
/// use std::rc::Rc;
///
/// let rc = Rc::new(1usize);
/// let c1 = Cell::new(rc);
/// let c2 = c1.get_cloned();
/// assert_eq!(*c2.into_inner(), 1);
/// ```
pub fn get_cloned(&self) -> Self {
// SAFETY: T is CloneFromCell, which guarantees that this is sound.
Cell::new(T::clone(unsafe { &*self.as_ptr() }))
}
}

/// A mutable memory location with dynamically checked borrow rules
///
/// See the [module-level documentation](self) for more.
Expand Down
58 changes: 58 additions & 0 deletions library/core/src/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

use crate::alloc::Layout;
use crate::marker::DiscriminantKind;
use crate::panic::const_assert;
use crate::{clone, cmp, fmt, hash, intrinsics, ptr};

mod manually_drop;
Expand Down Expand Up @@ -1407,3 +1408,60 @@ pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) {
// The `{}` is for better error messages
{builtin # offset_of($Container, $($fields)+)}
}

/// Create a fresh instance of the inhabited ZST type `T`.
///
/// Prefer this to [`zeroed`] or [`uninitialized`] or [`transmute_copy`]
/// in places where you know that `T` is zero-sized, but don't have a bound
/// (such as [`Default`]) that would allow you to instantiate it using safe code.
///
/// If you're not sure whether `T` is an inhabited ZST, then you should be
/// using [`MaybeUninit`], not this function.
///
/// # Panics
///
/// If `size_of::<T>() != 0`.
///
/// # Safety
///
/// - `T` must be *[inhabited]*, i.e. possible to construct. This means that types
/// like zero-variant enums and [`!`] are unsound to conjure.
/// - You must use the value only in ways which do not violate any *safety*
/// invariants of the type.
///
/// While it's easy to create a *valid* instance of an inhabited ZST, since having
/// no bits in its representation means there's only one possible value, that
/// doesn't mean that it's always *sound* to do so.
///
/// For example, a library could design zero-sized tokens that are `!Default + !Clone`, limiting
/// their creation to functions that initialize some state or establish a scope. Conjuring such a
/// token could break invariants and lead to unsoundness.
///
/// # Examples
///
/// ```
/// #![feature(mem_conjure_zst)]
/// use std::mem::conjure_zst;
///
/// assert_eq!(unsafe { conjure_zst::<()>() }, ());
/// assert_eq!(unsafe { conjure_zst::<[i32; 0]>() }, []);
/// ```
///
/// [inhabited]: https://doc.rust-lang.org/reference/glossary.html#inhabited
#[unstable(feature = "mem_conjure_zst", issue = "95383")]
pub const unsafe fn conjure_zst<T>() -> T {
const_assert!(
size_of::<T>() == 0,
"mem::conjure_zst invoked on a nonzero-sized type",
"mem::conjure_zst invoked on type {t}, which is not zero-sized",
t: &str = stringify!(T)
);

// SAFETY: because the caller must guarantee that it's inhabited and zero-sized,
// there's nothing in the representation that needs to be set.
// `assume_init` calls `assert_inhabited`, so we don't need to here.
unsafe {
#[allow(clippy::uninit_assumed_init)]
MaybeUninit::uninit().assume_init()
}
}
10 changes: 10 additions & 0 deletions library/core/src/tuple.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// See core/src/primitive_docs.rs for documentation.

use crate::cell::CloneFromCell;
use crate::cmp::Ordering::{self, *};
use crate::marker::{ConstParamTy_, StructuralPartialEq};
use crate::ops::ControlFlow::{self, Break, Continue};
Expand Down Expand Up @@ -155,6 +156,15 @@ macro_rules! tuple_impls {
}
}
}

maybe_tuple_doc! {
$($T)+ @
// SAFETY: tuples introduce no additional indirection, so they can be copied whenever T
// can.
#[unstable(feature = "cell_get_cloned", issue = "145329")]
unsafe impl<$($T: CloneFromCell),+> CloneFromCell for ($($T,)+)
{}
}
}
}

Expand Down
Loading
Loading