Skip to content

Commit ee3f3df

Browse files
committed
Implement trait const stability
1 parent 78af7da commit ee3f3df

29 files changed

+207
-62
lines changed

compiler/rustc_const_eval/src/check_consts/check.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -709,8 +709,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
709709
if trait_is_const {
710710
// Trait calls are always conditionally-const.
711711
self.check_op(ops::ConditionallyConstCall { callee, args: fn_args });
712-
// FIXME(const_trait_impl): do a more fine-grained check whether this
713-
// particular trait can be const-stably called.
712+
self.tcx.enforce_trait_const_stability(trait_did, *fn_span);
714713
} else {
715714
// Not even a const trait.
716715
self.check_op(ops::FnCallNonConst {

compiler/rustc_hir_analysis/src/collect.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,7 @@ fn check_impl_constness(
16121612

16131613
let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
16141614
if tcx.is_const_trait(trait_def_id) {
1615+
tcx.enforce_trait_const_stability(trait_def_id, hir_trait_ref.path.span);
16151616
return;
16161617
}
16171618

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -741,9 +741,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
741741
};
742742

743743
if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness
744-
&& !self.tcx().is_const_trait(trait_def_id)
745744
{
746-
let (def_span, suggestion, suggestion_pre) =
745+
if !self.tcx().is_const_trait(trait_def_id) {
746+
let (def_span, suggestion, suggestion_pre) =
747747
match (trait_def_id.is_local(), self.tcx().sess.is_nightly_build()) {
748748
(true, true) => (
749749
None,
@@ -756,14 +756,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
756756
),
757757
(false, _) | (_, false) => (Some(tcx.def_span(trait_def_id)), None, ""),
758758
};
759-
self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
760-
span,
761-
modifier: constness.as_str(),
762-
def_span,
763-
trait_name: self.tcx().def_path_str(trait_def_id),
764-
suggestion_pre,
765-
suggestion,
766-
});
759+
self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
760+
span,
761+
modifier: constness.as_str(),
762+
def_span,
763+
trait_name: self.tcx().def_path_str(trait_def_id),
764+
suggestion_pre,
765+
suggestion,
766+
});
767+
}
768+
769+
tcx.enforce_trait_const_stability(trait_def_id, span)
767770
}
768771

769772
match predicate_filter {

compiler/rustc_middle/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ middle_type_length_limit = reached the type-length limit while instantiating `{$
105105
middle_unknown_layout =
106106
the type `{$ty}` has an unknown layout
107107
108+
middle_unstable_const_trait = `{$def_path}` is not yet stable as a const trait
109+
108110
middle_values_too_big =
109111
values of the type `{$ty}` are too big for the target architecture
110112
middle_written_to_path = the full type name has been written to '{$path}'

compiler/rustc_middle/src/error.rs

+8
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,11 @@ pub struct TypeLengthLimit {
171171
pub path: PathBuf,
172172
pub type_length: usize,
173173
}
174+
175+
#[derive(Diagnostic)]
176+
#[diag(middle_unstable_const_trait)]
177+
pub struct UnstableConstTrait {
178+
#[primary_span]
179+
pub span: Span,
180+
pub def_path: String,
181+
}

compiler/rustc_middle/src/ty/context.rs

+30
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use std::{fmt, iter, mem};
1515

1616
use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx};
1717
use rustc_ast as ast;
18+
use rustc_attr_parsing::{ConstStability, StabilityLevel};
1819
use rustc_data_structures::defer;
1920
use rustc_data_structures::fingerprint::Fingerprint;
2021
use rustc_data_structures::fx::FxHashMap;
@@ -3132,6 +3133,35 @@ impl<'tcx> TyCtxt<'tcx> {
31323133
&& self.impl_trait_header(def_id).unwrap().constness == hir::Constness::Const
31333134
}
31343135

3136+
pub fn enforce_trait_const_stability(self, trait_def_id: DefId, span: Span) {
3137+
match self.lookup_const_stability(trait_def_id) {
3138+
Some(ConstStability {
3139+
level: StabilityLevel::Unstable { implied_by: implied_feature, .. },
3140+
feature,
3141+
..
3142+
}) => {
3143+
if span.allows_unstable(feature)
3144+
|| implied_feature.is_some_and(|f| span.allows_unstable(f))
3145+
{
3146+
return;
3147+
}
3148+
let feature_enabled = trait_def_id.is_local()
3149+
|| self.features().enabled(feature)
3150+
|| implied_feature.is_some_and(|f| self.features().enabled(f));
3151+
3152+
if !feature_enabled {
3153+
let mut diag = self.dcx().create_err(crate::error::UnstableConstTrait {
3154+
span,
3155+
def_path: self.def_path_str(trait_def_id),
3156+
});
3157+
self.disabled_nightly_features(&mut diag, None, [(String::new(), feature)]);
3158+
diag.emit();
3159+
}
3160+
}
3161+
_ => {}
3162+
}
3163+
}
3164+
31353165
pub fn intrinsic(self, def_id: impl IntoQueryParam<DefId> + Copy) -> Option<ty::IntrinsicDef> {
31363166
match self.def_kind(def_id) {
31373167
DefKind::Fn | DefKind::AssocFn => {}

compiler/rustc_passes/src/stability.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -593,9 +593,11 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
593593
}
594594

595595
fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) {
596-
let is_const = self.tcx.is_const_fn(def_id.to_def_id());
596+
let is_const = self.tcx.is_const_fn(def_id.to_def_id())
597+
|| (self.tcx.def_kind(def_id.to_def_id()) == DefKind::Trait
598+
&& self.tcx.is_const_trait(def_id.to_def_id()));
597599

598-
// Reachable const fn must have a stability attribute.
600+
// Reachable const fn/trait must have a stability attribute.
599601
if is_const
600602
&& self.effective_visibilities.is_reachable(def_id)
601603
&& self.tcx.lookup_const_stability(def_id).is_none()

library/core/src/marker.rs

+1
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,7 @@ marker_impls! {
960960
/// This should be used for `~const` bounds,
961961
/// as non-const bounds will always hold for every type.
962962
#[unstable(feature = "const_destruct", issue = "133214")]
963+
#[rustc_const_unstable(feature = "const_destruct", issue = "133214")]
963964
#[lang = "destruct"]
964965
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
965966
#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))]

library/core/src/ops/arith.rs

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
/// ```
6666
#[lang = "add"]
6767
#[stable(feature = "rust1", since = "1.0.0")]
68+
#[rustc_const_unstable(feature = "const_ops", issue = "90080")]
6869
#[rustc_on_unimplemented(
6970
on(all(_Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",),
7071
on(all(_Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",),

library/core/src/ops/deref.rs

+2
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@
134134
#[stable(feature = "rust1", since = "1.0.0")]
135135
#[rustc_diagnostic_item = "Deref"]
136136
#[cfg_attr(not(bootstrap), const_trait)]
137+
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
137138
pub trait Deref {
138139
/// The resulting type after dereferencing.
139140
#[stable(feature = "rust1", since = "1.0.0")]
@@ -287,6 +288,7 @@ impl<T: ?Sized> const Deref for &mut T {
287288
#[doc(alias = "*")]
288289
#[stable(feature = "rust1", since = "1.0.0")]
289290
#[const_trait]
291+
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
290292
pub trait DerefMut: ~const Deref {
291293
/// Mutably dereferences the value.
292294
#[stable(feature = "rust1", since = "1.0.0")]

library/core/src/ops/drop.rs

+1
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@
204204
#[lang = "drop"]
205205
#[stable(feature = "rust1", since = "1.0.0")]
206206
#[cfg_attr(not(bootstrap), const_trait)]
207+
#[rustc_const_unstable(feature = "const_destruct", issue = "133214")]
207208
pub trait Drop {
208209
/// Executes the destructor for this type.
209210
///

tests/ui/consts/promoted-const-drop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(const_trait_impl)]
1+
#![feature(const_trait_impl, const_destruct)]
22

33
struct A();
44

tests/ui/consts/promoted_const_call.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@ known-bug: #103507
22

3-
#![feature(const_trait_impl)]
3+
#![feature(const_trait_impl, const_destruct)]
44

55
struct Panic;
66
impl const Drop for Panic { fn drop(&mut self) { panic!(); } }

tests/ui/issues/issue-25901.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ struct B;
33

44
static S: &'static B = &A;
55
//~^ ERROR cannot call conditionally-const method
6+
//~| ERROR `Deref` is not yet stable as a const trait
67

78
use std::ops::Deref;
89

tests/ui/issues/issue-25901.stderr

+9-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ LL | static S: &'static B = &A;
88
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
99
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1010

11-
error: aborting due to 1 previous error
11+
error: `Deref` is not yet stable as a const trait
12+
--> $DIR/issue-25901.rs:4:24
13+
|
14+
LL | static S: &'static B = &A;
15+
| ^^
16+
|
17+
= help: add `#![feature(const_deref)]` to the crate attributes to enable
18+
19+
error: aborting due to 2 previous errors
1220

1321
For more information about this error, try `rustc --explain E0658`.

tests/ui/self/arbitrary-self-from-method-substs-ice.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ impl Foo {
1212
//~| ERROR destructor of `R` cannot be evaluated at compile-time
1313
self.0
1414
//~^ ERROR cannot call conditionally-const method `<R as Deref>::deref` in constant function
15+
//~| ERROR `Deref` is not yet stable as a const trait
1516
}
1617
}
1718

tests/ui/self/arbitrary-self-from-method-substs-ice.stderr

+9-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ LL | self.0
88
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
99
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1010

11+
error: `Deref` is not yet stable as a const trait
12+
--> $DIR/arbitrary-self-from-method-substs-ice.rs:13:9
13+
|
14+
LL | self.0
15+
| ^^^^^^
16+
|
17+
= help: add `#![feature(const_deref)]` to the crate attributes to enable
18+
1119
error[E0493]: destructor of `R` cannot be evaluated at compile-time
1220
--> $DIR/arbitrary-self-from-method-substs-ice.rs:10:43
1321
|
@@ -26,7 +34,7 @@ LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
2634
= note: type of `self` must not be a method generic parameter type
2735
= help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
2836

29-
error: aborting due to 3 previous errors
37+
error: aborting due to 4 previous errors
3038

3139
Some errors have detailed explanations: E0493, E0658, E0801.
3240
For more information about an error, try `rustc --explain E0493`.

tests/ui/stability-attribute/missing-const-stability.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ impl Foo {
2222
#[stable(feature = "stable", since = "1.0.0")]
2323
#[const_trait]
2424
pub trait Bar {
25+
//~^ ERROR: trait has missing const stability attribute
2526
#[stable(feature = "stable", since = "1.0.0")]
2627
fn fun();
2728
}

tests/ui/stability-attribute/missing-const-stability.stderr

+12-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,18 @@ error: function has missing const stability attribute
44
LL | pub const fn foo() {}
55
| ^^^^^^^^^^^^^^^^^^^^^
66

7+
error: trait has missing const stability attribute
8+
--> $DIR/missing-const-stability.rs:24:1
9+
|
10+
LL | / pub trait Bar {
11+
LL | |
12+
LL | | #[stable(feature = "stable", since = "1.0.0")]
13+
LL | | fn fun();
14+
LL | | }
15+
| |_^
16+
717
error: function has missing const stability attribute
8-
--> $DIR/missing-const-stability.rs:36:1
18+
--> $DIR/missing-const-stability.rs:37:1
919
|
1020
LL | pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
1121
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,5 +26,5 @@ error: associated function has missing const stability attribute
1626
LL | pub const fn foo() {}
1727
| ^^^^^^^^^^^^^^^^^^^^^
1828

19-
error: aborting due to 3 previous errors
29+
error: aborting due to 4 previous errors
2030

tests/ui/traits/const-traits/auxiliary/staged-api.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![stable(feature = "rust1", since = "1.0.0")]
55

66
#[stable(feature = "rust1", since = "1.0.0")]
7+
#[rustc_const_unstable(feature = "unstable", issue = "none")]
78
#[const_trait]
89
pub trait MyTrait {
910
#[stable(feature = "rust1", since = "1.0.0")]
@@ -14,16 +15,6 @@ pub trait MyTrait {
1415
pub struct Unstable;
1516

1617
#[stable(feature = "rust1", since = "1.0.0")]
17-
#[rustc_const_unstable(feature = "unstable", issue = "none")]
1818
impl const MyTrait for Unstable {
1919
fn func() {}
2020
}
21-
22-
#[stable(feature = "rust1", since = "1.0.0")]
23-
pub struct Unstable2;
24-
25-
#[stable(feature = "rust1", since = "1.0.0")]
26-
#[rustc_const_unstable(feature = "unstable2", issue = "none")]
27-
impl const MyTrait for Unstable2 {
28-
fn func() {}
29-
}

tests/ui/traits/const-traits/call-const-trait-method-pass.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@ known-bug: #110395
22

3-
#![feature(const_trait_impl)]
3+
#![feature(const_trait_impl, const_ops)]
44

55
struct Int(i32);
66

tests/ui/traits/const-traits/const-and-non-const-impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@ known-bug: #110395
22

3-
#![feature(const_trait_impl)]
3+
#![feature(const_trait_impl, const_ops)]
44

55
pub struct Int(i32);
66

tests/ui/traits/const-traits/generic-bound.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@ check-pass
22

3-
#![feature(const_trait_impl)]
3+
#![feature(const_trait_impl, const_ops)]
44

55
use std::marker::PhantomData;
66

tests/ui/traits/const-traits/staged-api-user-crate.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,30 @@ fn non_const_context() {
1010

1111
const fn stable_const_context() {
1212
Unstable::func();
13-
//~^ ERROR cannot call conditionally-const associated function `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
13+
//~^ ERROR: cannot call conditionally-const associated function `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
14+
//~| ERROR: `staged_api::MyTrait` is not yet stable as a const trait
1415
}
1516

17+
struct S1;
18+
impl MyTrait for S1 {
19+
fn func() {}
20+
}
21+
22+
// const impls are gated
23+
struct S2;
24+
impl const MyTrait for S2 {
25+
//~^ ERROR: `staged_api::MyTrait` is not yet stable as a const trait
26+
//~| ERROR: const trait impls are experimental
27+
fn func() {}
28+
}
29+
30+
fn bound1<T: MyTrait>() {}
31+
const fn bound2<T: ~const MyTrait>() {}
32+
//~^ ERROR: `staged_api::MyTrait` is not yet stable as a const trait
33+
//~| ERROR: `staged_api::MyTrait` is not yet stable as a const trait
34+
//~| ERROR: const trait impls are experimental
35+
fn bound3<T: const MyTrait>() {}
36+
//~^ ERROR: `staged_api::MyTrait` is not yet stable as a const trait
37+
//~| ERROR: const trait impls are experimental
38+
1639
fn main() {}

0 commit comments

Comments
 (0)