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

Lines changed: 1 addition & 2 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 13 additions & 10 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 30 additions & 0 deletions
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

Lines changed: 4 additions & 2 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 2 additions & 0 deletions
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")]

0 commit comments

Comments
 (0)