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 e968081

Browse files
committedNov 10, 2024
ensure that all publicly reachable const fn have const stability info
1 parent 686eeb8 commit e968081

File tree

12 files changed

+174
-201
lines changed

12 files changed

+174
-201
lines changed
 

‎compiler/rustc_attr/src/builtin.rs‎

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ use rustc_session::lint::BuiltinLintDiag;
1616
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
1717
use rustc_session::parse::feature_err;
1818
use rustc_session::{RustcVersion, Session};
19+
use rustc_span::Span;
1920
use rustc_span::hygiene::Transparency;
2021
use rustc_span::symbol::{Symbol, kw, sym};
21-
use rustc_span::{DUMMY_SP, Span};
2222

2323
use crate::fluent_generated;
2424
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
@@ -92,9 +92,7 @@ impl Stability {
9292
#[derive(HashStable_Generic)]
9393
pub struct ConstStability {
9494
pub level: StabilityLevel,
95-
/// This can be `None` for functions that do not have an explicit const feature.
96-
/// We still track them for recursive const stability checks.
97-
pub feature: Option<Symbol>,
95+
pub feature: Symbol,
9896
/// This is true iff the `const_stable_indirect` attribute is present.
9997
pub const_stable_indirect: bool,
10098
/// whether the function has a `#[rustc_promotable]` attribute
@@ -272,22 +270,19 @@ pub fn find_stability(
272270

273271
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
274272
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
275-
///
276-
/// `is_const_fn` indicates whether this is a function marked as `const`.
277273
pub fn find_const_stability(
278274
sess: &Session,
279275
attrs: &[Attribute],
280276
item_sp: Span,
281-
is_const_fn: bool,
282277
) -> Option<(ConstStability, Span)> {
283278
let mut const_stab: Option<(ConstStability, Span)> = None;
284279
let mut promotable = false;
285-
let mut const_stable_indirect = None;
280+
let mut const_stable_indirect = false;
286281

287282
for attr in attrs {
288283
match attr.name_or_empty() {
289284
sym::rustc_promotable => promotable = true,
290-
sym::rustc_const_stable_indirect => const_stable_indirect = Some(attr.span),
285+
sym::rustc_const_stable_indirect => const_stable_indirect = true,
291286
sym::rustc_const_unstable => {
292287
if const_stab.is_some() {
293288
sess.dcx()
@@ -299,7 +294,7 @@ pub fn find_const_stability(
299294
const_stab = Some((
300295
ConstStability {
301296
level,
302-
feature: Some(feature),
297+
feature,
303298
const_stable_indirect: false,
304299
promotable: false,
305300
},
@@ -317,7 +312,7 @@ pub fn find_const_stability(
317312
const_stab = Some((
318313
ConstStability {
319314
level,
320-
feature: Some(feature),
315+
feature,
321316
const_stable_indirect: false,
322317
promotable: false,
323318
},
@@ -340,7 +335,7 @@ pub fn find_const_stability(
340335
}
341336
}
342337
}
343-
if const_stable_indirect.is_some() {
338+
if const_stable_indirect {
344339
match &mut const_stab {
345340
Some((stab, _)) => {
346341
if stab.is_const_unstable() {
@@ -351,32 +346,13 @@ pub fn find_const_stability(
351346
})
352347
}
353348
}
354-
_ => {}
349+
_ => {
350+
// This function has no const stability attribute, but has `const_stable_indirect`.
351+
// We ignore that; unmarked functions are subject to recursive const stability
352+
// checks by default so we do carry out the user's intent.
353+
}
355354
}
356355
}
357-
// Make sure if `const_stable_indirect` is present, that is recorded. Also make sure all `const
358-
// fn` get *some* marker, since we are a staged_api crate and therefore will do recursive const
359-
// stability checks for them. We need to do this because the default for whether an unmarked
360-
// function enforces recursive stability differs between staged-api crates and force-unmarked
361-
// crates: in force-unmarked crates, only functions *explicitly* marked `const_stable_indirect`
362-
// enforce recursive stability. Therefore when `lookup_const_stability` is `None`, we have to
363-
// assume the function does not have recursive stability. All functions that *do* have recursive
364-
// stability must explicitly record this, and so that's what we do for all `const fn` in a
365-
// staged_api crate.
366-
if (is_const_fn || const_stable_indirect.is_some()) && const_stab.is_none() {
367-
let c = ConstStability {
368-
feature: None,
369-
const_stable_indirect: const_stable_indirect.is_some(),
370-
promotable: false,
371-
level: StabilityLevel::Unstable {
372-
reason: UnstableReason::Default,
373-
issue: None,
374-
is_soft: false,
375-
implied_by: None,
376-
},
377-
};
378-
const_stab = Some((c, const_stable_indirect.unwrap_or(DUMMY_SP)));
379-
}
380356

381357
const_stab
382358
}
@@ -394,7 +370,7 @@ pub fn unmarked_crate_const_stab(
394370
let const_stable_indirect =
395371
attrs.iter().any(|a| a.name_or_empty() == sym::rustc_const_stable_indirect);
396372
ConstStability {
397-
feature: Some(regular_stab.feature),
373+
feature: regular_stab.feature,
398374
const_stable_indirect,
399375
promotable: false,
400376
level: regular_stab.level,

‎compiler/rustc_const_eval/src/check_consts/check.rs‎

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -709,24 +709,26 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
709709

710710
// Intrinsics are language primitives, not regular calls, so treat them separately.
711711
if let Some(intrinsic) = tcx.intrinsic(callee) {
712+
if !tcx.is_const_fn(callee) {
713+
// Non-const intrinsic.
714+
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
715+
// If we allowed this, we're in miri-unleashed mode, so we might
716+
// as well skip the remaining checks.
717+
return;
718+
}
712719
// We use `intrinsic.const_stable` to determine if this can be safely exposed to
713720
// stable code, rather than `const_stable_indirect`. This is to make
714721
// `#[rustc_const_stable_indirect]` an attribute that is always safe to add.
715722
// We also ask is_safe_to_expose_on_stable_const_fn; this determines whether the intrinsic
716723
// fallback body is safe to expose on stable.
717724
let is_const_stable = intrinsic.const_stable
718725
|| (!intrinsic.must_be_overridden
719-
&& tcx.is_const_fn(callee)
720726
&& is_safe_to_expose_on_stable_const_fn(tcx, callee));
721727
match tcx.lookup_const_stability(callee) {
722728
None => {
723-
// Non-const intrinsic.
724-
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
725-
}
726-
Some(ConstStability { feature: None, .. }) => {
727-
// Intrinsic does not need a separate feature gate (we rely on the
728-
// regular stability checker). However, we have to worry about recursive
729-
// const stability.
729+
// This doesn't need a separate const-stability check -- const-stability equals
730+
// regular stability, and regular stability is checked separately.
731+
// However, we *do* have to worry about *recursive* const stability.
730732
if !is_const_stable && self.enforce_recursive_const_stability() {
731733
self.dcx().emit_err(errors::UnmarkedIntrinsicExposed {
732734
span: self.span,
@@ -735,8 +737,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
735737
}
736738
}
737739
Some(ConstStability {
738-
feature: Some(feature),
739740
level: StabilityLevel::Unstable { .. },
741+
feature,
740742
..
741743
}) => {
742744
self.check_op(ops::IntrinsicUnstable {
@@ -773,7 +775,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
773775
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
774776
// All good.
775777
}
776-
None | Some(ConstStability { feature: None, .. }) => {
778+
None => {
777779
// This doesn't need a separate const-stability check -- const-stability equals
778780
// regular stability, and regular stability is checked separately.
779781
// However, we *do* have to worry about *recursive* const stability.
@@ -787,8 +789,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
787789
}
788790
}
789791
Some(ConstStability {
790-
feature: Some(feature),
791792
level: StabilityLevel::Unstable { implied_by: implied_feature, .. },
793+
feature,
792794
..
793795
}) => {
794796
// An unstable const fn with a feature gate.

‎compiler/rustc_const_eval/src/check_consts/mod.rs‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,15 @@ pub fn is_safe_to_expose_on_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> b
110110

111111
match tcx.lookup_const_stability(def_id) {
112112
None => {
113-
// Only marked functions can be trusted. Note that this may be a function in a
114-
// non-staged-API crate where no recursive checks were done!
115-
false
113+
// In a `staged_api` crate, we do enforce recursive const stability for all unmarked
114+
// functions, so we can trust local functions. But in another crate we don't know which
115+
// rules were applied, so we can't trust that.
116+
def_id.is_local() && tcx.features().staged_api()
116117
}
117118
Some(stab) => {
118-
// We consider things safe-to-expose if they are stable, if they don't have any explicit
119-
// const stability attribute, or if they are marked as `const_stable_indirect`.
120-
stab.is_const_stable() || stab.feature.is_none() || stab.const_stable_indirect
119+
// We consider things safe-to-expose if they are stable or if they are marked as
120+
// `const_stable_indirect`.
121+
stab.is_const_stable() || stab.const_stable_indirect
121122
}
122123
}
123124
}

‎compiler/rustc_expand/src/base.rs‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -866,9 +866,7 @@ impl SyntaxExtension {
866866
})
867867
.unwrap_or_else(|| (None, helper_attrs));
868868
let stability = attr::find_stability(sess, attrs, span);
869-
// We set `is_const_fn` false to avoid getting any implicit const stability.
870-
let const_stability =
871-
attr::find_const_stability(sess, attrs, span, /* is_const_fn */ false);
869+
let const_stability = attr::find_const_stability(sess, attrs, span);
872870
let body_stability = attr::find_body_stability(sess, attrs);
873871
if let Some((_, sp)) = const_stability {
874872
sess.dcx().emit_err(errors::MacroConstStability {

‎compiler/rustc_passes/src/stability.rs‎

Lines changed: 98 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_hir::def::{DefKind, Res};
1616
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
1717
use rustc_hir::hir_id::CRATE_HIR_ID;
1818
use rustc_hir::intravisit::{self, Visitor};
19-
use rustc_hir::{Constness, FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
19+
use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
2020
use rustc_middle::hir::nested_filter;
2121
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
2222
use rustc_middle::middle::privacy::EffectiveVisibilities;
@@ -166,68 +166,11 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
166166
return;
167167
}
168168

169+
// # Regular and body stability
170+
169171
let stab = attr::find_stability(self.tcx.sess, attrs, item_sp);
170-
let const_stab = attr::find_const_stability(
171-
self.tcx.sess,
172-
attrs,
173-
item_sp,
174-
fn_sig.is_some_and(|s| s.header.is_const()),
175-
);
176172
let body_stab = attr::find_body_stability(self.tcx.sess, attrs);
177173

178-
// If the current node is a function with const stability attributes (directly given or
179-
// implied), check if the function/method is const or the parent impl block is const.
180-
if let Some(fn_sig) = fn_sig
181-
&& !fn_sig.header.is_const()
182-
&& const_stab.is_some()
183-
{
184-
self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span });
185-
}
186-
187-
// If this is marked const *stable*, it must also be regular-stable.
188-
if let Some((const_stab, const_span)) = const_stab
189-
&& let Some(fn_sig) = fn_sig
190-
&& const_stab.is_const_stable()
191-
&& !stab.is_some_and(|(s, _)| s.is_stable())
192-
{
193-
self.tcx
194-
.dcx()
195-
.emit_err(errors::ConstStableNotStable { fn_sig_span: fn_sig.span, const_span });
196-
}
197-
198-
// Stable *language* features shouldn't be used as unstable library features.
199-
// (Not doing this for stable library features is checked by tidy.)
200-
if let Some((
201-
ConstStability { level: Unstable { .. }, feature: Some(feature), .. },
202-
const_span,
203-
)) = const_stab
204-
{
205-
if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() {
206-
self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature {
207-
span: const_span,
208-
item_sp,
209-
});
210-
}
211-
}
212-
213-
let const_stab = const_stab.map(|(const_stab, _span)| {
214-
self.index.const_stab_map.insert(def_id, const_stab);
215-
const_stab
216-
});
217-
218-
// `impl const Trait for Type` items forward their const stability to their
219-
// immediate children.
220-
// FIXME(const_trait_impl): how is this supposed to interact with `#[rustc_const_stable_indirect]`?
221-
// Currently, once that is set, we do not inherit anything from the parent any more.
222-
if const_stab.is_none() {
223-
debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab);
224-
if let Some(parent) = self.parent_const_stab {
225-
if parent.is_const_unstable() {
226-
self.index.const_stab_map.insert(def_id, parent);
227-
}
228-
}
229-
}
230-
231174
if let Some((depr, span)) = &depr
232175
&& depr.is_since_rustc_version()
233176
&& stab.is_none()
@@ -294,15 +237,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
294237
self.index.implications.insert(implied_by, feature);
295238
}
296239

297-
if let Some(ConstStability {
298-
level: Unstable { implied_by: Some(implied_by), .. },
299-
feature,
300-
..
301-
}) = const_stab
302-
{
303-
self.index.implications.insert(implied_by, feature.unwrap());
304-
}
305-
306240
self.index.stab_map.insert(def_id, stab);
307241
stab
308242
});
@@ -316,6 +250,91 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
316250
}
317251
}
318252

253+
let final_stab = self.index.stab_map.get(&def_id);
254+
255+
// # Const stability
256+
257+
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item_sp);
258+
259+
// If the current node is a function with const stability attributes (directly given or
260+
// implied), check if the function/method is const.
261+
if let Some(fn_sig) = fn_sig
262+
&& !fn_sig.header.is_const()
263+
&& const_stab.is_some()
264+
{
265+
self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span });
266+
}
267+
268+
// If this is marked const *stable*, it must also be regular-stable.
269+
if let Some((const_stab, const_span)) = const_stab
270+
&& let Some(fn_sig) = fn_sig
271+
&& const_stab.is_const_stable()
272+
&& !stab.is_some_and(|s| s.is_stable())
273+
{
274+
self.tcx
275+
.dcx()
276+
.emit_err(errors::ConstStableNotStable { fn_sig_span: fn_sig.span, const_span });
277+
}
278+
279+
// Stable *language* features shouldn't be used as unstable library features.
280+
// (Not doing this for stable library features is checked by tidy.)
281+
if let Some((ConstStability { level: Unstable { .. }, feature, .. }, const_span)) =
282+
const_stab
283+
{
284+
if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() {
285+
self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature {
286+
span: const_span,
287+
item_sp,
288+
});
289+
}
290+
}
291+
292+
// After checking the immediate attributes, get rid of the span and compute implied
293+
// const stability: inherit feature gate from regular stability.
294+
let mut const_stab = const_stab.map(|(stab, _span)| stab);
295+
296+
// If this is a const fn but not annotated with stability markers, see if we can inherit regular stability.
297+
if fn_sig.is_some_and(|s| s.header.is_const()) && const_stab.is_none() &&
298+
// We only ever inherit unstable features.
299+
let Some(inherit_regular_stab) =
300+
final_stab.filter(|s| s.is_unstable())
301+
{
302+
const_stab = Some(ConstStability {
303+
// We subject these implicitly-const functions to recursive const stability.
304+
const_stable_indirect: true,
305+
promotable: false,
306+
level: inherit_regular_stab.level,
307+
feature: inherit_regular_stab.feature,
308+
});
309+
}
310+
311+
// Now that everything is computed, insert it into the table.
312+
const_stab.inspect(|const_stab| {
313+
self.index.const_stab_map.insert(def_id, *const_stab);
314+
});
315+
316+
if let Some(ConstStability {
317+
level: Unstable { implied_by: Some(implied_by), .. },
318+
feature,
319+
..
320+
}) = const_stab
321+
{
322+
self.index.implications.insert(implied_by, feature);
323+
}
324+
325+
// `impl const Trait for Type` items forward their const stability to their
326+
// immediate children.
327+
// FIXME(const_trait_impl): how is this supposed to interact with `#[rustc_const_stable_indirect]`?
328+
// Currently, once that is set, we do not inherit anything from the parent any more.
329+
if const_stab.is_none() {
330+
debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab);
331+
if let Some(parent) = self.parent_const_stab {
332+
if parent.is_const_unstable() {
333+
self.index.const_stab_map.insert(def_id, parent);
334+
}
335+
}
336+
}
337+
319338
self.recurse_with_stability_attrs(
320339
depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
321340
stab,
@@ -570,13 +589,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
570589
}
571590
}
572591

573-
fn check_missing_or_wrong_const_stability(&self, def_id: LocalDefId, span: Span) {
574-
// The visitor runs for "unstable-if-unmarked" crates, but we don't yet support
575-
// that on the const side.
576-
if !self.tcx.features().staged_api() {
577-
return;
578-
}
579-
592+
fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) {
580593
// if the const impl is derived using the `derive_const` attribute,
581594
// then it would be "stable" at least for the impl.
582595
// We gate usages of it using `feature(const_trait_impl)` anyways
@@ -587,12 +600,12 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
587600

588601
let is_const = self.tcx.is_const_fn(def_id.to_def_id())
589602
|| self.tcx.is_const_trait_impl(def_id.to_def_id());
590-
let is_stable =
591-
self.tcx.lookup_stability(def_id).is_some_and(|stability| stability.level.is_stable());
592-
let missing_const_stability_attribute =
593-
self.tcx.lookup_const_stability(def_id).is_none_or(|s| s.feature.is_none());
594603

595-
if is_const && is_stable && missing_const_stability_attribute {
604+
// Reachable const fn must have a stability attribute.
605+
if is_const
606+
&& self.effective_visibilities.is_reachable(def_id)
607+
&& self.tcx.lookup_const_stability(def_id).is_none()
608+
{
596609
let descr = self.tcx.def_descr(def_id.to_def_id());
597610
self.tcx.dcx().emit_err(errors::MissingConstStabAttr { span, descr });
598611
}
@@ -620,7 +633,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
620633
}
621634

622635
// Ensure stable `const fn` have a const stability attribute.
623-
self.check_missing_or_wrong_const_stability(i.owner_id.def_id, i.span);
636+
self.check_missing_const_stability(i.owner_id.def_id, i.span);
624637

625638
intravisit::walk_item(self, i)
626639
}
@@ -634,7 +647,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
634647
let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id());
635648
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
636649
self.check_missing_stability(ii.owner_id.def_id, ii.span);
637-
self.check_missing_or_wrong_const_stability(ii.owner_id.def_id, ii.span);
650+
self.check_missing_const_stability(ii.owner_id.def_id, ii.span);
638651
}
639652
intravisit::walk_impl_item(self, ii);
640653
}
@@ -765,23 +778,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
765778
// For implementations of traits, check the stability of each item
766779
// individually as it's possible to have a stable trait with unstable
767780
// items.
768-
hir::ItemKind::Impl(hir::Impl {
769-
constness,
770-
of_trait: Some(ref t),
771-
self_ty,
772-
items,
773-
..
774-
}) => {
781+
hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
775782
let features = self.tcx.features();
776783
if features.staged_api() {
777784
let attrs = self.tcx.hir().attrs(item.hir_id());
778785
let stab = attr::find_stability(self.tcx.sess, attrs, item.span);
779-
let const_stab = attr::find_const_stability(
780-
self.tcx.sess,
781-
attrs,
782-
item.span,
783-
matches!(constness, Constness::Const),
784-
);
786+
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item.span);
785787

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

‎src/librustdoc/html/render/mod.rs‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,9 +1010,7 @@ fn render_stability_since_raw_with_extra(
10101010
// don't display const unstable if entirely unstable
10111011
None
10121012
} else {
1013-
let unstable = if let Some(n) = issue
1014-
&& let Some(feature) = feature
1015-
{
1013+
let unstable = if let Some(n) = issue {
10161014
format!(
10171015
"<a \
10181016
href=\"https://github.com/rust-lang/rust/issues/{n}\" \

‎src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -393,12 +393,8 @@ fn is_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
393393

394394
msrv.meets(const_stab_rust_version)
395395
} else {
396-
// Unstable const fn, check if the feature is enabled. We need both the regular stability
397-
// feature and (if set) the const stability feature to const-call this function.
398-
let stab = tcx.lookup_stability(def_id);
399-
let is_enabled = stab.is_some_and(|s| s.is_stable() || tcx.features().enabled(s.feature))
400-
&& const_stab.feature.is_none_or(|f| tcx.features().enabled(f));
401-
is_enabled && msrv.current().is_none()
396+
// Unstable const fn, check if the feature is enabled.
397+
tcx.features().enabled(const_stab.feature) && msrv.current().is_none()
402398
}
403399
})
404400
}

‎tests/ui/consts/const-unstable-intrinsic.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ const fn const_main() {
1616
unsafe {
1717
unstable_intrinsic::size_of_val(&x);
1818
//~^ERROR: unstable library feature `unstable`
19-
//~|ERROR: cannot be (indirectly) exposed to stable
19+
//~|ERROR: not yet stable as a const intrinsic
2020
unstable_intrinsic::min_align_of_val(&x);
2121
//~^ERROR: unstable library feature `unstable`
2222
//~|ERROR: not yet stable as a const intrinsic
2323

2424
size_of_val(&x);
25-
//~^ERROR: cannot be (indirectly) exposed to stable
25+
//~^ERROR: cannot use `#[feature(local)]`
2626
min_align_of_val(&x);
2727
//~^ERROR: cannot use `#[feature(local)]`
2828
}
@@ -59,6 +59,6 @@ mod fallback {
5959
#[rustc_intrinsic]
6060
const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
6161
super::size_of_val(src);
62-
//~^ ERROR cannot be (indirectly) exposed to stable
62+
//~^ ERROR cannot use `#[feature(local)]`
6363
}
6464
}

‎tests/ui/consts/const-unstable-intrinsic.stderr‎

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ LL | unstable_intrinsic::min_align_of_val(&x);
1818
= help: add `#![feature(unstable)]` to the crate attributes to enable
1919
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2020

21-
error: intrinsic `unstable_intrinsic::size_of_val` cannot be (indirectly) exposed to stable
21+
error: `size_of_val` is not yet stable as a const intrinsic
2222
--> $DIR/const-unstable-intrinsic.rs:17:9
2323
|
2424
LL | unstable_intrinsic::size_of_val(&x);
2525
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2626
|
27-
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
27+
= help: add `#![feature(unstable)]` to the crate attributes to enable
2828

2929
error: `min_align_of_val` is not yet stable as a const intrinsic
3030
--> $DIR/const-unstable-intrinsic.rs:20:9
@@ -34,13 +34,22 @@ LL | unstable_intrinsic::min_align_of_val(&x);
3434
|
3535
= help: add `#![feature(unstable)]` to the crate attributes to enable
3636

37-
error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable
37+
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
3838
--> $DIR/const-unstable-intrinsic.rs:24:9
3939
|
4040
LL | size_of_val(&x);
4141
| ^^^^^^^^^^^^^^^
4242
|
43-
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
43+
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
44+
|
45+
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
46+
LL | const fn const_main() {
47+
|
48+
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
49+
|
50+
LL + #[rustc_allow_const_fn_unstable(local)]
51+
LL | const fn const_main() {
52+
|
4453

4554
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
4655
--> $DIR/const-unstable-intrinsic.rs:26:9
@@ -67,13 +76,22 @@ LL | unsafe { copy(src, dst, count) }
6776
|
6877
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
6978

70-
error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable
79+
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
7180
--> $DIR/const-unstable-intrinsic.rs:61:9
7281
|
7382
LL | super::size_of_val(src);
7483
| ^^^^^^^^^^^^^^^^^^^^^^^
7584
|
76-
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
85+
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
86+
|
87+
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
88+
LL | const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
89+
|
90+
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
91+
|
92+
LL + #[rustc_allow_const_fn_unstable(local)]
93+
LL | const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
94+
|
7795

7896
error: aborting due to 8 previous errors
7997

‎tests/ui/consts/rustc-const-stability-require-const.rs‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,3 @@ const fn barfoo_unmarked() {}
5656
#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
5757
pub const fn barfoo_unstable() {}
5858
//~^ ERROR can only be applied to functions that are declared `#[stable]`
59-
60-
// `#[rustc_const_stable_indirect]` also requires a const fn
61-
#[rustc_const_stable_indirect]
62-
#[unstable(feature = "unstable", issue = "none")]
63-
pub fn not_a_const_fn() {}
64-
//~^ ERROR require the function or method to be `const`

‎tests/ui/consts/rustc-const-stability-require-const.stderr‎

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,5 @@ LL | #[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
8686
LL | pub const fn barfoo_unstable() {}
8787
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8888

89-
error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
90-
--> $DIR/rustc-const-stability-require-const.rs:63:1
91-
|
92-
LL | pub fn not_a_const_fn() {}
93-
| ^^^^^^^^^^^^^^^^^^^^^^^
94-
|
95-
help: make the function or method const
96-
--> $DIR/rustc-const-stability-require-const.rs:63:1
97-
|
98-
LL | pub fn not_a_const_fn() {}
99-
| ^^^^^^^^^^^^^^^^^^^^^^^
100-
101-
error: aborting due to 9 previous errors
89+
error: aborting due to 8 previous errors
10290

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
error: can't mark as unstable using an already stable feature
2-
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
2+
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
33
|
4+
LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
46
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
67
LL | const fn my_fun() {}
78
| -------------------- the stability attribute annotates this item
89
|
910
help: consider removing the attribute
10-
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
11+
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
1112
|
12-
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1415

1516
error: can't mark as unstable using an already stable feature
16-
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
17+
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
1718
|
18-
LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
19-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
2019
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
2121
LL | const fn my_fun() {}
2222
| -------------------- the stability attribute annotates this item
2323
|
2424
help: consider removing the attribute
25-
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
25+
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
2626
|
27-
LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
28-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27+
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
28+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2929

3030
error: aborting due to 2 previous errors
3131

0 commit comments

Comments
 (0)
Please sign in to comment.