Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 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
4735c21
Fix diagnostics str::replace comma to bar
A4-Tacks Jul 2, 2025
a08228d
bless tests
karolzwolak Sep 27, 2025
934ad74
regression test
karolzwolak Oct 1, 2025
08b4641
add CloneFromCell and Cell::get_cloned
Qelxiros Aug 20, 2025
5a8f963
fix wording; we're replacing coma with a bar
karolzwolak Oct 2, 2025
d1d7b94
bring back plural 'alternatives' in suggestion message
karolzwolak Oct 2, 2025
fab9906
test: Add regression test for ICE when projecting associated types th…
reddevilmidzy Oct 2, 2025
99550fb
Return to needs-llvm-components being info-only
workingjubilee Oct 2, 2025
a5c9030
Extract common logic for iterating over features
fee1-dead Oct 2, 2025
3d5f54a
Respect `-Z` unstable options in `rustdoc --test`
Urgau Oct 3, 2025
1485e78
Document fully-qualified syntax in `as`' keyword doc
fpdotmonkey Jun 18, 2025
e914a1a
Respect `--error-format` in `rustdoc --test`
Urgau Oct 3, 2025
c1443e2
Add regression test for `-Zcrate-attr` in `rustdoc --test`
Urgau Oct 3, 2025
3f9c493
Add xtensa arch to object file creation
MabezDev Oct 3, 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
76caf12
Rollup merge of #142670 - fpdotmonkey:doc/as-fully-qualified-syntax, …
Zalathar Oct 4, 2025
d507f9e
Rollup merge of #145685 - Qelxiros:cell_get_cloned, r=programmerjake,…
Zalathar Oct 4, 2025
ba42eb6
Rollup merge of #146330 - Marcondiro:unicode-17, r=Manishearth
Zalathar Oct 4, 2025
b3c9cd3
Rollup merge of #146451 - DimitriiTrater:atan2_correctness_docs, r=tg…
Zalathar Oct 4, 2025
08e846d
Rollup merge of #146479 - Qelxiros:mem_conjure_zst, r=scottmcm,tgross35
Zalathar Oct 4, 2025
9de7576
Rollup merge of #147190 - joboet:sys-net-cleanup, r=hkBst,tgross35
Zalathar Oct 4, 2025
329692e
Rollup merge of #147245 - karolzwolak:only-replace-intended-bar-not-a…
Zalathar Oct 4, 2025
ce8bcbe
Rollup merge of #147251 - jackh726:global-cache-non-concurrent-change…
Zalathar Oct 4, 2025
088c176
Rollup merge of #147269 - reddevilmidzy:ice-fix, r=petrochenkov
Zalathar Oct 4, 2025
8641f87
Rollup merge of #147277 - fee1-dead-contrib:featiter, r=Zalathar
Zalathar Oct 4, 2025
1706a32
Rollup merge of #147280 - workingjubilee:you-can-put-your-gcc-in-my-l…
Zalathar Oct 4, 2025
ed7257b
Rollup merge of #147292 - Urgau:rustdoc-test-unstable_opts, r=fmease
Zalathar Oct 4, 2025
5ac4386
Rollup merge of #147300 - esp-rs:xtensa-meta, r=saethlin
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
6 changes: 1 addition & 5 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,11 +622,7 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
}

fn check_incompatible_features(sess: &Session, features: &Features) {
let enabled_lang_features =
features.enabled_lang_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));
let enabled_lib_features =
features.enabled_lib_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));
let enabled_features = enabled_lang_features.chain(enabled_lib_features);
let enabled_features = features.enabled_features_iter_stable_order();

for (f1, f2) in rustc_feature::INCOMPATIBLE_FEATURES
.iter()
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ impl Features {
&self.enabled_features
}

/// Returns a iterator of enabled features in stable order.
pub fn enabled_features_iter_stable_order(
&self,
) -> impl Iterator<Item = (Symbol, Span)> + Clone {
self.enabled_lang_features
.iter()
.map(|feat| (feat.gate_name, feat.attr_sp))
.chain(self.enabled_lib_features.iter().map(|feat| (feat.gate_name, feat.attr_sp)))
}

/// Is the given feature enabled (via `#[feature(...)]`)?
pub fn enabled(&self, feature: Symbol) -> bool {
self.enabled_features.contains(&feature)
Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2331,13 +2331,9 @@ declare_lint_pass!(
impl EarlyLintPass for IncompleteInternalFeatures {
fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
let features = cx.builder.features();
let lang_features =
features.enabled_lang_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));
let lib_features =
features.enabled_lib_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));

lang_features
.chain(lib_features)
features
.enabled_features_iter_stable_order()
.filter(|(name, _)| features.incomplete(*name) || features.internal(*name))
.for_each(|(name, span)| {
if features.incomplete(name) {
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
34 changes: 16 additions & 18 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2939,26 +2939,24 @@ impl<'a> Parser<'a> {
}
let seq_span = lo.to(self.prev_token.span);
let mut err = self.dcx().struct_span_err(comma_span, "unexpected `,` in pattern");
if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
err.multipart_suggestion(
format!(
"try adding parentheses to match on a tuple{}",
if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
),
vec![
(seq_span.shrink_to_lo(), "(".to_string()),
(seq_span.shrink_to_hi(), ")".to_string()),
],
err.multipart_suggestion(
format!(
"try adding parentheses to match on a tuple{}",
if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
),
vec![
(seq_span.shrink_to_lo(), "(".to_string()),
(seq_span.shrink_to_hi(), ")".to_string()),
],
Applicability::MachineApplicable,
);
if let CommaRecoveryMode::EitherTupleOrPipe = rt {
err.span_suggestion(
comma_span,
"...or a vertical bar to match on alternatives",
" |",
Applicability::MachineApplicable,
);
if let CommaRecoveryMode::EitherTupleOrPipe = rt {
err.span_suggestion(
seq_span,
"...or a vertical bar to match on multiple alternatives",
seq_snippet.replace(',', " |"),
Applicability::MachineApplicable,
);
}
}
Err(err)
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3182,6 +3182,7 @@ impl Target {
"avr" => (Architecture::Avr, None),
"msp430" => (Architecture::Msp430, None),
"hexagon" => (Architecture::Hexagon, None),
"xtensa" => (Architecture::Xtensa, None),
"bpf" => (Architecture::Bpf, None),
"loongarch32" => (Architecture::LoongArch32, None),
"loongarch64" => (Architecture::LoongArch64, None),
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