Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3cd9780

Browse files
committedJan 12, 2025·
Enforce syntactical stability of const traits in HIR
1 parent 7bb9888 commit 3cd9780

21 files changed

+261
-16
lines changed
 

‎compiler/rustc_middle/src/middle/stability.rs

+80-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ pub enum StabilityLevel {
3030
Stable,
3131
}
3232

33+
#[derive(Copy, Clone)]
34+
pub enum UnstableKind {
35+
/// Enforcing regular stability of an item
36+
Regular,
37+
/// Enforcing const stability of an item
38+
Const(Span),
39+
}
40+
3341
/// An entry in the `depr_map`.
3442
#[derive(Copy, Clone, HashStable, Debug, Encodable, Decodable)]
3543
pub struct DeprecationEntry {
@@ -108,10 +116,16 @@ pub fn report_unstable(
108116
is_soft: bool,
109117
span: Span,
110118
soft_handler: impl FnOnce(&'static Lint, Span, String),
119+
kind: UnstableKind,
111120
) {
121+
let qual = match kind {
122+
UnstableKind::Regular => "",
123+
UnstableKind::Const(_) => " const",
124+
};
125+
112126
let msg = match reason {
113-
Some(r) => format!("use of unstable library feature `{feature}`: {r}"),
114-
None => format!("use of unstable library feature `{feature}`"),
127+
Some(r) => format!("use of unstable{qual} library feature `{feature}`: {r}"),
128+
None => format!("use of unstable{qual} library feature `{feature}`"),
115129
};
116130

117131
if is_soft {
@@ -121,6 +135,9 @@ pub fn report_unstable(
121135
if let Some((inner_types, msg, sugg, applicability)) = suggestion {
122136
err.span_suggestion(inner_types, msg, sugg, applicability);
123137
}
138+
if let UnstableKind::Const(kw) = kind {
139+
err.span_label(kw, "trait is not stable as const yet");
140+
}
124141
err.emit();
125142
}
126143
}
@@ -587,13 +604,74 @@ impl<'tcx> TyCtxt<'tcx> {
587604
is_soft,
588605
span,
589606
soft_handler,
607+
UnstableKind::Regular,
590608
),
591609
EvalResult::Unmarked => unmarked(span, def_id),
592610
}
593611

594612
is_allowed
595613
}
596614

615+
pub fn check_const_stability(self, def_id: DefId, span: Span, const_kw_span: Span) {
616+
let is_staged_api = self.lookup_stability(def_id.krate.as_def_id()).is_some();
617+
if !is_staged_api {
618+
return;
619+
}
620+
621+
// Only the cross-crate scenario matters when checking unstable APIs
622+
let cross_crate = !def_id.is_local();
623+
if !cross_crate {
624+
return;
625+
}
626+
627+
let stability = self.lookup_const_stability(def_id);
628+
debug!(
629+
"stability: \
630+
inspecting def_id={:?} span={:?} of stability={:?}",
631+
def_id, span, stability
632+
);
633+
634+
match stability {
635+
Some(ConstStability {
636+
level: attr::StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. },
637+
feature,
638+
..
639+
}) => {
640+
assert!(!is_soft);
641+
642+
if span.allows_unstable(feature) {
643+
debug!("body stability: skipping span={:?} since it is internal", span);
644+
return;
645+
}
646+
if self.features().enabled(feature) {
647+
return;
648+
}
649+
650+
// If this item was previously part of a now-stabilized feature which is still
651+
// enabled (i.e. the user hasn't removed the attribute for the stabilized feature
652+
// yet) then allow use of this item.
653+
if let Some(implied_by) = implied_by
654+
&& self.features().enabled(implied_by)
655+
{
656+
return;
657+
}
658+
659+
report_unstable(
660+
self.sess,
661+
feature,
662+
reason.to_opt_reason(),
663+
issue,
664+
None,
665+
false,
666+
span,
667+
|_, _, _| {},
668+
UnstableKind::Const(const_kw_span),
669+
);
670+
}
671+
Some(_) | None => {}
672+
}
673+
}
674+
597675
pub fn lookup_deprecation(self, id: DefId) -> Option<Deprecation> {
598676
self.lookup_deprecation_entry(id).map(|depr| depr.attr)
599677
}

‎compiler/rustc_passes/src/stability.rs

+33-3
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()
@@ -772,7 +774,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
772774
// For implementations of traits, check the stability of each item
773775
// individually as it's possible to have a stable trait with unstable
774776
// items.
775-
hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
777+
hir::ItemKind::Impl(hir::Impl {
778+
of_trait: Some(ref t),
779+
self_ty,
780+
items,
781+
constness,
782+
..
783+
}) => {
776784
let features = self.tcx.features();
777785
if features.staged_api() {
778786
let attrs = self.tcx.hir().attrs(item.hir_id());
@@ -814,6 +822,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
814822
}
815823
}
816824

825+
match constness {
826+
rustc_hir::Constness::Const => {
827+
if let Some(def_id) = t.trait_def_id() {
828+
// FIXME(const_trait_impl): Improve the span here.
829+
self.tcx.check_const_stability(def_id, t.path.span, t.path.span);
830+
}
831+
}
832+
rustc_hir::Constness::NotConst => {}
833+
}
834+
817835
for impl_item_ref in *items {
818836
let impl_item = self.tcx.associated_item(impl_item_ref.id.owner_id);
819837

@@ -829,6 +847,18 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
829847
intravisit::walk_item(self, item);
830848
}
831849

850+
fn visit_poly_trait_ref(&mut self, t: &'tcx hir::PolyTraitRef<'tcx>) {
851+
match t.modifiers.constness {
852+
hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) => {
853+
if let Some(def_id) = t.trait_ref.trait_def_id() {
854+
self.tcx.check_const_stability(def_id, t.trait_ref.path.span, span);
855+
}
856+
}
857+
hir::BoundConstness::Never => {}
858+
}
859+
intravisit::walk_poly_trait_ref(self, t);
860+
}
861+
832862
fn visit_path(&mut self, path: &hir::Path<'tcx>, id: hir::HirId) {
833863
if let Some(def_id) = path.res.opt_def_id() {
834864
let method_span = path.segments.last().map(|s| s.ident.span);

‎compiler/rustc_resolve/src/macros.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
10311031
is_soft,
10321032
span,
10331033
soft_handler,
1034+
stability::UnstableKind::Regular,
10341035
);
10351036
}
10361037
}

‎library/core/src/intrinsics/fallback.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#![allow(missing_docs)]
99

1010
#[const_trait]
11+
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
1112
pub trait CarryingMulAdd: Copy + 'static {
1213
type Unsigned: Copy + 'static;
1314
fn carrying_mul_add(

‎library/core/src/marker.rs

+1
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,7 @@ marker_impls! {
952952
/// This should be used for `~const` bounds,
953953
/// as non-const bounds will always hold for every type.
954954
#[unstable(feature = "const_destruct", issue = "133214")]
955+
#[rustc_const_unstable(feature = "const_destruct", issue = "133214")]
955956
#[lang = "destruct"]
956957
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
957958
#[rustc_deny_explicit_impl]

‎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
#[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")]
@@ -263,6 +264,7 @@ impl<T: ?Sized> const Deref for &mut T {
263264
#[doc(alias = "*")]
264265
#[stable(feature = "rust1", since = "1.0.0")]
265266
#[const_trait]
267+
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
266268
pub trait DerefMut: ~const Deref {
267269
/// Mutably dereferences the value.
268270
#[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
#[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_drop)]
44

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

‎tests/ui/consts/promoted_const_call.stderr

+18-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
error[E0658]: use of unstable const library feature `const_destruct`
2+
--> $DIR/promoted_const_call.rs:6:12
3+
|
4+
LL | impl const Drop for Panic { fn drop(&mut self) { panic!(); } }
5+
| ^^^^ trait is not stable as const yet
6+
|
7+
= note: see issue #133214 <https://github.com/rust-lang/rust/issues/133214> for more information
8+
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
9+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
10+
11+
error[E0635]: unknown feature `const_drop`
12+
--> $DIR/promoted_const_call.rs:3:30
13+
|
14+
LL | #![feature(const_trait_impl, const_drop)]
15+
| ^^^^^^^^^^
16+
117
error[E0493]: destructor of `Panic` cannot be evaluated at compile-time
218
--> $DIR/promoted_const_call.rs:10:30
319
|
@@ -52,7 +68,7 @@ LL | let _: &'static _ = &&(Panic, 0).1;
5268
LL | }
5369
| - temporary value is freed at the end of this statement
5470

55-
error: aborting due to 5 previous errors
71+
error: aborting due to 7 previous errors
5672

57-
Some errors have detailed explanations: E0493, E0716.
73+
Some errors have detailed explanations: E0493, E0635, E0658, E0716.
5874
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
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")]

‎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

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//@ aux-build:staged-api.rs
2+
3+
// Ensure that we enforce const stability of traits in `~const`/`const` bounds.
4+
5+
#![feature(const_trait_impl)]
6+
7+
use std::ops::Deref;
8+
9+
extern crate staged_api;
10+
use staged_api::MyTrait;
11+
12+
#[const_trait]
13+
trait Foo: ~const MyTrait {
14+
//~^ ERROR use of unstable const library feature `unstable`
15+
type Item: ~const MyTrait;
16+
//~^ ERROR use of unstable const library feature `unstable`
17+
}
18+
19+
const fn where_clause<T>() where T: ~const MyTrait {}
20+
//~^ ERROR use of unstable const library feature `unstable`
21+
22+
const fn nested<T>() where T: Deref<Target: ~const MyTrait> {}
23+
//~^ ERROR use of unstable const library feature `unstable`
24+
25+
const fn rpit() -> impl ~const MyTrait { Local }
26+
//~^ ERROR use of unstable const library feature `unstable`
27+
28+
struct Local;
29+
impl const MyTrait for Local {
30+
//~^ ERROR use of unstable const library feature `unstable`
31+
fn func() {}
32+
}
33+
34+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
error[E0658]: use of unstable const library feature `unstable`
2+
--> $DIR/syntactical-unstable.rs:13:19
3+
|
4+
LL | trait Foo: ~const MyTrait {
5+
| ------ ^^^^^^^
6+
| |
7+
| trait is not stable as const yet
8+
|
9+
= help: add `#![feature(unstable)]` to the crate attributes to enable
10+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
11+
12+
error[E0658]: use of unstable const library feature `unstable`
13+
--> $DIR/syntactical-unstable.rs:19:44
14+
|
15+
LL | const fn where_clause<T>() where T: ~const MyTrait {}
16+
| ------ ^^^^^^^
17+
| |
18+
| trait is not stable as const yet
19+
|
20+
= help: add `#![feature(unstable)]` to the crate attributes to enable
21+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
22+
23+
error[E0658]: use of unstable const library feature `unstable`
24+
--> $DIR/syntactical-unstable.rs:22:52
25+
|
26+
LL | const fn nested<T>() where T: Deref<Target: ~const MyTrait> {}
27+
| ------ ^^^^^^^
28+
| |
29+
| trait is not stable as const yet
30+
|
31+
= help: add `#![feature(unstable)]` to the crate attributes to enable
32+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
33+
34+
error[E0658]: use of unstable const library feature `unstable`
35+
--> $DIR/syntactical-unstable.rs:25:32
36+
|
37+
LL | const fn rpit() -> impl ~const MyTrait { Local }
38+
| ------ ^^^^^^^
39+
| |
40+
| trait is not stable as const yet
41+
|
42+
= help: add `#![feature(unstable)]` to the crate attributes to enable
43+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
44+
45+
error[E0658]: use of unstable const library feature `unstable`
46+
--> $DIR/syntactical-unstable.rs:29:12
47+
|
48+
LL | impl const MyTrait for Local {
49+
| ^^^^^^^ trait is not stable as const yet
50+
|
51+
= help: add `#![feature(unstable)]` to the crate attributes to enable
52+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
53+
54+
error[E0658]: use of unstable const library feature `unstable`
55+
--> $DIR/syntactical-unstable.rs:15:23
56+
|
57+
LL | type Item: ~const MyTrait;
58+
| ------ ^^^^^^^
59+
| |
60+
| trait is not stable as const yet
61+
|
62+
= help: add `#![feature(unstable)]` to the crate attributes to enable
63+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
64+
65+
error: aborting due to 6 previous errors
66+
67+
For more information about this error, try `rustc --explain E0658`.

‎tests/ui/traits/const-traits/trait-default-body-stability.rs

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ impl const FromResidual for T {
3838
}
3939

4040
#[stable(feature = "foo", since = "1.0")]
41+
#[rustc_const_unstable(feature = "const_tr", issue = "none")]
4142
#[const_trait]
4243
pub trait Tr {
4344
#[stable(feature = "foo", since = "1.0")]

‎tests/ui/traits/const-traits/trait-default-body-stability.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ LL | impl const FromResidual for T {
1717
= note: adding a non-const method body in the future would be a breaking change
1818

1919
error[E0015]: `?` is not allowed on `T` in constant functions
20-
--> $DIR/trait-default-body-stability.rs:45:9
20+
--> $DIR/trait-default-body-stability.rs:46:9
2121
|
2222
LL | T?
2323
| ^^
2424
|
2525
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
2626

2727
error[E0015]: `?` is not allowed on `T` in constant functions
28-
--> $DIR/trait-default-body-stability.rs:45:9
28+
--> $DIR/trait-default-body-stability.rs:46:9
2929
|
3030
LL | T?
3131
| ^^

0 commit comments

Comments
 (0)
Please sign in to comment.