Rollup merge of #139858 - oli-obk:new-const-traits-syntax, r=fee1-dead

New const traits syntax

This PR only affects the AST and doesn't actually change anything semantically.

All occurrences of `~const` outside of libcore have been replaced by `[const]`. Within libcore we have to wait for rustfmt to be bumped in the bootstrap compiler. This will happen "automatically" (when rustfmt is run) during the bootstrap bump, as rustfmt converts `~const` into `[const]`. After this we can remove the `~const` support from the parser

Caveat discovered during impl: there is no legacy bare trait object recovery for `[const] Trait` as that snippet in type position goes down the slice /array parsing code and will error

r? ``@fee1-dead``

cc ``@nikomatsakis`` ``@traviscross`` ``@compiler-errors``
This commit is contained in:
Matthias Krüger 2025-06-27 22:13:00 +02:00 committed by GitHub
commit 36c2b011cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
243 changed files with 1641 additions and 1571 deletions

View file

@ -227,7 +227,7 @@ fn clean_generic_bound<'tcx>(
Some(match bound {
hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)),
hir::GenericBound::Trait(t) => {
// `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
// `T: [const] Destruct` is hidden because `T: Destruct` is a no-op.
if let hir::BoundConstness::Maybe(_) = t.modifiers.constness
&& cx.tcx.lang_items().destruct_trait() == Some(t.trait_ref.trait_def_id().unwrap())
{
@ -395,7 +395,7 @@ pub(crate) fn clean_predicate<'tcx>(
ty::ClauseKind::ConstEvaluatable(..)
| ty::ClauseKind::WellFormed(..)
| ty::ClauseKind::ConstArgHasType(..)
// FIXME(const_trait_impl): We can probably use this `HostEffect` pred to render `~const`.
// FIXME(const_trait_impl): We can probably use this `HostEffect` pred to render `[const]`.
| ty::ClauseKind::HostEffect(_) => None,
}
}
@ -404,7 +404,7 @@ fn clean_poly_trait_predicate<'tcx>(
pred: ty::PolyTraitPredicate<'tcx>,
cx: &mut DocContext<'tcx>,
) -> Option<WherePredicate> {
// `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
// `T: [const] Destruct` is hidden because `T: Destruct` is a no-op.
// FIXME(const_trait_impl) check constness
if Some(pred.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait() {
return None;

View file

@ -268,7 +268,7 @@ impl clean::GenericBound {
fmt::from_fn(move |f| match self {
clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()),
clean::GenericBound::TraitBound(ty, modifiers) => {
// `const` and `~const` trait bounds are experimental; don't render them.
// `const` and `[const]` trait bounds are experimental; don't render them.
let hir::TraitBoundModifiers { polarity, constness: _ } = modifiers;
f.write_str(match polarity {
hir::BoundPolarity::Positive => "",

View file

@ -436,7 +436,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
// FIXME(const_trait_impl, fee1-dead) revert to const destruct once it works again
#[expect(unused)]
fn is_ty_const_destruct_unused<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>) -> bool {
// If this doesn't need drop at all, then don't select `~const Destruct`.
// If this doesn't need drop at all, then don't select `[const] Destruct`.
if !ty.needs_drop(tcx, body.typing_env(tcx)) {
return false;
}

View file

@ -91,7 +91,7 @@ mod issue14871 {
impl<T> const NumberConstants for T
where
T: Number + ~const core::ops::Add,
T: Number + [const] core::ops::Add,
{
fn constant(value: usize) -> Self {
let mut res = Self::ZERO;

View file

@ -91,7 +91,7 @@ mod issue14871 {
impl<T> const NumberConstants for T
where
T: Number + ~const core::ops::Add,
T: Number + [const] core::ops::Add,
{
fn constant(value: usize) -> Self {
let mut res = Self::ZERO;

View file

@ -169,9 +169,9 @@ where
// #13476
#[const_trait]
trait ConstTrait {}
const fn const_trait_bounds_good<T: ConstTrait + ~const ConstTrait>() {}
const fn const_trait_bounds_good<T: ConstTrait + [const] ConstTrait>() {}
const fn const_trait_bounds_bad<T: ~const ConstTrait>() {}
const fn const_trait_bounds_bad<T: [const] ConstTrait>() {}
//~^ trait_duplication_in_bounds
fn projections<T, U, V>()

View file

@ -169,9 +169,9 @@ where
// #13476
#[const_trait]
trait ConstTrait {}
const fn const_trait_bounds_good<T: ConstTrait + ~const ConstTrait>() {}
const fn const_trait_bounds_good<T: ConstTrait + [const] ConstTrait>() {}
const fn const_trait_bounds_bad<T: ~const ConstTrait + ~const ConstTrait>() {}
const fn const_trait_bounds_bad<T: [const] ConstTrait + [const] ConstTrait>() {}
//~^ trait_duplication_in_bounds
fn projections<T, U, V>()

View file

@ -61,8 +61,8 @@ LL | fn bad_trait_object(arg0: &(dyn Any + Send + Send)) {
error: these bounds contain repeated elements
--> tests/ui/trait_duplication_in_bounds.rs:174:36
|
LL | const fn const_trait_bounds_bad<T: ~const ConstTrait + ~const ConstTrait>() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `~const ConstTrait`
LL | const fn const_trait_bounds_bad<T: [const] ConstTrait + [const] ConstTrait>() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[const] ConstTrait`
error: these where clauses contain repeated elements
--> tests/ui/trait_duplication_in_bounds.rs:181:8

View file

@ -142,18 +142,18 @@ type MyFn = fn(a: SomeLongComplexType, b: SomeOtherLongComplexType,) -> Box<Futu
// Const bound
trait T: ~ const Super {}
trait T: [ const ] Super {}
const fn not_quite_const<S: ~ const T>() -> i32 { <S as T>::CONST }
const fn not_quite_const<S: [ const ] T>() -> i32 { <S as T>::CONST }
impl ~ const T {}
impl const T for U {}
fn apit(_: impl ~ const T) {}
fn apit(_: impl [ const ] T) {}
fn rpit() -> impl ~ const T { S }
fn rpit() -> impl [ const] T { S }
pub struct Foo<T: Trait>(T);
impl<T: ~ const Trait> Foo<T> {
impl<T: [ const] Trait> Foo<T> {
fn new(t: T) -> Self {
Self(t)
}

View file

@ -147,22 +147,22 @@ type MyFn = fn(
// Const bound
trait T: ~const Super {}
trait T: [const] Super {}
const fn not_quite_const<S: ~const T>() -> i32 {
const fn not_quite_const<S: [const] T>() -> i32 {
<S as T>::CONST
}
impl ~const T {}
impl const T for U {}
fn apit(_: impl ~const T) {}
fn apit(_: impl [const] T) {}
fn rpit() -> impl ~const T {
fn rpit() -> impl [const] T {
S
}
pub struct Foo<T: Trait>(T);
impl<T: ~const Trait> Foo<T> {
impl<T: [const] Trait> Foo<T> {
fn new(t: T) -> Self {
Self(t)
}

View file

@ -3919,7 +3919,6 @@ ui/traits/const-traits/issue-79450.rs
ui/traits/const-traits/issue-88155.rs
ui/traits/const-traits/issue-92111.rs
ui/traits/const-traits/issue-92230-wf-super-trait-env.rs
ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.rs
ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs
ui/traits/issue-103563.rs
ui/traits/issue-104322.rs