diff options
| author | Jacob Pratt <jacob@jhpratt.dev> | 2022-02-13 05:54:00 -0500 |
|---|---|---|
| committer | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2022-05-19 12:21:45 +0000 |
| commit | f0620c95038c1e586f5165d5d3be7cf009aaf387 (patch) | |
| tree | 0df4aedeb4c4593fca47616f7d209abea39224bf /compiler/rustc_const_eval | |
| parent | a9dd4cfa6b5398b945d3ad39e01bedb5d861ed60 (diff) | |
| download | rust-f0620c95038c1e586f5165d5d3be7cf009aaf387.tar.gz rust-f0620c95038c1e586f5165d5d3be7cf009aaf387.zip | |
Proper const stability check, default to unstable
Rather than deferring to const eval for checking if a trait is const, we now check up-front. This allows the error to be emitted earlier, notably at the same time as other stability checks. Also included in this commit is a change of the default const stability level to UNstable. Previously, an item that was `const` but did not explicitly state it was unstable was implicitly stable.
Diffstat (limited to 'compiler/rustc_const_eval')
| -rw-r--r-- | compiler/rustc_const_eval/src/transform/check_consts/check.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/transform/check_consts/mod.rs | 42 |
2 files changed, 35 insertions, 19 deletions
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 7f9f5dc39a1..2c669dd6d9a 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -229,18 +229,6 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { // 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`. - // FIXME: Do this as part of stability checking. - if self.is_const_stable_const_fn() { - if crate::const_eval::is_parent_const_impl_raw(tcx, def_id) { - self.ccx - .tcx - .sess - .struct_span_err(self.span, "trait methods cannot be stable const fn") - .emit(); - } - } - for (idx, local) in body.local_decls.iter_enumerated() { // Handle the return place below. if idx == RETURN_PLACE || local.internal { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index 768540c2d0d..0f79fe5513d 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -84,8 +84,6 @@ pub fn rustc_allow_const_fn_unstable( // functions are subject to more stringent restrictions than "const-unstable" functions: They // cannot use unstable features and can only call other "const-stable" functions. pub fn is_const_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - use attr::{ConstStability, StabilityLevel}; - // A default body marked const is not const-stable because const // trait fns currently cannot be const-stable. We shouldn't // restrict default bodies to only call const-stable functions. @@ -96,9 +94,39 @@ pub fn is_const_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { // Const-stability is only relevant for `const fn`. assert!(tcx.is_const_fn_raw(def_id)); - // A function is only const-stable if it has `#[rustc_const_stable]`. - matches!( - tcx.lookup_const_stability(def_id), - Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) - ) + // A function is only const-stable if it has `#[rustc_const_stable]` or it the trait it belongs + // to is const-stable. + match tcx.lookup_const_stability(def_id) { + Some(stab) => stab.is_const_stable(), + None if is_parent_const_stable_trait(tcx, def_id) => { + // Remove this when `#![feature(const_trait_impl)]` is stabilized, + // returning `true` unconditionally. + tcx.sess.delay_span_bug( + tcx.def_span(def_id), + "trait implementations cannot be const stable yet", + ); + true + } + None => false, // By default, items are not const stable. + } +} + +fn is_parent_const_stable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + let local_def_id = def_id.expect_local(); + let hir_id = tcx.local_def_id_to_hir_id(local_def_id); + + let Some(parent) = tcx.hir().find_parent_node(hir_id) else { return false }; + let parent_def = tcx.hir().get(parent); + + if !matches!( + parent_def, + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }), + .. + }) + ) { + return false; + } + + tcx.lookup_const_stability(parent.owner).map_or(false, |stab| stab.is_const_stable()) } |
