Skip to content

Commit

Permalink
only use rustc_const_stable on functions that are actually stable, an…
Browse files Browse the repository at this point in the history
…d inherit const feature gate from other unstable gates

With this, we need fewer rustc_const_(un)stable annotations
  • Loading branch information
RalfJung committed Oct 7, 2024
1 parent b630e50 commit 203ca72
Show file tree
Hide file tree
Showing 24 changed files with 342 additions and 181 deletions.
9 changes: 8 additions & 1 deletion compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,14 @@ pub fn find_stability(

/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
///
/// `inherited_feature_gate` says which feature gate this function should be under if it doesn't
/// declare a gate itself, but has `#[rustc_const_stable_indirect]`.
pub fn find_const_stability(
sess: &Session,
attrs: &[Attribute],
item_sp: Span,
inherited_feature_gate: Option<Symbol>,
) -> Option<(ConstStability, Span)> {
let mut const_stab: Option<(ConstStability, Span)> = None;
let mut promotable = false;
Expand Down Expand Up @@ -351,8 +355,11 @@ pub fn find_const_stability(
}
}
_ => {
// `#[rustc_const_stable_indirect]` implicitly makes the function unstably const,
// inheriting the feature gate from `#[unstable]` if it xists, or without any
// feature gate otherwise.
let c = ConstStability {
feature: None,
feature: inherited_feature_gate,
safe_to_expose_on_stable: true,
promotable: false,
level: StabilityLevel::Unstable {
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,11 @@ impl SyntaxExtension {
})
.unwrap_or_else(|| (None, helper_attrs));
let stability = attr::find_stability(sess, attrs, span);
let const_stability = attr::find_const_stability(sess, attrs, span);
// FIXME: this will give a different result than the normal stability computation, since we
// don't inherit stability from the parent. But that's true even for `stability` above so
// it's probably okay?
let const_stability =
attr::find_const_stability(sess, attrs, span, stability.map(|(s, _)| s.feature));
let body_stability = attr::find_body_stability(sess, attrs);
if let Some((_, sp)) = const_stability {
sess.dcx().emit_err(errors::MacroConstStability {
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ passes_collapse_debuginfo =
passes_confusables = attribute should be applied to an inherent method
.label = not an inherent method
passes_const_stable_not_stable =
attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`
.label = attribute specified here
passes_continue_labeled_block =
`continue` pointing to a labeled block
.label = labeled blocks cannot be `continue`'d
Expand Down Expand Up @@ -450,7 +454,7 @@ passes_may_dangle =
passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
passes_missing_const_err =
attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
.help = make the function or method const
.label = attribute specified here
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1544,6 +1544,7 @@ pub(crate) struct DuplicateFeatureErr {
pub span: Span,
pub feature: Symbol,
}

#[derive(Diagnostic)]
#[diag(passes_missing_const_err)]
pub(crate) struct MissingConstErr {
Expand All @@ -1554,6 +1555,15 @@ pub(crate) struct MissingConstErr {
pub const_span: Span,
}

#[derive(Diagnostic)]
#[diag(passes_const_stable_not_stable)]
pub(crate) struct ConstStableNotStable {
#[primary_span]
pub fn_sig_span: Span,
#[label]
pub const_span: Span,
}

#[derive(LintDiagnostic)]
pub(crate) enum MultipleDeadCodes<'tcx> {
#[diag(passes_dead_codes)]
Expand Down
59 changes: 47 additions & 12 deletions compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,19 +162,32 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
}

let stab = attr::find_stability(self.tcx.sess, attrs, item_sp);
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item_sp);
let const_stab = attr::find_const_stability(
self.tcx.sess,
attrs,
item_sp,
// Compute the feature gate we inherit if this
// doesn't have its own feature gate.
self.parent_const_stab.and_then(|c| c.feature).or_else(|| {
// Infer the const feature gate from the regular feature gate,
// but only if that regular gate is unstable.
if let Some((s, _)) = stab {
s.is_unstable().then_some(s.feature)
} else if inherit_deprecation.yes()
&& let Some(parent_stab) = self.parent_stab
&& parent_stab.is_unstable()
{
Some(parent_stab.feature)
} else {
None
}
}),
);
let body_stab = attr::find_body_stability(self.tcx.sess, attrs);
let mut const_span = None;

let const_stab = const_stab.map(|(const_stab, const_span_node)| {
self.index.const_stab_map.insert(def_id, const_stab);
const_span = Some(const_span_node);
const_stab
});

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

// If this is marked const *stable*, it must also be regular-stable.
if let Some((const_stab, const_span)) = const_stab
&& let Some(fn_sig) = fn_sig
&& const_stab.is_const_stable()
&& !stab.is_some_and(|(s, _)| s.is_stable())
{
self.tcx
.dcx()
.emit_err(errors::ConstStableNotStable { fn_sig_span: fn_sig.span, const_span });
}

let const_stab = const_stab.map(|(const_stab, _span)| {
self.index.const_stab_map.insert(def_id, const_stab);
const_stab
});

// `impl const Trait for Type` items forward their const stability to their
// immediate children.
if const_stab.is_none() {
Expand Down Expand Up @@ -274,8 +303,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
}
}

// Every `const fn` that has stability should also have const-stability.

self.recurse_with_stability_attrs(
depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
stab,
Expand Down Expand Up @@ -724,7 +751,15 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
if features.staged_api {
let attrs = self.tcx.hir().attrs(item.hir_id());
let stab = attr::find_stability(self.tcx.sess, attrs, item.span);
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item.span);
// FIXME: this will give a different result than the normal stability
// computation, since we don't inherit stability from the parent. But that's
// true even for `stab` above so it's probably okay?
let const_stab = attr::find_const_stability(
self.tcx.sess,
attrs,
item.span,
stab.map(|(s, _)| s.feature),
);

// If this impl block has an #[unstable] attribute, give an
// error if all involved types and traits are stable, because
Expand Down
2 changes: 0 additions & 2 deletions library/core/src/alloc/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,6 @@ impl Layout {
/// This can return at most `Alignment::MAX` (aka `isize::MAX + 1`)
/// because the original size is at most `isize::MAX`.
#[inline]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
const fn size_rounded_up_to_custom_align(&self, align: Alignment) -> usize {
// SAFETY:
// Rounded up value is:
Expand Down Expand Up @@ -507,7 +506,6 @@ impl Layout {
return inner(T::LAYOUT, n);

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

Expand Down
6 changes: 3 additions & 3 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,11 @@ enum FromBytesWithNulErrorKind {

// FIXME: const stability attributes should not be required here, I think
impl FromBytesWithNulError {
#[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))]
const fn interior_nul(pos: usize) -> FromBytesWithNulError {
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) }
}
#[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))]
const fn not_nul_terminated() -> FromBytesWithNulError {
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated }
}
Expand Down Expand Up @@ -730,7 +730,7 @@ impl AsRef<CStr> for CStr {
/// located within `isize::MAX` from `ptr`.
#[inline]
#[unstable(feature = "cstr_internals", issue = "none")]
#[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")]
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0"))]
#[rustc_allow_const_fn_unstable(const_eval_select)]
const unsafe fn strlen(ptr: *const c_char) -> usize {
const fn strlen_ct(s: *const c_char) -> usize {
Expand Down
1 change: 1 addition & 0 deletions library/core/src/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@ pub const fn black_box<T>(dummy: T) -> T {
/// ```
#[unstable(feature = "hint_must_use", issue = "94745")]
#[rustc_const_unstable(feature = "hint_must_use", issue = "94745")]
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // exposed via macro
#[must_use] // <-- :)
#[inline(always)]
pub const fn must_use<T>(value: T) -> T {
Expand Down
Loading

0 comments on commit 203ca72

Please sign in to comment.