From 61d86fa06ca4d7c93109fc857300abbd25a19a0a Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 25 Sep 2020 13:48:48 -0700 Subject: [PATCH 1/4] Check for missing const-stability attributes in `stability` This used to happen as a side-effect of `is_min_const_fn`, which was subtle. --- compiler/rustc_passes/src/stability.rs | 38 +++++++++++++++++++++----- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 4ca52f405fb94..24972b5cc6a6f 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -368,6 +368,21 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { 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> { @@ -378,14 +393,23 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'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, - // 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 - // optional. They inherit stability from their parents when unannotated. - hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {} + // 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 + // and propagate this unstability to children, but this annotation is completely + // optional. They inherit stability from their parents when unannotated. + if !matches!( + 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) From 11bfc60a4b5fa111527a69e5f511cb69ae5325af Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 25 Sep 2020 14:08:44 -0700 Subject: [PATCH 2/4] Change error in `fn_queries` to `delay_span_bug` This should be caught by the new check in `rustc_passes`. At some point, this function will be removed entirely. --- compiler/rustc_mir/src/const_eval/fn_queries.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/const_eval/fn_queries.rs b/compiler/rustc_mir/src/const_eval/fn_queries.rs index 9ef63b3322dd5..1db1f6ceedac5 100644 --- a/compiler/rustc_mir/src/const_eval/fn_queries.rs +++ b/compiler/rustc_mir/src/const_eval/fn_queries.rs @@ -50,7 +50,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { None => { if let Some(stab) = tcx.lookup_stability(def_id) { if stab.level.is_stable() { - tcx.sess.span_err( + tcx.sess.delay_span_bug( tcx.def_span(def_id), "stable const functions must have either `rustc_const_stable` or \ `rustc_const_unstable` attribute", From 76c6f2dc3f0769653e80c58bd3f288594fa11dc6 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 25 Sep 2020 13:50:18 -0700 Subject: [PATCH 3/4] No need to call `is_min_const_fn` for side-effects --- compiler/rustc_mir/src/transform/check_consts/validation.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index dc28ba46d7cbb..3a5ae4c8348f5 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -204,9 +204,6 @@ impl Validator<'mir, 'tcx> { pub fn check_body(&mut self) { 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. if self.const_kind() == hir::ConstContext::ConstFn { // Prevent const trait methods from being annotated as `stable`. From 6ce178f60eec86cfd9245e6289598938df519359 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 25 Sep 2020 13:51:52 -0700 Subject: [PATCH 4/4] Test for missing const-stability attributes --- .../stability-attribute/missing-const-stability.rs | 12 ++++++++++++ .../missing-const-stability.stderr | 8 ++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/test/ui/stability-attribute/missing-const-stability.rs create mode 100644 src/test/ui/stability-attribute/missing-const-stability.stderr diff --git a/src/test/ui/stability-attribute/missing-const-stability.rs b/src/test/ui/stability-attribute/missing-const-stability.rs new file mode 100644 index 0000000000000..7d499c611a43c --- /dev/null +++ b/src/test/ui/stability-attribute/missing-const-stability.rs @@ -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() {} diff --git a/src/test/ui/stability-attribute/missing-const-stability.stderr b/src/test/ui/stability-attribute/missing-const-stability.stderr new file mode 100644 index 0000000000000..450a5303fd86f --- /dev/null +++ b/src/test/ui/stability-attribute/missing-const-stability.stderr @@ -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 +