Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 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
1485e78
Document fully-qualified syntax in `as`' keyword doc
fpdotmonkey Jun 18, 2025
a9ab29c
add mem::conjure_zst
Qelxiros Sep 12, 2025
55aeb17
Do not assert that a change in global cache only happens when concurrent
jackh726 Oct 2, 2025
c721fa2
interpret #[used] as #[used(compiler)] on illumos
iximeow Sep 28, 2025
12cfad9
update autodiff batching test
ZuseZ4 Oct 3, 2025
f837cfe
Rollup merge of #142670 - fpdotmonkey:doc/as-fully-qualified-syntax, …
matthiaskrgr Oct 4, 2025
47bd38c
Rollup merge of #145685 - Qelxiros:cell_get_cloned, r=programmerjake,…
matthiaskrgr Oct 4, 2025
dbc1e82
Rollup merge of #146330 - Marcondiro:unicode-17, r=Manishearth
matthiaskrgr Oct 4, 2025
baea20b
Rollup merge of #146451 - DimitriiTrater:atan2_correctness_docs, r=tg…
matthiaskrgr Oct 4, 2025
18388b8
Rollup merge of #146479 - Qelxiros:mem_conjure_zst, r=scottmcm,tgross35
matthiaskrgr Oct 4, 2025
3f7b8c5
Rollup merge of #147117 - iximeow:ixi/illumos-used-attr, r=Noratrieb
matthiaskrgr Oct 4, 2025
c389e2e
Rollup merge of #147190 - joboet:sys-net-cleanup, r=hkBst,tgross35
matthiaskrgr Oct 4, 2025
dade9fe
Rollup merge of #147251 - jackh726:global-cache-non-concurrent-change…
matthiaskrgr Oct 4, 2025
6c24eee
Rollup merge of #147280 - workingjubilee:you-can-put-your-gcc-in-my-l…
matthiaskrgr Oct 4, 2025
a84359c
Rollup merge of #147315 - ZuseZ4:fix-ad-batching-test, r=jieyouxu
matthiaskrgr 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
36 changes: 28 additions & 8 deletions compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for NoMangleParser {
pub(crate) struct UsedParser {
first_compiler: Option<Span>,
first_linker: Option<Span>,
first_default: Option<Span>,
}

// A custom `AttributeParser` is used rather than a Simple attribute parser because
Expand All @@ -382,7 +383,7 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
template!(Word, List: &["compiler", "linker"]),
|group: &mut Self, cx, args| {
let used_by = match args {
ArgParser::NoArgs => UsedBy::Linker,
ArgParser::NoArgs => UsedBy::Default,
ArgParser::List(list) => {
let Some(l) = list.single() else {
cx.expected_single_argument(list.span);
Expand Down Expand Up @@ -423,12 +424,29 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
ArgParser::NameValue(_) => return,
};

let attr_span = cx.attr_span;

// `#[used]` is interpreted as `#[used(linker)]` (though depending on target OS the
// circumstances are more complicated). While we're checking `used_by`, also report
// these cross-`UsedBy` duplicates to warn.
let target = match used_by {
UsedBy::Compiler => &mut group.first_compiler,
UsedBy::Linker => &mut group.first_linker,
UsedBy::Linker => {
if let Some(prev) = group.first_default {
cx.warn_unused_duplicate(prev, attr_span);
return;
}
&mut group.first_linker
}
UsedBy::Default => {
if let Some(prev) = group.first_linker {
cx.warn_unused_duplicate(prev, attr_span);
return;
}
&mut group.first_default
}
};

let attr_span = cx.attr_span;
if let Some(prev) = *target {
cx.warn_unused_duplicate(prev, attr_span);
} else {
Expand All @@ -440,11 +458,13 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
AllowedTargets::AllowList(&[Allow(Target::Static), Warn(Target::MacroCall)]);

fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
// Ratcheting behaviour, if both `linker` and `compiler` are specified, use `linker`
Some(match (self.first_compiler, self.first_linker) {
(_, Some(span)) => AttributeKind::Used { used_by: UsedBy::Linker, span },
(Some(span), _) => AttributeKind::Used { used_by: UsedBy::Compiler, span },
(None, None) => return None,
// If a specific form of `used` is specified, it takes precedence over generic `#[used]`.
// If both `linker` and `compiler` are specified, use `linker`.
Some(match (self.first_compiler, self.first_linker, self.first_default) {
(_, Some(span), _) => AttributeKind::Used { used_by: UsedBy::Linker, span },
(Some(span), _, _) => AttributeKind::Used { used_by: UsedBy::Compiler, span },
(_, _, Some(span)) => AttributeKind::Used { used_by: UsedBy::Default, span },
(None, None, None) => return None,
})
}
}
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,19 @@ fn process_builtin_attrs(
AttributeKind::Used { used_by, .. } => match used_by {
UsedBy::Compiler => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_COMPILER,
UsedBy::Linker => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER,
UsedBy::Default => {
let used_form = if tcx.sess.target.os == "illumos" {
// illumos' `ld` doesn't support a section header that would represent
// `#[used(linker)]`, see
// https://github.com/rust-lang/rust/issues/146169. For that target,
// downgrade as if `#[used(compiler)]` was requested and hope for the
// best.
CodegenFnAttrFlags::USED_COMPILER
} else {
CodegenFnAttrFlags::USED_LINKER
};
codegen_fn_attrs.flags |= used_form;
}
},
AttributeKind::FfiConst(_) => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,13 @@ impl Deprecation {
}

/// There are three valid forms of the attribute:
/// `#[used]`, which is semantically equivalent to `#[used(linker)]` except that the latter is currently unstable.
/// `#[used]`, which is equivalent to `#[used(linker)]` on targets that support it, but `#[used(compiler)]` if not.
/// `#[used(compiler)]`
/// `#[used(linker)]`
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic, PrintAttribute)]
pub enum UsedBy {
Default,
Compiler,
Linker,
}
Expand Down
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
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
Loading
Loading