Rollup merge of #155957 - oli-obk:const-closure-std, r=jhpratt

Revert const hacks and use const closures in std

This revealed some smaller bugs in stability checking that I fixed where needed:

* const closures use the const stability of their parent
* trait method default bodies use the const stability of their trait

Otherwise trivial reverts of the const hacks that were added

fixes rust-lang/rust#155781
This commit is contained in:
Jonathan Brouwer
2026-05-05 14:25:25 +02:00
committed by GitHub
8 changed files with 30 additions and 63 deletions
+2 -1
View File
@@ -54,10 +54,11 @@ fn inherit_const_stability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
match def_kind {
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst { .. } => {
match tcx.def_kind(tcx.local_parent(def_id)) {
DefKind::Impl { .. } => true,
DefKind::Trait | DefKind::Impl { .. } => true,
_ => false,
}
}
DefKind::Closure => true,
_ => false,
}
}
+2
View File
@@ -108,6 +108,7 @@
#![feature(const_heap)]
#![feature(const_index)]
#![feature(const_option_ops)]
#![feature(const_result_trait_fn)]
#![feature(const_try)]
#![feature(copied_into_inner)]
#![feature(core_intrinsics)]
@@ -173,6 +174,7 @@
#![feature(allocator_internals)]
#![feature(allow_internal_unstable)]
#![feature(cfg_sanitize)]
#![feature(const_closures)]
#![feature(const_precise_live_drops)]
#![feature(const_trait_impl)]
#![feature(coroutine_trait)]
+1 -5
View File
@@ -898,9 +898,5 @@ const fn layout_array(cap: usize, elem_layout: Layout) -> Result<Layout, TryRese
// which lets us use the much-simpler `repeat_packed`.
debug_assert!(elem_layout.size() == elem_layout.pad_to_align().size());
// FIXME(const-hack) return to using `map` and `map_err` once `const_closures` is implemented
match elem_layout.repeat_packed(cap) {
Ok(layout) => Ok(layout),
Err(_) => Err(CapacityOverflow.into()),
}
elem_layout.repeat_packed(cap).map_err(const |_| CapacityOverflow.into())
}
+2
View File
@@ -23,6 +23,7 @@
#![feature(const_destruct)]
#![feature(const_heap)]
#![feature(const_option_ops)]
#![feature(const_result_trait_fn)]
#![feature(const_try)]
#![feature(copied_into_inner)]
#![feature(core_intrinsics)]
@@ -54,6 +55,7 @@
//
// Language features:
// tidy-alphabetical-start
#![feature(const_closures)]
#![feature(const_trait_impl)]
#![feature(dropck_eyepatch)]
#![feature(min_specialization)]
+4 -6
View File
@@ -226,13 +226,11 @@ pub const trait Iterator {
Self: Sized + [const] Destruct,
Self::Item: [const] Destruct,
{
// FIXME(const-hack): revert this to a const closure
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
self.fold(
0,
#[rustc_inherit_overflow_checks]
const fn plus_one<T: [const] Destruct>(accum: usize, _elem: T) -> usize {
accum + 1
}
self.fold(0, plus_one)
const |accum, _elem| accum + 1,
)
}
/// Consumes the iterator, returning the last element.
+1
View File
@@ -125,6 +125,7 @@
#![feature(cfg_target_has_atomic)]
#![feature(cfg_target_has_atomic_equal_alignment)]
#![feature(cfg_ub_checks)]
#![feature(const_closures)]
#![feature(const_precise_live_drops)]
#![feature(const_trait_impl)]
#![feature(decl_macro)]
+7 -23
View File
@@ -1,4 +1,4 @@
use crate::marker::{Destruct, PhantomData};
use crate::marker::Destruct;
use crate::ops::ControlFlow;
/// The `?` operator and `try {}` blocks.
@@ -398,25 +398,6 @@ pub(crate) type ChangeOutputType<T: Try<Residual: Residual<V>>, V> =
/// Not currently planned to be exposed publicly, so just `pub(crate)`.
#[repr(transparent)]
pub(crate) struct NeverShortCircuit<T>(pub T);
// FIXME(const-hack): replace with `|a| NeverShortCircuit(f(a))` when const closures added.
pub(crate) struct Wrapped<T, A, F: FnMut(A) -> T> {
f: F,
p: PhantomData<(T, A)>,
}
#[rustc_const_unstable(feature = "const_never_short_circuit", issue = "none")]
impl<T, A, F: [const] FnMut(A) -> T + [const] Destruct> const FnOnce<(A,)> for Wrapped<T, A, F> {
type Output = NeverShortCircuit<T>;
extern "rust-call" fn call_once(mut self, args: (A,)) -> Self::Output {
self.call_mut(args)
}
}
#[rustc_const_unstable(feature = "const_never_short_circuit", issue = "none")]
impl<T, A, F: [const] FnMut(A) -> T> const FnMut<(A,)> for Wrapped<T, A, F> {
extern "rust-call" fn call_mut(&mut self, (args,): (A,)) -> Self::Output {
NeverShortCircuit((self.f)(args))
}
}
impl<T> NeverShortCircuit<T> {
/// Wraps a unary function to produce one that wraps the output into a `NeverShortCircuit`.
@@ -424,11 +405,14 @@ impl<T> NeverShortCircuit<T> {
/// This is useful for implementing infallible functions in terms of the `try_` ones,
/// without accidentally capturing extra generic parameters in a closure.
#[inline]
pub(crate) const fn wrap_mut_1<A, F>(f: F) -> Wrapped<T, A, F>
#[rustc_const_unstable(feature = "const_array", issue = "147606")]
pub(crate) const fn wrap_mut_1<A, F>(
mut f: F,
) -> impl [const] FnMut(A) -> Self + [const] Destruct
where
F: [const] FnMut(A) -> T,
F: [const] FnMut(A) -> T + [const] Destruct,
{
Wrapped { f, p: PhantomData }
const move |a| NeverShortCircuit(f(a))
}
#[inline]
+6 -23
View File
@@ -3,7 +3,6 @@
use super::{from_raw_parts, memchr};
use crate::ascii;
use crate::cmp::{self, BytewiseEq, Ordering};
use crate::convert::Infallible;
use crate::intrinsics::compare_bytes;
use crate::marker::Destruct;
use crate::mem::SizedTypeProperties;
@@ -182,20 +181,12 @@ type AlwaysBreak<B> = ControlFlow<B, crate::convert::Infallible>;
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: [const] PartialOrd> const SlicePartialOrd for A {
default fn partial_compare(left: &[A], right: &[A]) -> Option<Ordering> {
// FIXME(const-hack): revert this to a const closure once possible
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
const fn elem_chain<A: [const] PartialOrd>(a: &A, b: &A) -> ControlFlow<Option<Ordering>> {
match PartialOrd::partial_cmp(a, b) {
let elem_chain = const |a, b| match PartialOrd::partial_cmp(a, b) {
Some(Ordering::Equal) => ControlFlow::Continue(()),
non_eq => ControlFlow::Break(non_eq),
}
}
};
// FIXME(const-hack): revert this to a const closure once possible
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
const fn len_chain(a: &usize, b: &usize) -> ControlFlow<Option<Ordering>, Infallible> {
ControlFlow::Break(usize::partial_cmp(a, b))
}
let len_chain = const |a: &_, b: &_| ControlFlow::Break(usize::partial_cmp(a, b));
let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
b
@@ -293,20 +284,12 @@ const trait SliceOrd: Sized {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: [const] Ord> const SliceOrd for A {
default fn compare(left: &[Self], right: &[Self]) -> Ordering {
// FIXME(const-hack): revert this to a const closure once possible
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
const fn elem_chain<A: [const] Ord>(a: &A, b: &A) -> ControlFlow<Ordering> {
match Ord::cmp(a, b) {
let elem_chain = const |a, b| match Ord::cmp(a, b) {
Ordering::Equal => ControlFlow::Continue(()),
non_eq => ControlFlow::Break(non_eq),
}
}
};
// FIXME(const-hack): revert this to a const closure once possible
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
const fn len_chain(a: &usize, b: &usize) -> ControlFlow<Ordering, Infallible> {
ControlFlow::Break(usize::cmp(a, b))
}
let len_chain = const |a: &_, b: &_| ControlFlow::Break(usize::cmp(a, b));
let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
b