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

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

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

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

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
@@ -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

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

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

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)