From 41f84c258ad5fc12775e25aafe4d67e3304a5bda Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Wed, 17 Nov 2021 21:06:17 -0500 Subject: [PATCH] Require const stability on all stable const items This was supposed to be the case previously, but a missed method call meant that trait impls were not checked. --- compiler/rustc_passes/src/stability.rs | 36 +++++++++---------- .../missing-const-stability.rs | 24 +++++++++---- .../missing-const-stability.stderr | 12 +++++-- 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 3521b6fc169..136059677c5 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -577,17 +577,21 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { } fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) { - let stab_map = self.tcx.stability(); - let stab = stab_map.local_stability(def_id); - if stab.map_or(false, |stab| stab.level.is_stable()) { - let const_stab = stab_map.local_const_stability(def_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]`", - ); - } + if !self.tcx.features().staged_api { + return; + } + + let is_const = self.tcx.is_const_fn(def_id.to_def_id()); + let is_stable = self + .tcx + .lookup_stability(def_id) + .map_or(false, |stability| stability.level.is_stable()); + let missing_const_stability_attribute = self.tcx.lookup_const_stability(def_id).is_none(); + let is_reachable = self.access_levels.is_reachable(def_id); + + if is_const && is_stable && missing_const_stability_attribute && is_reachable { + let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id()); + self.tcx.sess.span_err(span, &format!("{descr} has missing const stability attribute")); } } } @@ -612,13 +616,8 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { self.check_missing_stability(i.def_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.def_id, i.span); - } + // Ensure stable `const fn` have a const stability attribute. + self.check_missing_const_stability(i.def_id, i.span); intravisit::walk_item(self, i) } @@ -632,6 +631,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id()); if self.tcx.impl_trait_ref(impl_def_id).is_none() { self.check_missing_stability(ii.def_id, ii.span); + self.check_missing_const_stability(ii.def_id, ii.span); } intravisit::walk_impl_item(self, ii); } diff --git a/src/test/ui/stability-attribute/missing-const-stability.rs b/src/test/ui/stability-attribute/missing-const-stability.rs index 7d499c611a4..39af6e9e3b9 100644 --- a/src/test/ui/stability-attribute/missing-const-stability.rs +++ b/src/test/ui/stability-attribute/missing-const-stability.rs @@ -1,12 +1,24 @@ #![feature(staged_api)] +#![stable(feature = "stable", since = "1.0.0")] -#![stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "stable", since = "1.0.0")] +pub const fn foo() {} //~ ERROR function has missing const stability attribute -#[stable(feature = "foo", since = "1.0.0")] -pub const fn foo() {} -//~^ ERROR rustc_const_stable +#[unstable(feature = "unstable", issue = "none")] +pub const fn bar() {} // ok for now -#[unstable(feature = "bar", issue = "none")] -pub const fn bar() {} // ok +#[stable(feature = "stable", since = "1.0.0")] +pub struct Foo; +impl Foo { + #[stable(feature = "stable", since = "1.0.0")] + pub const fn foo() {} //~ ERROR associated function has missing const stability attribute + + #[unstable(feature = "unstable", issue = "none")] + pub const fn bar() {} // ok for now +} + +// FIXME When #![feature(const_trait_impl)] is stabilized, add tests for const +// trait impls. Right now, a "trait methods cannot be stable const fn" error is +// emitted, but that's not in the scope of this test. fn main() {} diff --git a/src/test/ui/stability-attribute/missing-const-stability.stderr b/src/test/ui/stability-attribute/missing-const-stability.stderr index 450a5303fd8..ee98e7b0e3f 100644 --- a/src/test/ui/stability-attribute/missing-const-stability.stderr +++ b/src/test/ui/stability-attribute/missing-const-stability.stderr @@ -1,8 +1,14 @@ -error: `#[stable]` const functions must also be either `#[rustc_const_stable]` or `#[rustc_const_unstable]` - --> $DIR/missing-const-stability.rs:6:1 +error: function has missing const stability attribute + --> $DIR/missing-const-stability.rs:5:1 | LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: associated function has missing const stability attribute + --> $DIR/missing-const-stability.rs:14:5 + | +LL | pub const fn foo() {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors