Rollup merge of #77203 - ecstatic-morse:const-stability-attr-checks, r=oli-obk
Check for missing const-stability attributes in `rustc_passes` Currently, this happens as a side effect of `is_min_const_fn`, which is non-obvious. Also adds a test for this case, since we didn't seem to have one before.
This commit is contained in:
commit
9f086fcb00
5 changed files with 52 additions and 11 deletions
|
@ -50,7 +50,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||||
None => {
|
None => {
|
||||||
if let Some(stab) = tcx.lookup_stability(def_id) {
|
if let Some(stab) = tcx.lookup_stability(def_id) {
|
||||||
if stab.level.is_stable() {
|
if stab.level.is_stable() {
|
||||||
tcx.sess.span_err(
|
tcx.sess.delay_span_bug(
|
||||||
tcx.def_span(def_id),
|
tcx.def_span(def_id),
|
||||||
"stable const functions must have either `rustc_const_stable` or \
|
"stable const functions must have either `rustc_const_stable` or \
|
||||||
`rustc_const_unstable` attribute",
|
`rustc_const_unstable` attribute",
|
||||||
|
|
|
@ -204,9 +204,6 @@ impl Validator<'mir, 'tcx> {
|
||||||
pub fn check_body(&mut self) {
|
pub fn check_body(&mut self) {
|
||||||
let ConstCx { tcx, body, def_id, .. } = *self.ccx;
|
let ConstCx { tcx, body, def_id, .. } = *self.ccx;
|
||||||
|
|
||||||
// HACK: This function has side-effects???? Make sure we call it.
|
|
||||||
let _ = crate::const_eval::is_min_const_fn(tcx, def_id.to_def_id());
|
|
||||||
|
|
||||||
// The local type and predicate checks are not free and only relevant for `const fn`s.
|
// The local type and predicate checks are not free and only relevant for `const fn`s.
|
||||||
if self.const_kind() == hir::ConstContext::ConstFn {
|
if self.const_kind() == hir::ConstContext::ConstFn {
|
||||||
// Prevent const trait methods from being annotated as `stable`.
|
// Prevent const trait methods from being annotated as `stable`.
|
||||||
|
|
|
@ -459,6 +459,21 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
|
||||||
self.tcx.sess.span_err(span, &format!("{} has missing stability attribute", descr));
|
self.tcx.sess.span_err(span, &format!("{} has missing stability attribute", descr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_missing_const_stability(&self, hir_id: HirId, span: Span) {
|
||||||
|
let stab_map = self.tcx.stability();
|
||||||
|
let stab = stab_map.local_stability(hir_id);
|
||||||
|
if stab.map_or(false, |stab| stab.level.is_stable()) {
|
||||||
|
let const_stab = stab_map.local_const_stability(hir_id);
|
||||||
|
if const_stab.is_none() {
|
||||||
|
self.tcx.sess.span_err(
|
||||||
|
span,
|
||||||
|
"`#[stable]` const functions must also be either \
|
||||||
|
`#[rustc_const_stable]` or `#[rustc_const_unstable]`",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
|
impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
|
||||||
|
@ -469,14 +484,23 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
|
fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
|
||||||
match i.kind {
|
// Inherent impls and foreign modules serve only as containers for other items,
|
||||||
// Inherent impls and foreign modules serve only as containers for other items,
|
// they don't have their own stability. They still can be annotated as unstable
|
||||||
// they don't have their own stability. They still can be annotated as unstable
|
// and propagate this unstability to children, but this annotation is completely
|
||||||
// and propagate this unstability to children, but this annotation is completely
|
// optional. They inherit stability from their parents when unannotated.
|
||||||
// optional. They inherit stability from their parents when unannotated.
|
if !matches!(
|
||||||
hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {}
|
i.kind,
|
||||||
|
hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..)
|
||||||
|
) {
|
||||||
|
self.check_missing_stability(i.hir_id, i.span);
|
||||||
|
}
|
||||||
|
|
||||||
_ => self.check_missing_stability(i.hir_id, i.span),
|
// Ensure `const fn` that are `stable` have one of `rustc_const_unstable` or
|
||||||
|
// `rustc_const_stable`.
|
||||||
|
if self.tcx.features().staged_api
|
||||||
|
&& matches!(&i.kind, hir::ItemKind::Fn(sig, ..) if sig.header.is_const())
|
||||||
|
{
|
||||||
|
self.check_missing_const_stability(i.hir_id, i.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
intravisit::walk_item(self, i)
|
intravisit::walk_item(self, i)
|
||||||
|
|
12
src/test/ui/stability-attribute/missing-const-stability.rs
Normal file
12
src/test/ui/stability-attribute/missing-const-stability.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#![feature(staged_api)]
|
||||||
|
|
||||||
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
|
#[stable(feature = "foo", since = "1.0.0")]
|
||||||
|
pub const fn foo() {}
|
||||||
|
//~^ ERROR rustc_const_stable
|
||||||
|
|
||||||
|
#[unstable(feature = "bar", issue = "none")]
|
||||||
|
pub const fn bar() {} // ok
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,8 @@
|
||||||
|
error: `#[stable]` const functions must also be either `#[rustc_const_stable]` or `#[rustc_const_unstable]`
|
||||||
|
--> $DIR/missing-const-stability.rs:6:1
|
||||||
|
|
|
||||||
|
LL | pub const fn foo() {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue