Skip to content

Commit fa450eb

Browse files
committed
Implement trait const stability
1 parent 75716b4 commit fa450eb

29 files changed

+203
-60
lines changed

compiler/rustc_const_eval/src/check_consts/check.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -695,8 +695,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
695695
if trait_is_const {
696696
// Trait calls are always conditionally-const.
697697
self.check_op(ops::ConditionallyConstCall { callee, args: fn_args });
698-
// FIXME(const_trait_impl): do a more fine-grained check whether this
699-
// particular trait can be const-stably called.
698+
self.tcx.enforce_trait_const_stability(trait_did, *fn_span);
700699
} else {
701700
// Not even a const trait.
702701
self.check_op(ops::FnCallNonConst {

compiler/rustc_hir_analysis/src/collect.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,7 @@ fn check_impl_constness(
16331633

16341634
let trait_def_id = hir_trait_ref.trait_def_id()?;
16351635
if tcx.is_const_trait(trait_def_id) {
1636+
tcx.enforce_trait_const_stability(trait_def_id, hir_trait_ref.path.span);
16361637
return None;
16371638
}
16381639

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -734,13 +734,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
734734
}
735735
};
736736

737-
if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness
738-
&& !self.tcx().is_const_trait(trait_def_id)
739-
{
740-
self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
741-
span,
742-
modifier: constness.as_str(),
743-
});
737+
if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness {
738+
if !self.tcx().is_const_trait(trait_def_id) {
739+
self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
740+
span,
741+
modifier: constness.as_str(),
742+
});
743+
}
744+
tcx.enforce_trait_const_stability(trait_def_id, span)
744745
}
745746

746747
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
@@ -14,6 +14,7 @@ use std::{fmt, iter, mem};
1414

1515
use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx};
1616
use rustc_ast::{self as ast, attr};
17+
use rustc_attr::{ConstStability, StabilityLevel};
1718
use rustc_data_structures::defer;
1819
use rustc_data_structures::fingerprint::Fingerprint;
1920
use rustc_data_structures::fx::FxHashMap;
@@ -3140,6 +3141,35 @@ impl<'tcx> TyCtxt<'tcx> {
31403141
&& self.constness(def_id) == hir::Constness::Const
31413142
}
31423143

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

compiler/rustc_passes/src/stability.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -590,9 +590,11 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
590590
}
591591

592592
fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) {
593-
let is_const = self.tcx.is_const_fn(def_id.to_def_id());
593+
let is_const = self.tcx.is_const_fn(def_id.to_def_id())
594+
|| (self.tcx.def_kind(def_id.to_def_id()) == DefKind::Trait
595+
&& self.tcx.is_const_trait(def_id.to_def_id()));
594596

595-
// Reachable const fn must have a stability attribute.
597+
// Reachable const fn/trait must have a stability attribute.
596598
if is_const
597599
&& self.effective_visibilities.is_reachable(def_id)
598600
&& self.tcx.lookup_const_stability(def_id).is_none()

library/core/src/marker.rs

+1
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,7 @@ marker_impls! {
954954
/// This should be used for `~const` bounds,
955955
/// as non-const bounds will always hold for every type.
956956
#[unstable(feature = "const_destruct", issue = "133214")]
957+
#[rustc_const_unstable(feature = "const_destruct", issue = "133214")]
957958
#[lang = "destruct"]
958959
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
959960
#[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

+10-2
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
|
@@ -18,7 +26,7 @@ LL | }
1826
| - value is dropped here
1927

2028
note: erroneous constant encountered
21-
--> $DIR/arbitrary-self-from-method-substs-ice.rs:24:5
29+
--> $DIR/arbitrary-self-from-method-substs-ice.rs:25:5
2230
|
2331
LL | FOO;
2432
| ^^^
@@ -32,7 +40,7 @@ LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
3240
= note: type of `self` must not be a method generic parameter type
3341
= 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`)
3442

35-
error: aborting due to 3 previous errors
43+
error: aborting due to 4 previous errors
3644

3745
Some errors have detailed explanations: E0493, E0658, E0801.
3846
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)