@@ -53,22 +53,38 @@ marks an item as stabilized. Note that stable functions may use unstable things
53
53
54
54
The `#[ rustc_const_unstable(feature = "foo", issue = "1234", reason = "lorem
55
55
ipsum")] ` has the same interface as the ` unstable` attribute. It is used to mark
56
- ` const fn ` as having their constness be unstable. Every ` const fn ` with
57
- stability attributes should carry either this attribute or
58
- ` #[rustc_const_stable] ` (see below).
56
+ ` const fn ` as having their constness be unstable. This is only needed in rare cases:
57
+ - If a ` const fn ` makes use of unstable language features or intrinsics.
58
+ (The compiler will tell you to add the attribute if you run into this.)
59
+ - If a ` const fn ` is ` #[stable] ` but not yet intended to be const-stable.
59
60
60
- Furthermore this attribute is needed to mark an intrinsic as ` const fn ` , because
61
+ Furthermore, this attribute is needed to mark an intrinsic as an * unstable * ` const fn ` , because
61
62
there's no way to add ` const ` to functions in ` extern ` blocks for now.
62
63
64
+ Const-stability differs from regular stability in that it is * recursive* : a
65
+ ` #[rustc_const_unstable(...)] ` function cannot even be indirectly called from stable code. This is
66
+ to avoid accidentally leaking unstable compiler implementation artifacts to stable code or locking
67
+ us into the accidental quirks of an incomplete implementation. See the rustc_const_stable_indirect
68
+ and rustc_allow_const_fn_unstable attributes below for how to fine-tune this check.
69
+
63
70
## rustc_const_stable
64
71
65
72
The ` #[rustc_const_stable(feature = "foo", since = "1.420.69")] ` attribute explicitly marks
66
- a ` const fn ` as having its constness be ` stable ` . This attribute can make sense
67
- even on an ` unstable ` function, if that function is called from another
68
- ` rustc_const_stable ` function.
73
+ a ` const fn ` as having its constness be ` stable ` .
74
+
75
+ ## rustc_const_stable_indirect
76
+
77
+ The ` #[rustc_const_stable_indirect] ` attribute can be added to a ` #[rustc_const_unstable(...)] `
78
+ function to make it callable from ` #[rustc_const_stable(...)] ` functions. This indicates that the
79
+ function is ready for stable in terms of its implementation (i.e., it doesn't use any unstable
80
+ compiler features); the only reason it is not const-stable yet are API concerns.
69
81
70
- Furthermore this attribute is needed to mark an intrinsic as callable from
71
- ` rustc_const_stable ` functions.
82
+ This should also be added to lang items for which const-calls are synthesized in the compiler, to
83
+ ensure those calls do not bypass recursive const stability rules.
84
+
85
+ On an intrinsic, this attribute marks the intrinsic as "ready to be used by public stable functions".
86
+ The ` rustc_const_unstable ` can be removed when this attribute is added.
87
+ ** Adding this attribute to an intrinsic requires t-lang and wg-const-eval approval!**
72
88
73
89
## rustc_default_body_unstable
74
90
@@ -89,8 +105,9 @@ To stabilize a feature, follow these steps:
89
105
2 . Change ` #[unstable(...)] ` to ` #[stable(since = "CURRENT_RUSTC_VERSION")] ` .
90
106
3 . Remove ` #![feature(...)] ` from any test or doc-test for this API. If the feature is used in the
91
107
compiler or tools, remove it from there as well.
92
- 4 . If applicable, change ` #[rustc_const_unstable(...)] ` to
93
- ` #[rustc_const_stable(since = "CURRENT_RUSTC_VERSION")] ` .
108
+ 4 . If this is a ` const fn ` , add ` #[rustc_const_stable(since = "CURRENT_RUSTC_VERSION")] ` .
109
+ Alternatively, if this is not supposed to be const-stabilized yet,
110
+ add ` #[rustc_const_unstable(...)] ` for some new feature gate (with a new tracking issue).
94
111
5 . Open a PR against ` rust-lang/rust ` .
95
112
- Add the appropriate labels: ` @rustbot modify labels: +T-libs-api ` .
96
113
- Link to the tracking issue and say "Closes #XXXXX".
@@ -107,27 +124,30 @@ site. To work around not being able to use unstable things in the standard
107
124
library's macros, there's the ` #[allow_internal_unstable(feature1, feature2)] `
108
125
attribute that allows the given features to be used in stable macros.
109
126
127
+ Note that if a macro is used in const context and generates a call to a
128
+ ` #[rustc_const_unstable(...)] ` function, that will * still* be rejected even with
129
+ ` allow_internal_unstable ` . Add ` #[rustc_const_stable_indirect] ` to the function to ensure the macro
130
+ cannot accidentally bypass the recursive const stability checks.
131
+
110
132
## rustc_allow_const_fn_unstable
111
133
112
- ` const fn ` , while not directly exposing their body to the world, are going to get
113
- evaluated at compile time in stable crates. If their body does something const-unstable,
114
- that could lock us into certain features indefinitely by accident. Thus no unstable const
115
- features are allowed inside stable ` const fn ` .
134
+ As explained above, no unstable const features are allowed inside stable ` const fn ` , not even
135
+ indirectly.
116
136
117
- However, sometimes we do know that a feature will get
118
- stabilized, just not when, or there is a stable (but e.g. runtime-slow) workaround, so we
119
- could always fall back to some stable version if we scrapped the unstable feature.
120
- In those cases, the rustc_allow_const_fn_unstable attribute can be used to allow some
121
- unstable features in the body of a stable ` const fn ` .
137
+ However, sometimes we do know that a feature will get stabilized, just not when, or there is a
138
+ stable (but e.g. runtime-slow) workaround, so we could always fall back to some stable version if we
139
+ scrapped the unstable feature. In those cases, the ` [ rustc_allow_const_fn_unstable(feature1,
140
+ feature2) ] ` attribute can be used to allow some unstable features in the body of a stable (or
141
+ indirectly stable) ` const fn ` .
122
142
123
143
You also need to take care to uphold the ` const fn ` invariant that calling it at runtime and
124
144
compile-time needs to behave the same (see also [ this blog post] [ blog ] ). This means that you
125
145
may not create a ` const fn ` that e.g. transmutes a memory address to an integer,
126
146
because the addresses of things are nondeterministic and often unknown at
127
147
compile-time.
128
148
129
- Always ping @rust-lang/wg-const-eval if you are adding more
130
- ` rustc_allow_const_fn_unstable ` attributes to any ` const fn ` .
149
+ ** Always ping @rust-lang/wg-const-eval if you are adding more
150
+ ` rustc_allow_const_fn_unstable ` attributes to any ` const fn ` .**
131
151
132
152
## staged_api
133
153
0 commit comments