Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2bae85e
Remove `derive(Copy)` on `ArrayWindows`
cuviper Jan 24, 2026
9052155
Manually `impl Clone for ArrayWindows`
cuviper Jan 24, 2026
08cd2ac
`impl FusedIterator for ArrayWindows`
cuviper Jan 24, 2026
8f7d556
`impl TrustedLen for ArrayWindows`
cuviper Jan 24, 2026
129d552
`impl TrustedRandomAccess for ArrayWindows`
cuviper Jan 24, 2026
1a240d6
expand `define_reify_functions!`
cyrgani Feb 5, 2026
749d62b
remove `Closure` generics
cyrgani Feb 5, 2026
1a03742
simplify some other generics
cyrgani Feb 5, 2026
18996c6
make `with_api!` take explicit type paths
cyrgani Feb 5, 2026
a6062a8
use `mem::conjure_zst` directly
cyrgani Feb 5, 2026
74d2616
deduplicate `Tag` enum
cyrgani Feb 6, 2026
d0b3a0b
Add some conversion trait impls
Jules-Bertholet Feb 3, 2026
d8ff397
check stalled coroutine obligations eagerly
adwinwhite Feb 8, 2026
f248395
bless tests
adwinwhite Feb 8, 2026
88c296a
std: introduce path normalize methods at top of std::path
xizheyin Feb 9, 2026
e04ae80
Rename `JobOwner` to `ActiveJobGuard`
Zalathar Feb 9, 2026
c475bda
Include `key_hash` in `ActiveJobGuard`
Zalathar Feb 9, 2026
2b22150
Port rustc_no_implicit_bounds attribute to parser.
Ozzy1423 Feb 4, 2026
43e5203
compiletest: `-Zunstable-options` for json targets
davidtwco Feb 6, 2026
1bc638b
Rollup merge of #151613 - cuviper:array-windows-parity, r=Amanieu
JonathanBrouwer Feb 9, 2026
6b259f5
Rollup merge of #152166 - cyrgani:questionable-pm-cleanups, r=petroch…
JonathanBrouwer Feb 9, 2026
2fdafa9
Rollup merge of #152236 - davidtwco:compiletest-destabilise-custom-ta…
JonathanBrouwer Feb 9, 2026
5e5525f
Rollup merge of #142957 - xizheyin:142931, r=tgross35
JonathanBrouwer Feb 9, 2026
a9a3687
Rollup merge of #145504 - Jules-Bertholet:more_conversion_trait_impls…
JonathanBrouwer Feb 9, 2026
548228b
Rollup merge of #152131 - Ozzy1423:attrs6, r=JonathanBrouwer
JonathanBrouwer Feb 9, 2026
3cd8a0b
Rollup merge of #152327 - adwinwhite:fix-non-defining-use-ices-ready,…
JonathanBrouwer Feb 9, 2026
5c7e935
Rollup merge of #152377 - Zalathar:active-job-guard, r=nnethercote
JonathanBrouwer Feb 9, 2026
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
9 changes: 9 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/crate_level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,12 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcPreserveUbChecksParser {
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks;
}

pub(crate) struct RustcNoImplicitBoundsParser;

impl<S: Stage> NoArgsAttributeParser<S> for RustcNoImplicitBoundsParser {
const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds;
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ attribute_parsers!(
Single<WithoutArgs<RustcMainParser>>,
Single<WithoutArgs<RustcNeverReturnsNullPointerParser>>,
Single<WithoutArgs<RustcNoImplicitAutorefsParser>>,
Single<WithoutArgs<RustcNoImplicitBoundsParser>>,
Single<WithoutArgs<RustcNonConstTraitMethodParser>>,
Single<WithoutArgs<RustcNounwindParser>>,
Single<WithoutArgs<RustcOffloadKernelParser>>,
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ fn mir_borrowck(
let (input_body, _) = tcx.mir_promoted(def);
debug!("run query mir_borrowck: {}", tcx.def_path_str(def));

// We should eagerly check stalled coroutine obligations from HIR typeck.
// Not doing so leads to silent normalization failures later, which will
// fail to register opaque types in the next solver.
tcx.check_coroutine_obligations(def)?;

let input_body: &Body<'_> = &input_body.borrow();
if let Some(guar) = input_body.tainted_by_errors {
debug!("Skipping borrowck because of tainted body");
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_no_implicit_autorefs]`
RustcNoImplicitAutorefs,

/// Represents `#[rustc_no_implicit_bounds]`
RustcNoImplicitBounds,

/// Represents `#[rustc_non_const_trait_method]`.
RustcNonConstTraitMethod,

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ impl AttributeKind {
RustcMustImplementOneOf { .. } => No,
RustcNeverReturnsNullPointer => Yes,
RustcNoImplicitAutorefs => Yes,
RustcNoImplicitBounds => No,
RustcNonConstTraitMethod => No, // should be reported via other queries like `constness`
RustcNounwind => No,
RustcObjcClass { .. } => No,
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::codes::*;
use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
use rustc_hir::PolyTraitRef;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
use rustc_hir::{PolyTraitRef, find_attr};
use rustc_middle::bug;
use rustc_middle::ty::{
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
TypeVisitor, Upcast,
};
use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
use rustc_span::{ErrorGuaranteed, Ident, Span, kw};
use rustc_trait_selection::traits;
use smallvec::SmallVec;
use tracing::{debug, instrument};
Expand Down Expand Up @@ -170,7 +171,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let tcx = self.tcx();

// Skip adding any default bounds if `#![rustc_no_implicit_bounds]`
if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) {
if find_attr!(tcx.get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNoImplicitBounds) {
return;
}

Expand Down Expand Up @@ -284,7 +285,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
context: ImpliedBoundsContext<'tcx>,
) -> bool {
let collected = collect_bounds(hir_bounds, context, trait_def_id);
!self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
!find_attr!(self.tcx().get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNoImplicitBounds)
&& !collected.any()
}

fn reject_duplicate_relaxed_bounds(&self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>) {
Expand Down
18 changes: 7 additions & 11 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1116,18 +1116,14 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
{
tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id);
}
if tcx.is_coroutine(def_id.to_def_id()) {
tcx.ensure_ok().mir_coroutine_witnesses(def_id);
let _ = tcx.ensure_ok().check_coroutine_obligations(
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
if tcx.is_coroutine(def_id.to_def_id())
&& (!tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()))
{
// Eagerly check the unsubstituted layout for cycles.
tcx.ensure_ok().layout_of(
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
.as_query_input(tcx.type_of(def_id).instantiate_identity()),
);
if !tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()) {
// Eagerly check the unsubstituted layout for cycles.
tcx.ensure_ok().layout_of(
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
.as_query_input(tcx.type_of(def_id).instantiate_identity()),
);
}
}
});
});
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/ty/context/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ pub struct ImplicitCtxt<'a, 'tcx> {
/// The current `TyCtxt`.
pub tcx: TyCtxt<'tcx>,

/// The current query job, if any. This is updated by `JobOwner::start` in
/// `ty::query::plumbing` when executing a query.
/// The current query job, if any.
pub query: Option<QueryJobId>,

/// Used to prevent queries from calling too deeply.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::RustcMir(_)
| AttributeKind::RustcNeverReturnsNullPointer
| AttributeKind::RustcNoImplicitAutorefs
| AttributeKind::RustcNoImplicitBounds
| AttributeKind::RustcNonConstTraitMethod
| AttributeKind::RustcNounwind
| AttributeKind::RustcObjcClass { .. }
Expand Down Expand Up @@ -413,7 +414,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
// crate-level attrs, are checked below
| sym::feature
| sym::register_tool
| sym::rustc_no_implicit_bounds
| sym::test_runner,
..
] => {}
Expand Down
40 changes: 23 additions & 17 deletions compiler/rustc_query_impl/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,18 @@ pub(crate) fn gather_active_jobs_inner<'tcx, K: Copy>(
Some(())
}

/// A type representing the responsibility to execute the job in the `job` field.
/// This will poison the relevant query if dropped.
struct JobOwner<'tcx, K>
/// Guard object representing the responsibility to execute a query job and
/// mark it as completed.
///
/// This will poison the relevant query key if it is dropped without calling
/// [`Self::complete`].
struct ActiveJobGuard<'tcx, K>
where
K: Eq + Hash + Copy,
{
state: &'tcx QueryState<'tcx, K>,
key: K,
key_hash: u64,
}

#[cold]
Expand Down Expand Up @@ -137,20 +141,19 @@ fn handle_cycle_error<'tcx, C: QueryCache, const FLAGS: QueryFlags>(
}
}

impl<'tcx, K> JobOwner<'tcx, K>
impl<'tcx, K> ActiveJobGuard<'tcx, K>
where
K: Eq + Hash + Copy,
{
/// Completes the query by updating the query cache with the `result`,
/// signals the waiter and forgets the JobOwner, so it won't poison the query
fn complete<C>(self, cache: &C, key_hash: u64, result: C::Value, dep_node_index: DepNodeIndex)
/// signals the waiter, and forgets the guard so it won't poison the query.
fn complete<C>(self, cache: &C, result: C::Value, dep_node_index: DepNodeIndex)
where
C: QueryCache<Key = K>,
{
let key = self.key;
let state = self.state;

// Forget ourself so our destructor won't poison the query
// Forget ourself so our destructor won't poison the query.
// (Extract fields by value first to make sure we don't leak anything.)
let Self { state, key, key_hash }: Self = self;
mem::forget(self);

// Mark as complete before we remove the job from the active state
Expand All @@ -174,19 +177,18 @@ where
}
}

impl<'tcx, K> Drop for JobOwner<'tcx, K>
impl<'tcx, K> Drop for ActiveJobGuard<'tcx, K>
where
K: Eq + Hash + Copy,
{
#[inline(never)]
#[cold]
fn drop(&mut self) {
// Poison the query so jobs waiting on it panic.
let state = self.state;
let Self { state, key, key_hash } = *self;
let job = {
let key_hash = sharded::make_hash(&self.key);
let mut shard = state.active.lock_shard_by_hash(key_hash);
match shard.find_entry(key_hash, equivalent_key(&self.key)) {
match shard.find_entry(key_hash, equivalent_key(&key)) {
Err(_) => panic!(),
Ok(occupied) => {
let ((key, value), vacant) = occupied.remove();
Expand Down Expand Up @@ -342,11 +344,13 @@ fn execute_job<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>(
id: QueryJobId,
dep_node: Option<DepNode>,
) -> (C::Value, Option<DepNodeIndex>) {
// Use `JobOwner` so the query will be poisoned if executing it panics.
let job_owner = JobOwner { state, key };
// Set up a guard object that will automatically poison the query if a
// panic occurs while executing the query (or any intermediate plumbing).
let job_guard = ActiveJobGuard { state, key, key_hash };

debug_assert_eq!(qcx.tcx.dep_graph.is_fully_enabled(), INCR);

// Delegate to another function to actually execute the query job.
let (result, dep_node_index) = if INCR {
execute_job_incr(query, qcx, qcx.tcx.dep_graph.data().unwrap(), key, dep_node, id)
} else {
Expand Down Expand Up @@ -388,7 +392,9 @@ fn execute_job<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>(
}
}
}
job_owner.complete(cache, key_hash, result, dep_node_index);

// Tell the guard to perform completion bookkeeping, and also to not poison the query.
job_guard.complete(cache, result, dep_node_index);

(result, Some(dep_node_index))
}
Expand Down
24 changes: 24 additions & 0 deletions library/core/src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,30 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {}
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Cell<U>> for Cell<T> {}

#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T, const N: usize> AsRef<[Cell<T>; N]> for Cell<[T; N]> {
#[inline]
fn as_ref(&self) -> &[Cell<T>; N] {
self.as_array_of_cells()
}
}

#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T, const N: usize> AsRef<[Cell<T>]> for Cell<[T; N]> {
#[inline]
fn as_ref(&self) -> &[Cell<T>] {
&*self.as_array_of_cells()
}
}

#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T> AsRef<[Cell<T>]> for Cell<[T]> {
#[inline]
fn as_ref(&self) -> &[Cell<T>] {
self.as_slice_of_cells()
}
}

impl<T> Cell<[T]> {
/// Returns a `&[Cell<T>]` from a `&Cell<[T]>`
///
Expand Down
50 changes: 50 additions & 0 deletions library/core/src/mem/maybe_uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1532,6 +1532,56 @@ impl<T, const N: usize> MaybeUninit<[T; N]> {
}
}

#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T, const N: usize> From<[MaybeUninit<T>; N]> for MaybeUninit<[T; N]> {
#[inline]
fn from(arr: [MaybeUninit<T>; N]) -> Self {
arr.transpose()
}
}

#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T, const N: usize> AsRef<[MaybeUninit<T>; N]> for MaybeUninit<[T; N]> {
#[inline]
fn as_ref(&self) -> &[MaybeUninit<T>; N] {
// SAFETY: T and MaybeUninit<T> have the same layout
unsafe { &*ptr::from_ref(self).cast() }
}
}

#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T, const N: usize> AsRef<[MaybeUninit<T>]> for MaybeUninit<[T; N]> {
#[inline]
fn as_ref(&self) -> &[MaybeUninit<T>] {
&*AsRef::<[MaybeUninit<T>; N]>::as_ref(self)
}
}

#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T, const N: usize> AsMut<[MaybeUninit<T>; N]> for MaybeUninit<[T; N]> {
#[inline]
fn as_mut(&mut self) -> &mut [MaybeUninit<T>; N] {
// SAFETY: T and MaybeUninit<T> have the same layout
unsafe { &mut *ptr::from_mut(self).cast() }
}
}

#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T, const N: usize> AsMut<[MaybeUninit<T>]> for MaybeUninit<[T; N]> {
#[inline]
fn as_mut(&mut self) -> &mut [MaybeUninit<T>] {
&mut *AsMut::<[MaybeUninit<T>; N]>::as_mut(self)
}
}

#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T, const N: usize> From<MaybeUninit<[T; N]>> for [MaybeUninit<T>; N] {
#[inline]
fn from(arr: MaybeUninit<[T; N]>) -> Self {
arr.transpose()
}
}

impl<T, const N: usize> [MaybeUninit<T>; N] {
/// Transposes a `[MaybeUninit<T>; N]` into a `MaybeUninit<[T; N]>`.
///
Expand Down
34 changes: 33 additions & 1 deletion library/core/src/slice/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2175,7 +2175,7 @@ unsafe impl<T> Sync for ChunksExactMut<'_, T> where T: Sync {}
///
/// [`array_windows`]: slice::array_windows
/// [slices]: slice
#[derive(Debug, Clone, Copy)]
#[derive(Debug)]
#[stable(feature = "array_windows", since = "1.94.0")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ArrayWindows<'a, T: 'a, const N: usize> {
Expand All @@ -2189,6 +2189,14 @@ impl<'a, T: 'a, const N: usize> ArrayWindows<'a, T, N> {
}
}

// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
#[stable(feature = "array_windows", since = "1.94.0")]
impl<T, const N: usize> Clone for ArrayWindows<'_, T, N> {
fn clone(&self) -> Self {
Self { v: self.v }
}
}

#[stable(feature = "array_windows", since = "1.94.0")]
impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> {
type Item = &'a [T; N];
Expand Down Expand Up @@ -2224,6 +2232,14 @@ impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> {
fn last(self) -> Option<Self::Item> {
self.v.last_chunk()
}

unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
// SAFETY: since the caller guarantees that `idx` is in bounds,
// which means that `idx` cannot overflow an `isize`, and the
// "slice" created by `cast_array` is a subslice of `self.v`
// thus is guaranteed to be valid for the lifetime `'a` of `self.v`.
unsafe { &*self.v.as_ptr().add(idx).cast_array() }
}
}

#[stable(feature = "array_windows", since = "1.94.0")]
Expand Down Expand Up @@ -2252,6 +2268,22 @@ impl<T, const N: usize> ExactSizeIterator for ArrayWindows<'_, T, N> {
}
}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T, const N: usize> TrustedLen for ArrayWindows<'_, T, N> {}

#[stable(feature = "array_windows", since = "1.94.0")]
impl<T, const N: usize> FusedIterator for ArrayWindows<'_, T, N> {}

#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl<T, const N: usize> TrustedRandomAccess for ArrayWindows<'_, T, N> {}

#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl<T, const N: usize> TrustedRandomAccessNoCoerce for ArrayWindows<'_, T, N> {
const MAY_HAVE_SIDE_EFFECT: bool = false;
}

/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
/// time), starting at the end of the slice.
///
Expand Down
Loading
Loading