From f53fc41cfcb49bb47dab47962e045dd007f9ba9f Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Fri, 4 Feb 2022 19:03:34 -0500 Subject: [PATCH 1/7] Fall back to being const-unstable when undeclared --- .../src/transform/check_consts/mod.rs | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 deletions(-) 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 23e2afae79183..768540c2d0d48 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -84,7 +84,7 @@ 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, Stability, StabilityLevel}; + 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 @@ -96,22 +96,9 @@ 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)); - // Functions with `#[rustc_const_unstable]` are const-unstable. - match tcx.lookup_const_stability(def_id) { - Some(ConstStability { level: StabilityLevel::Unstable { .. }, .. }) => return false, - Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => return true, - None => {} - } - - // Functions with `#[unstable]` are const-unstable. - // - // FIXME(ecstaticmorse): We should keep const-stability attributes wholly separate from normal stability - // attributes. `#[unstable]` should be irrelevant. - if let Some(Stability { level: StabilityLevel::Unstable { .. }, .. }) = - tcx.lookup_stability(def_id) - { - return false; - } - - true + // A function is only const-stable if it has `#[rustc_const_stable]`. + matches!( + tcx.lookup_const_stability(def_id), + Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) + ) } From a9dd4cfa6b5398b945d3ad39e01bedb5d861ed60 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Tue, 8 Feb 2022 04:52:11 -0500 Subject: [PATCH 2/7] Add and use stability helper methods This avoids an ambiguity (when reading) where `.level.is_stable()` is not immediately clear whether it is general stability or const stability. --- compiler/rustc_attr/src/builtin.rs | 20 +++++++++++++++++++ .../src/const_eval/fn_queries.rs | 2 +- .../src/transform/check_consts/check.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_passes/src/stability.rs | 8 +++----- src/librustdoc/clean/inline.rs | 4 ++-- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/html/render/print_item.rs | 5 +---- 8 files changed, 30 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 3d4bd222715c3..2704cb8d78538 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -101,6 +101,16 @@ pub struct Stability { pub feature: Symbol, } +impl Stability { + pub fn is_unstable(&self) -> bool { + self.level.is_unstable() + } + + pub fn is_stable(&self) -> bool { + self.level.is_stable() + } +} + /// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes. #[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(HashStable_Generic)] @@ -111,6 +121,16 @@ pub struct ConstStability { pub promotable: bool, } +impl ConstStability { + pub fn is_const_unstable(&self) -> bool { + self.level.is_unstable() + } + + pub fn is_const_stable(&self) -> bool { + self.level.is_stable() + } +} + /// The available stability levels. #[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)] #[derive(HashStable_Generic)] diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index 777f4393458e2..d6f62062d1f8e 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -9,7 +9,7 @@ use rustc_span::symbol::Symbol; pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { if tcx.is_const_fn_raw(def_id) { let const_stab = tcx.lookup_const_stability(def_id)?; - if const_stab.level.is_unstable() { Some(const_stab.feature) } else { None } + if const_stab.is_const_unstable() { Some(const_stab.feature) } else { None } } else { None } 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 1104bbf471682..7f9f5dc39a1fb 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -944,7 +944,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // have no `rustc_const_stable` attributes to be const-unstable as well. This // should be fixed later. let callee_is_unstable_unmarked = tcx.lookup_const_stability(callee).is_none() - && tcx.lookup_stability(callee).map_or(false, |s| s.level.is_unstable()); + && tcx.lookup_stability(callee).map_or(false, |s| s.is_unstable()); if callee_is_unstable_unmarked { trace!("callee_is_unstable_unmarked"); // We do not use `const` modifiers for intrinsic "functions", as intrinsics are diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1616b753433a8..fa519ede4eaf2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2791,7 +2791,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn is_const_fn(self, def_id: DefId) -> bool { if self.is_const_fn_raw(def_id) { match self.lookup_const_stability(def_id) { - Some(stability) if stability.level.is_unstable() => { + Some(stability) if stability.is_const_unstable() => { // has a `rustc_const_unstable` attribute, check whether the user enabled the // corresponding feature gate. self.features() diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 58195fce28197..b96322db26efd 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -147,7 +147,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // Propagate unstability. This can happen even for non-staged-api crates in case // -Zforce-unstable-if-unmarked is set. if let Some(stab) = self.parent_stab { - if inherit_deprecation.yes() && stab.level.is_unstable() { + if inherit_deprecation.yes() && stab.is_unstable() { self.index.stab_map.insert(def_id, stab); } } @@ -190,7 +190,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { if const_stab.is_none() { debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab); if let Some(parent) = self.parent_const_stab { - if parent.level.is_unstable() { + if parent.is_const_unstable() { self.index.const_stab_map.insert(def_id, parent); } } @@ -272,9 +272,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { if stab.is_none() { debug!("annotate: stab not found, parent = {:?}", self.parent_stab); if let Some(stab) = self.parent_stab { - if inherit_deprecation.yes() && stab.level.is_unstable() - || inherit_from_parent.yes() - { + if inherit_deprecation.yes() && stab.is_unstable() || inherit_from_parent.yes() { self.index.stab_map.insert(def_id, stab); } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 9a579cb531164..6b73634afbc2e 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -344,7 +344,7 @@ crate fn build_impl( } if let Some(stab) = tcx.lookup_stability(did) { - if stab.level.is_unstable() && stab.feature == sym::rustc_private { + if stab.is_unstable() && stab.feature == sym::rustc_private { return; } } @@ -373,7 +373,7 @@ crate fn build_impl( } if let Some(stab) = tcx.lookup_stability(did) { - if stab.level.is_unstable() && stab.feature == sym::rustc_private { + if stab.is_unstable() && stab.feature == sym::rustc_private { return; } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 456d860f12559..934de5471fe13 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -632,7 +632,7 @@ impl Item { self.stability(tcx).as_ref().and_then(|s| { let mut classes = Vec::with_capacity(2); - if s.level.is_unstable() { + if s.is_unstable() { classes.push("unstable"); } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 4951cd83af207..e0f4083a91812 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -445,10 +445,7 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) -> // The "rustc_private" crates are permanently unstable so it makes no sense // to render "unstable" everywhere. - if item - .stability(tcx) - .as_ref() - .map(|s| s.level.is_unstable() && s.feature != sym::rustc_private) + if item.stability(tcx).as_ref().map(|s| s.is_unstable() && s.feature != sym::rustc_private) == Some(true) { tags += &tag_html("unstable", "", "Experimental"); From f0620c95038c1e586f5165d5d3be7cf009aaf387 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Sun, 13 Feb 2022 05:54:00 -0500 Subject: [PATCH 3/7] 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. --- .../src/transform/check_consts/check.rs | 12 ----- .../src/transform/check_consts/mod.rs | 42 ++++++++++++--- compiler/rustc_interface/src/passes.rs | 4 ++ compiler/rustc_middle/src/ty/context.rs | 15 ++++++ compiler/rustc_passes/src/stability.rs | 53 ++++++++++++++++++- .../ui/consts/rustc-impl-const-stability.rs | 7 ++- .../auxiliary/staged-api.rs | 7 +-- .../ui/rfc-2632-const-trait-impl/stability.rs | 16 +++--- .../stability.stderr | 29 +++++----- .../rfc-2632-const-trait-impl/staged-api.rs | 17 +++--- .../staged-api.stable.stderr | 22 ++++++++ .../staged-api.staged.stderr | 10 ---- .../staged-api.stock.stderr | 18 ------- .../staged-api.unstable.stderr | 12 +++++ .../missing-const-stability.rs | 14 +++-- .../missing-const-stability.stderr | 11 +++- 16 files changed, 196 insertions(+), 93 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr 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 7f9f5dc39a1fb..2c669dd6d9a9b 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 768540c2d0d48..0f79fe5513dd8 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()) } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 00119267e8561..7a6ab62ef67fa 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -970,6 +970,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { sess.time("layout_testing", || layout_test::test_layout(tcx)); + sess.time("stable_impl_const_trait_checking", || { + rustc_passes::stability::check_const_impl_trait(tcx) + }); + // Avoid overwhelming user with errors if borrow checking failed. // I'm not sure how helpful this is, to be honest, but it avoids a // lot of annoying errors in the ui tests (basically, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index fa519ede4eaf2..3b0df1d83e86a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2808,6 +2808,21 @@ impl<'tcx> TyCtxt<'tcx> { false } } + + /// Whether the trait impl is marked const. This does not consider stability or feature gates. + pub fn is_const_trait_impl_raw(self, def_id: DefId) -> bool { + let Some(local_def_id) = def_id.as_local() else { return false }; + let hir_id = self.local_def_id_to_hir_id(local_def_id); + let node = self.hir().get(hir_id); + + matches!( + node, + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }), + .. + }) + ) + } } impl<'tcx> TyCtxtAt<'tcx> { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index b96322db26efd..7b8ffeaac2484 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -9,6 +9,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::privacy::AccessLevels; @@ -530,7 +531,8 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { return; } - let is_const = self.tcx.is_const_fn(def_id.to_def_id()); + let is_const = self.tcx.is_const_fn(def_id.to_def_id()) + || self.tcx.is_const_trait_impl_raw(def_id.to_def_id()); let is_stable = self .tcx .lookup_stability(def_id) @@ -604,6 +606,44 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { // stable (assuming they have not inherited instability from their parent). } +struct CheckStableConstImplTrait<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> ItemLikeVisitor<'tcx> for CheckStableConstImplTrait<'tcx> { + fn visit_item(&mut self, item: &'tcx Item<'tcx>) { + if !matches!( + item.kind, + hir::ItemKind::Impl(hir::Impl { + of_trait: Some(_), + constness: hir::Constness::Const, + .. + }) + ) { + return; + } + + if self.tcx.lookup_const_stability(item.def_id).map_or(false, |stab| stab.is_const_stable()) + { + self.tcx + .sess + .struct_span_err(item.span, "trait implementations cannot be const stable yet") + .note("see issue #67792 for more information") + .emit(); + } + } + + fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) { + // Nothing to do here. + } + fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) { + // Nothing to do here. + } + fn visit_foreign_item(&mut self, _foreign_item: &'tcx hir::ForeignItem<'tcx>) { + // Nothing to do here. + } +} + fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index { let mut index = Index { stab_map: Default::default(), @@ -824,6 +864,17 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> { } } +pub fn check_const_impl_trait(tcx: TyCtxt<'_>) { + let features = tcx.features(); // FIXME How cheap is this call? + // Both feature gates have to be enabled for this check to have any effect. + if !features.staged_api || !features.const_trait_impl { + return; + } + + let mut visitor = CheckStableConstImplTrait { tcx }; + tcx.hir().visit_all_item_likes(&mut visitor); +} + /// Given the list of enabled features that were not language features (i.e., that /// were expected to be library features), and the list of features used from /// libraries, identify activated features that don't exist and error about them. diff --git a/src/test/ui/consts/rustc-impl-const-stability.rs b/src/test/ui/consts/rustc-impl-const-stability.rs index e3fda57548ea3..0c18efa0a0235 100644 --- a/src/test/ui/consts/rustc-impl-const-stability.rs +++ b/src/test/ui/consts/rustc-impl-const-stability.rs @@ -1,19 +1,18 @@ -// build-pass +// check-pass #![crate_type = "lib"] #![feature(staged_api)] #![feature(const_trait_impl)] #![stable(feature = "foo", since = "1.0.0")] - #[stable(feature = "potato", since = "1.27.0")] pub struct Data { - _data: u128 + _data: u128, } #[stable(feature = "potato", since = "1.27.0")] +#[rustc_const_unstable(feature = "data_foo", issue = "none")] impl const Default for Data { - #[rustc_const_unstable(feature = "data_foo", issue = "none")] fn default() -> Data { Data { _data: 42 } } diff --git a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs index 80e61ab0a9e8b..19e9006094bed 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs @@ -1,5 +1,4 @@ #![feature(const_trait_impl)] - #![feature(staged_api)] #![stable(feature = "rust1", since = "1.0.0")] @@ -13,9 +12,7 @@ pub trait MyTrait { pub struct Unstable; #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "staged", issue = "none")] +#[rustc_const_unstable(feature = "unstable", issue = "none")] impl const MyTrait for Unstable { - fn func() { - - } + fn func() {} } diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.rs b/src/test/ui/rfc-2632-const-trait-impl/stability.rs index 906956f5eba49..15f1db18f89d9 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/stability.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/stability.rs @@ -1,5 +1,3 @@ -#![feature(allow_internal_unstable)] -#![feature(const_add)] #![feature(const_trait_impl)] #![feature(staged_api)] #![stable(feature = "rust1", since = "1.0.0")] @@ -10,10 +8,10 @@ pub struct Int(i32); #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rust1", since = "1.0.0")] impl const std::ops::Sub for Int { + //~^ ERROR trait implementations cannot be const stable yet type Output = Self; fn sub(self, rhs: Self) -> Self { - //~^ ERROR trait methods cannot be stable const fn Int(self.0 - rhs.0) } } @@ -30,16 +28,16 @@ impl const std::ops::Add for Int { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rust1", since = "1.0.0")] -pub const fn foo() -> Int { - Int(1i32) + Int(2i32) +pub const fn const_err() { + Int(0) + Int(0); //~^ ERROR not yet stable as a const fn + Int(0) - Int(0); } -// ok #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "bar", issue = "none")] -pub const fn bar() -> Int { - Int(1i32) + Int(2i32) +pub fn non_const_success() { + Int(0) + Int(0); + Int(0) - Int(0); } fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr index 7473b801cce63..fa3d85a3e6ad3 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr @@ -1,19 +1,24 @@ -error: trait methods cannot be stable const fn - --> $DIR/stability.rs:15:5 - | -LL | / fn sub(self, rhs: Self) -> Self { -LL | | -LL | | Int(self.0 - rhs.0) -LL | | } - | |_____^ - error: `::add` is not yet stable as a const fn - --> $DIR/stability.rs:34:5 + --> $DIR/stability.rs:32:5 | -LL | Int(1i32) + Int(2i32) - | ^^^^^^^^^^^^^^^^^^^^^ +LL | Int(0) + Int(0); + | ^^^^^^^^^^^^^^^ | = help: const-stable functions can only call other const-stable functions +error: trait implementations cannot be const stable yet + --> $DIR/stability.rs:10:1 + | +LL | / impl const std::ops::Sub for Int { +LL | | +LL | | type Output = Self; +LL | | +... | +LL | | } +LL | | } + | |_^ + | + = note: see issue #67792 for more information + error: aborting due to 2 previous errors diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs index 39a1b6066dea3..903ced42698ac 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs @@ -1,9 +1,7 @@ -// revisions: stock staged -#![cfg_attr(staged, feature(staged))] +// revisions: stable unstable +#![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file. #![feature(const_trait_impl)] -#![allow(incomplete_features)] - #![feature(staged_api)] #![stable(feature = "rust1", since = "1.0.0")] @@ -16,12 +14,11 @@ use staged_api::*; pub struct Stable; #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(staged, rustc_const_stable(feature = "rust1", since = "1.0.0"))] -// ^ should trigger error with or without the attribute +#[cfg_attr(stable, rustc_const_stable(feature = "rust1", since = "1.0.0"))] impl const MyTrait for Stable { - fn func() { //~ ERROR trait methods cannot be stable const fn - - } + //[stable]~^ ERROR trait implementations cannot be const stable yet + //[unstable]~^^ ERROR implementation has missing const stability attribute + fn func() {} } fn non_const_context() { @@ -32,7 +29,7 @@ fn non_const_context() { #[unstable(feature = "none", issue = "none")] const fn const_context() { Unstable::func(); - //[stock]~^ ERROR `::func` is not yet stable as a const fn + //[stable]~^ ERROR `::func` is not yet stable as a const fn Stable::func(); } diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr new file mode 100644 index 0000000000000..2fde51217f5dc --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr @@ -0,0 +1,22 @@ +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:31:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + +error: trait implementations cannot be const stable yet + --> $DIR/staged-api.rs:18:1 + | +LL | / impl const MyTrait for Stable { +LL | | +LL | | +LL | | fn func() {} +LL | | } + | |_^ + | + = note: see issue #67792 for more information + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr deleted file mode 100644 index d2ff4ce200130..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: trait methods cannot be stable const fn - --> $DIR/staged-api.rs:22:5 - | -LL | / fn func() { -LL | | -LL | | } - | |_____^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr deleted file mode 100644 index 91c5469bd90a5..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: trait methods cannot be stable const fn - --> $DIR/staged-api.rs:22:5 - | -LL | / fn func() { -LL | | -LL | | } - | |_____^ - -error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:34:5 - | -LL | Unstable::func(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(staged)]` to the crate attributes to enable - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr new file mode 100644 index 0000000000000..4ea1be69b3bb9 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr @@ -0,0 +1,12 @@ +error: implementation has missing const stability attribute + --> $DIR/staged-api.rs:18:1 + | +LL | / impl const MyTrait for Stable { +LL | | +LL | | +LL | | fn func() {} +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/stability-attribute/missing-const-stability.rs b/src/test/ui/stability-attribute/missing-const-stability.rs index 57e64737d0faa..d89886af314a4 100644 --- a/src/test/ui/stability-attribute/missing-const-stability.rs +++ b/src/test/ui/stability-attribute/missing-const-stability.rs @@ -18,9 +18,15 @@ impl Foo { pub const fn bar() {} // ok because function is unstable } -// FIXME Once #![feature(const_trait_impl)] is allowed to be stable, add a test -// for const trait impls. Right now, a "trait methods cannot be stable const fn" -// error is emitted. This occurs prior to the lint being tested here, such that -// the lint cannot currently be tested on this use case. +#[stable(feature = "stable", since = "1.0.0")] +pub trait Bar { + #[stable(feature = "stable", since = "1.0.0")] + fn fun(); +} +#[stable(feature = "stable", since = "1.0.0")] +impl const Bar for Foo { + //~^ ERROR implementation has missing const stability attribute + fn fun() {} +} 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 7eba99a477abe..6f2ade0d0abf4 100644 --- a/src/test/ui/stability-attribute/missing-const-stability.stderr +++ b/src/test/ui/stability-attribute/missing-const-stability.stderr @@ -10,5 +10,14 @@ error: associated function has missing const stability attribute LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: implementation has missing const stability attribute + --> $DIR/missing-const-stability.rs:27:1 + | +LL | / impl const Bar for Foo { +LL | | +LL | | fn fun() {} +LL | | } + | |_^ + +error: aborting due to 3 previous errors From 5ff331142e03bede7f9c8264b8625caf6b65989c Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Tue, 22 Feb 2022 14:54:47 -0500 Subject: [PATCH 4/7] Move check to existing pass This alters the diagnostics a bit, as the trait method is still stable. The only thing this check does is ensure that compilation fails if a trait implementation is declared const-stable. --- compiler/rustc_interface/src/passes.rs | 4 - compiler/rustc_passes/src/stability.rs | 82 ++++++------------- .../ui/rfc-2632-const-trait-impl/stability.rs | 43 ---------- .../stability.stderr | 24 ------ .../rfc-2632-const-trait-impl/staged-api.rs | 24 ++++-- .../staged-api.stable.stderr | 17 +--- .../staged-api.unstable.stderr | 26 +++--- 7 files changed, 62 insertions(+), 158 deletions(-) delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/stability.rs delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/stability.stderr diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7a6ab62ef67fa..00119267e8561 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -970,10 +970,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { sess.time("layout_testing", || layout_test::test_layout(tcx)); - sess.time("stable_impl_const_trait_checking", || { - rustc_passes::stability::check_const_impl_trait(tcx) - }); - // Avoid overwhelming user with errors if borrow checking failed. // I'm not sure how helpful this is, to be honest, but it avoids a // lot of annoying errors in the ui tests (basically, diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 7b8ffeaac2484..8f8f677cad4de 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -9,7 +9,6 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::privacy::AccessLevels; @@ -606,44 +605,6 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { // stable (assuming they have not inherited instability from their parent). } -struct CheckStableConstImplTrait<'tcx> { - tcx: TyCtxt<'tcx>, -} - -impl<'tcx> ItemLikeVisitor<'tcx> for CheckStableConstImplTrait<'tcx> { - fn visit_item(&mut self, item: &'tcx Item<'tcx>) { - if !matches!( - item.kind, - hir::ItemKind::Impl(hir::Impl { - of_trait: Some(_), - constness: hir::Constness::Const, - .. - }) - ) { - return; - } - - if self.tcx.lookup_const_stability(item.def_id).map_or(false, |stab| stab.is_const_stable()) - { - self.tcx - .sess - .struct_span_err(item.span, "trait implementations cannot be const stable yet") - .note("see issue #67792 for more information") - .emit(); - } - } - - fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) { - // Nothing to do here. - } - fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) { - // Nothing to do here. - } - fn visit_foreign_item(&mut self, _foreign_item: &'tcx hir::ForeignItem<'tcx>) { - // Nothing to do here. - } -} - fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index { let mut index = Index { stab_map: Default::default(), @@ -748,16 +709,23 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { // For implementations of traits, check the stability of each item // individually as it's possible to have a stable trait with unstable // items. - hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => { - if self.tcx.features().staged_api { + hir::ItemKind::Impl(hir::Impl { + of_trait: Some(ref t), + self_ty, + items, + constness, + .. + }) => { + let features = self.tcx.features(); + if features.staged_api { + let attrs = self.tcx.hir().attrs(item.hir_id()); + let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item.span); + // If this impl block has an #[unstable] attribute, give an // error if all involved types and traits are stable, because // it will have no effect. // See: https://github.com/rust-lang/rust/issues/55436 - let attrs = self.tcx.hir().attrs(item.hir_id()); - if let (Some((Stability { level: attr::Unstable { .. }, .. }, span)), _) = - attr::find_stability(&self.tcx.sess, attrs, item.span) - { + if let Some((Stability { level: attr::Unstable { .. }, .. }, span)) = stab { let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true }; c.visit_ty(self_ty); c.visit_trait_ref(t); @@ -773,6 +741,19 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { ); } } + + // `#![feature(const_trait_impl)]` is unstable, so any impl declared stable + // needs to have an error emitted. + if features.const_trait_impl + && constness == hir::Constness::Const + && const_stab.map_or(false, |(stab, _)| stab.is_const_stable()) + { + self.tcx + .sess + .struct_span_err(item.span, "trait implementations cannot be const stable yet") + .note("see issue #67792 for more information") + .emit(); + } } for impl_item_ref in *items { @@ -864,17 +845,6 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> { } } -pub fn check_const_impl_trait(tcx: TyCtxt<'_>) { - let features = tcx.features(); // FIXME How cheap is this call? - // Both feature gates have to be enabled for this check to have any effect. - if !features.staged_api || !features.const_trait_impl { - return; - } - - let mut visitor = CheckStableConstImplTrait { tcx }; - tcx.hir().visit_all_item_likes(&mut visitor); -} - /// Given the list of enabled features that were not language features (i.e., that /// were expected to be library features), and the list of features used from /// libraries, identify activated features that don't exist and error about them. diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.rs b/src/test/ui/rfc-2632-const-trait-impl/stability.rs deleted file mode 100644 index 15f1db18f89d9..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/stability.rs +++ /dev/null @@ -1,43 +0,0 @@ -#![feature(const_trait_impl)] -#![feature(staged_api)] -#![stable(feature = "rust1", since = "1.0.0")] - -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Int(i32); - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "rust1", since = "1.0.0")] -impl const std::ops::Sub for Int { - //~^ ERROR trait implementations cannot be const stable yet - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - Int(self.0 - rhs.0) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_add", issue = "none")] -impl const std::ops::Add for Int { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - Int(self.0 + rhs.0) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "rust1", since = "1.0.0")] -pub const fn const_err() { - Int(0) + Int(0); - //~^ ERROR not yet stable as a const fn - Int(0) - Int(0); -} - -#[stable(feature = "rust1", since = "1.0.0")] -pub fn non_const_success() { - Int(0) + Int(0); - Int(0) - Int(0); -} - -fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr deleted file mode 100644 index fa3d85a3e6ad3..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error: `::add` is not yet stable as a const fn - --> $DIR/stability.rs:32:5 - | -LL | Int(0) + Int(0); - | ^^^^^^^^^^^^^^^ - | - = help: const-stable functions can only call other const-stable functions - -error: trait implementations cannot be const stable yet - --> $DIR/stability.rs:10:1 - | -LL | / impl const std::ops::Sub for Int { -LL | | -LL | | type Output = Self; -LL | | -... | -LL | | } -LL | | } - | |_^ - | - = note: see issue #67792 for more information - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs index 903ced42698ac..f8a55a0a4a02f 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs @@ -11,26 +11,36 @@ extern crate staged_api; use staged_api::*; #[stable(feature = "rust1", since = "1.0.0")] -pub struct Stable; +pub struct Foo; #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(stable, rustc_const_stable(feature = "rust1", since = "1.0.0"))] -impl const MyTrait for Stable { +#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))] +impl const MyTrait for Foo { //[stable]~^ ERROR trait implementations cannot be const stable yet - //[unstable]~^^ ERROR implementation has missing const stability attribute fn func() {} } +// Const stability has no impact on usage in non-const contexts. fn non_const_context() { Unstable::func(); - Stable::func(); + Foo::func(); } #[unstable(feature = "none", issue = "none")] const fn const_context() { Unstable::func(); - //[stable]~^ ERROR `::func` is not yet stable as a const fn - Stable::func(); + // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is + // not const-stable. + Foo::func(); + //[unstable]~^ not yet stable as a const fn +} + +#[stable(feature = "rust1", since = "1.0.0")] +const fn stable_const_context() { + Unstable::func(); + //[unstable]~^ ERROR not yet stable as a const fn + Foo::func(); + //[unstable]~^ ERROR not yet stable as a const fn } fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr index 2fde51217f5dc..25407a0b43c18 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr @@ -1,22 +1,11 @@ -error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:31:5 - | -LL | Unstable::func(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(unstable)]` to the crate attributes to enable - -error: trait implementations cannot be const stable yet +error: implementation has missing const stability attribute --> $DIR/staged-api.rs:18:1 | -LL | / impl const MyTrait for Stable { -LL | | +LL | / impl const MyTrait for Foo { LL | | LL | | fn func() {} LL | | } | |_^ - | - = note: see issue #67792 for more information -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr index 4ea1be69b3bb9..30fe97bb884b4 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr @@ -1,12 +1,18 @@ -error: implementation has missing const stability attribute - --> $DIR/staged-api.rs:18:1 - | -LL | / impl const MyTrait for Stable { -LL | | -LL | | -LL | | fn func() {} -LL | | } - | |_^ +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:34:5 + | +LL | Foo::func(); + | ^^^^^^^^^^^ + | + = help: add `#![feature(foo)]` to the crate attributes to enable + +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:42:5 + | +LL | Foo::func(); + | ^^^^^^^^^^^ + | + = help: add `#![feature(foo)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 2 previous errors From cf5a803600c7a1f18883eef30de61815690664bc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 19 May 2022 12:26:06 +0000 Subject: [PATCH 5/7] Rebase fallout --- compiler/rustc_passes/src/stability.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 8f8f677cad4de..70cb1f2a281a8 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -745,7 +745,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { // `#![feature(const_trait_impl)]` is unstable, so any impl declared stable // needs to have an error emitted. if features.const_trait_impl - && constness == hir::Constness::Const + && *constness == hir::Constness::Const && const_stab.map_or(false, |(stab, _)| stab.is_const_stable()) { self.tcx From aa9eae50f3fd6e4cc7ed0a3e8c2c2a24012e3564 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 19 May 2022 12:30:38 +0000 Subject: [PATCH 6/7] Stable const things need a stability attribute --- src/test/ui/rfc-2632-const-trait-impl/staged-api.rs | 1 + .../ui/rfc-2632-const-trait-impl/staged-api.stable.stderr | 6 ++++-- .../ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs index f8a55a0a4a02f..a521e986babf0 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs @@ -15,6 +15,7 @@ pub struct Foo; #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))] +#[cfg_attr(stable, rustc_const_stable(feature = "foo", since = "1.0.0"))] impl const MyTrait for Foo { //[stable]~^ ERROR trait implementations cannot be const stable yet fn func() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr index 25407a0b43c18..6c9c660ab234c 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr @@ -1,11 +1,13 @@ -error: implementation has missing const stability attribute - --> $DIR/staged-api.rs:18:1 +error: trait implementations cannot be const stable yet + --> $DIR/staged-api.rs:19:1 | LL | / impl const MyTrait for Foo { LL | | LL | | fn func() {} LL | | } | |_^ + | + = note: see issue #67792 for more information error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr index 30fe97bb884b4..0401ba478fd11 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr @@ -1,5 +1,5 @@ error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:34:5 + --> $DIR/staged-api.rs:35:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | Foo::func(); = help: add `#![feature(foo)]` to the crate attributes to enable error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:42:5 + --> $DIR/staged-api.rs:43:5 | LL | Foo::func(); | ^^^^^^^^^^^ From f9c4f2b7ad431c6658682724a057b4a36920fdb4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 19 May 2022 14:48:39 +0000 Subject: [PATCH 7/7] Fix up tests --- .../staged-api-user-crate.rs | 16 +++++++++++ .../staged-api-user-crate.stderr | 11 ++++++++ .../rfc-2632-const-trait-impl/staged-api.rs | 18 +++++++++++- .../staged-api.stable.stderr | 14 +++++++++- .../staged-api.unstable.stderr | 28 +++++++++++++++++-- 5 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs new file mode 100644 index 0000000000000..fc0d82727b553 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs @@ -0,0 +1,16 @@ +// aux-build: staged-api.rs +extern crate staged_api; + +use staged_api::*; + +// Const stability has no impact on usage in non-const contexts. +fn non_const_context() { + Unstable::func(); +} + +const fn stable_const_context() { + Unstable::func(); + //~^ ERROR cannot call non-const fn `::func` in constant functions +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr new file mode 100644 index 0000000000000..61f9840e0d0a0 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `::func` in constant functions + --> $DIR/staged-api-user-crate.rs:12:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs index a521e986babf0..1d79f5adf93f3 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs @@ -33,15 +33,31 @@ const fn const_context() { // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is // not const-stable. Foo::func(); - //[unstable]~^ not yet stable as a const fn + //[unstable]~^ ERROR not yet stable as a const fn + // ^ fails, because the `foo` feature is not active } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))] +pub const fn const_context_not_const_stable() { + //[stable]~^ ERROR function has missing const stability attribute + Unstable::func(); + // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is + // not const-stable. + Foo::func(); + //[unstable]~^ ERROR not yet stable as a const fn + // ^ fails, because the `foo` feature is not active +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "cheese", since = "1.0.0")] const fn stable_const_context() { Unstable::func(); //[unstable]~^ ERROR not yet stable as a const fn Foo::func(); //[unstable]~^ ERROR not yet stable as a const fn + const_context_not_const_stable() + //[unstable]~^ ERROR not yet stable as a const fn } fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr index 6c9c660ab234c..a1aca762ef479 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr @@ -9,5 +9,17 @@ LL | | } | = note: see issue #67792 for more information -error: aborting due to previous error +error: function has missing const stability attribute + --> $DIR/staged-api.rs:42:1 + | +LL | / pub const fn const_context_not_const_stable() { +LL | | +LL | | Unstable::func(); +LL | | // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is +... | +LL | | // ^ fails, because the `foo` feature is not active +LL | | } + | |_^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr index 0401ba478fd11..c38d1a81ae77b 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr @@ -7,12 +7,36 @@ LL | Foo::func(); = help: add `#![feature(foo)]` to the crate attributes to enable error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:43:5 + --> $DIR/staged-api.rs:47:5 | LL | Foo::func(); | ^^^^^^^^^^^ | = help: add `#![feature(foo)]` to the crate attributes to enable -error: aborting due to 2 previous errors +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:55:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:57:5 + | +LL | Foo::func(); + | ^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: `const_context_not_const_stable` is not yet stable as a const fn + --> $DIR/staged-api.rs:59:5 + | +LL | const_context_not_const_stable() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: aborting due to 5 previous errors