Skip to content

Commit 053d1a4

Browse files
committed
only use rustc_const_stable on functions that are actually stable, and inherit const feature gate from other unstable gates
With this, we need fewer rustc_const_(un)stable annotations
1 parent b630e50 commit 053d1a4

23 files changed

+341
-181
lines changed

compiler/rustc_attr/src/builtin.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,14 @@ pub fn find_stability(
274274

275275
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
276276
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
277+
///
278+
/// `inherited_feature_gate` says which feature gate this function should be under if it doesn't
279+
/// declare a gate itself, but has `#[rustc_const_stable_indirect]`.
277280
pub fn find_const_stability(
278281
sess: &Session,
279282
attrs: &[Attribute],
280283
item_sp: Span,
284+
inherited_feature_gate: Option<Symbol>,
281285
) -> Option<(ConstStability, Span)> {
282286
let mut const_stab: Option<(ConstStability, Span)> = None;
283287
let mut promotable = false;
@@ -351,8 +355,11 @@ pub fn find_const_stability(
351355
}
352356
}
353357
_ => {
358+
// `#[rustc_const_stable_indirect]` implicitly makes the function unstably const,
359+
// inheriting the feature gate from `#[unstable]` if it xists, or without any
360+
// feature gate otherwise.
354361
let c = ConstStability {
355-
feature: None,
362+
feature: inherited_feature_gate,
356363
safe_to_expose_on_stable: true,
357364
promotable: false,
358365
level: StabilityLevel::Unstable {

compiler/rustc_expand/src/base.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,11 @@ impl SyntaxExtension {
865865
})
866866
.unwrap_or_else(|| (None, helper_attrs));
867867
let stability = attr::find_stability(sess, attrs, span);
868-
let const_stability = attr::find_const_stability(sess, attrs, span);
868+
// FIXME: this will give a different result than the normal stability computation, since we
869+
// don't inherit stability from the parent. But that's true even for `stability` above so
870+
// it's probably okay?
871+
let const_stability =
872+
attr::find_const_stability(sess, attrs, span, stability.map(|(s, _)| s.feature));
869873
let body_stability = attr::find_body_stability(sess, attrs);
870874
if let Some((_, sp)) = const_stability {
871875
sess.dcx().emit_err(errors::MacroConstStability {

compiler/rustc_passes/messages.ftl

+5-1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ passes_collapse_debuginfo =
9595
passes_confusables = attribute should be applied to an inherent method
9696
.label = not an inherent method
9797
98+
passes_const_stable_not_stable =
99+
attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`
100+
.label = attribute specified here
101+
98102
passes_continue_labeled_block =
99103
`continue` pointing to a labeled block
100104
.label = labeled blocks cannot be `continue`'d
@@ -450,7 +454,7 @@ passes_may_dangle =
450454
passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
451455
452456
passes_missing_const_err =
453-
attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
457+
attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
454458
.help = make the function or method const
455459
.label = attribute specified here
456460

compiler/rustc_passes/src/errors.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,7 @@ pub(crate) struct DuplicateFeatureErr {
15441544
pub span: Span,
15451545
pub feature: Symbol,
15461546
}
1547+
15471548
#[derive(Diagnostic)]
15481549
#[diag(passes_missing_const_err)]
15491550
pub(crate) struct MissingConstErr {
@@ -1554,6 +1555,15 @@ pub(crate) struct MissingConstErr {
15541555
pub const_span: Span,
15551556
}
15561557

1558+
#[derive(Diagnostic)]
1559+
#[diag(passes_const_stable_not_stable)]
1560+
pub(crate) struct ConstStableNotStable {
1561+
#[primary_span]
1562+
pub fn_sig_span: Span,
1563+
#[label]
1564+
pub const_span: Span,
1565+
}
1566+
15571567
#[derive(LintDiagnostic)]
15581568
pub(crate) enum MultipleDeadCodes<'tcx> {
15591569
#[diag(passes_dead_codes)]

compiler/rustc_passes/src/stability.rs

+47-12
Original file line numberDiff line numberDiff line change
@@ -162,19 +162,32 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
162162
}
163163

164164
let stab = attr::find_stability(self.tcx.sess, attrs, item_sp);
165-
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item_sp);
165+
let const_stab = attr::find_const_stability(
166+
self.tcx.sess,
167+
attrs,
168+
item_sp,
169+
// Compute the feature gate we inherit if this
170+
// doesn't have its own feature gate.
171+
self.parent_const_stab.and_then(|c| c.feature).or_else(|| {
172+
// Infer the const feature gate from the regular feature gate,
173+
// but only if that regular gate is unstable.
174+
if let Some((s, _)) = stab {
175+
s.is_unstable().then_some(s.feature)
176+
} else if inherit_deprecation.yes()
177+
&& let Some(parent_stab) = self.parent_stab
178+
&& parent_stab.is_unstable()
179+
{
180+
Some(parent_stab.feature)
181+
} else {
182+
None
183+
}
184+
}),
185+
);
166186
let body_stab = attr::find_body_stability(self.tcx.sess, attrs);
167-
let mut const_span = None;
168-
169-
let const_stab = const_stab.map(|(const_stab, const_span_node)| {
170-
self.index.const_stab_map.insert(def_id, const_stab);
171-
const_span = Some(const_span_node);
172-
const_stab
173-
});
174187

175188
// If the current node is a function, has const stability attributes and if it doesn not have an intrinsic ABI,
176189
// check if the function/method is const or the parent impl block is const
177-
if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig)
190+
if let (Some((_, const_span)), Some(fn_sig)) = (const_stab, fn_sig)
178191
&& fn_sig.header.abi != Abi::RustIntrinsic
179192
&& !fn_sig.header.is_const()
180193
&& (!self.in_trait_impl || !self.tcx.is_const_fn_raw(def_id.to_def_id()))
@@ -184,6 +197,22 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
184197
.emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span });
185198
}
186199

200+
// If this is marked const *stable*, it must also be regular-stable.
201+
if let Some((const_stab, const_span)) = const_stab
202+
&& let Some(fn_sig) = fn_sig
203+
&& const_stab.is_const_stable()
204+
&& !stab.is_some_and(|(s, _)| s.is_stable())
205+
{
206+
self.tcx
207+
.dcx()
208+
.emit_err(errors::ConstStableNotStable { fn_sig_span: fn_sig.span, const_span });
209+
}
210+
211+
let const_stab = const_stab.map(|(const_stab, _span)| {
212+
self.index.const_stab_map.insert(def_id, const_stab);
213+
const_stab
214+
});
215+
187216
// `impl const Trait for Type` items forward their const stability to their
188217
// immediate children.
189218
if const_stab.is_none() {
@@ -274,8 +303,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
274303
}
275304
}
276305

277-
// Every `const fn` that has stability should also have const-stability.
278-
279306
self.recurse_with_stability_attrs(
280307
depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
281308
stab,
@@ -724,7 +751,15 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
724751
if features.staged_api {
725752
let attrs = self.tcx.hir().attrs(item.hir_id());
726753
let stab = attr::find_stability(self.tcx.sess, attrs, item.span);
727-
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item.span);
754+
// FIXME: this will give a different result than the normal stability
755+
// computation, since we don't inherit stability from the parent. But that's
756+
// true even for `stab` above so it's probably okay?
757+
let const_stab = attr::find_const_stability(
758+
self.tcx.sess,
759+
attrs,
760+
item.span,
761+
stab.map(|(s, _)| s.feature),
762+
);
728763

729764
// If this impl block has an #[unstable] attribute, give an
730765
// error if all involved types and traits are stable, because

library/core/src/alloc/layout.rs

-2
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,6 @@ impl Layout {
302302
/// This can return at most `Alignment::MAX` (aka `isize::MAX + 1`)
303303
/// because the original size is at most `isize::MAX`.
304304
#[inline]
305-
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
306305
const fn size_rounded_up_to_custom_align(&self, align: Alignment) -> usize {
307306
// SAFETY:
308307
// Rounded up value is:
@@ -507,7 +506,6 @@ impl Layout {
507506
return inner(T::LAYOUT, n);
508507

509508
#[inline]
510-
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
511509
const fn inner(element_layout: Layout, n: usize) -> Result<Layout, LayoutError> {
512510
let Layout { size: element_size, align } = element_layout;
513511

library/core/src/ffi/c_str.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,11 @@ enum FromBytesWithNulErrorKind {
137137

138138
// FIXME: const stability attributes should not be required here, I think
139139
impl FromBytesWithNulError {
140-
#[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
140+
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))]
141141
const fn interior_nul(pos: usize) -> FromBytesWithNulError {
142142
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) }
143143
}
144-
#[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
144+
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))]
145145
const fn not_nul_terminated() -> FromBytesWithNulError {
146146
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated }
147147
}
@@ -730,7 +730,7 @@ impl AsRef<CStr> for CStr {
730730
/// located within `isize::MAX` from `ptr`.
731731
#[inline]
732732
#[unstable(feature = "cstr_internals", issue = "none")]
733-
#[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")]
733+
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0"))]
734734
#[rustc_allow_const_fn_unstable(const_eval_select)]
735735
const unsafe fn strlen(ptr: *const c_char) -> usize {
736736
const fn strlen_ct(s: *const c_char) -> usize {

0 commit comments

Comments
 (0)