From 2743df848b0970ad9d97b6ce8222d4fd64898b61 Mon Sep 17 00:00:00 2001 From: Michael Goulet <michael@errs.io> Date: Sun, 12 Jan 2025 20:52:30 +0000 Subject: [PATCH] Enforce syntactical stability of const traits in HIR --- compiler/rustc_middle/src/middle/stability.rs | 89 ++++++++++++++++++- compiler/rustc_passes/src/stability.rs | 36 +++++++- compiler/rustc_resolve/src/macros.rs | 1 + library/core/src/intrinsics/fallback.rs | 1 + library/core/src/marker.rs | 1 + library/core/src/ops/arith.rs | 1 + library/core/src/ops/deref.rs | 2 + library/core/src/ops/drop.rs | 1 + tests/ui/consts/promoted-const-drop.rs | 2 +- tests/ui/consts/promoted_const_call.rs | 16 ++-- tests/ui/consts/promoted_const_call.stderr | 39 ++++---- .../missing-const-stability.rs | 1 + .../missing-const-stability.stderr | 14 ++- .../const-traits/auxiliary/staged-api.rs | 1 + .../call-const-trait-method-pass.rs | 2 +- .../const-traits/const-and-non-const-impl.rs | 2 +- tests/ui/traits/const-traits/generic-bound.rs | 2 +- .../const-traits/syntactical-unstable.rs | 34 +++++++ .../const-traits/syntactical-unstable.stderr | 67 ++++++++++++++ .../trait-default-body-stability.rs | 1 + .../trait-default-body-stability.stderr | 4 +- 21 files changed, 279 insertions(+), 38 deletions(-) create mode 100644 tests/ui/traits/const-traits/syntactical-unstable.rs create mode 100644 tests/ui/traits/const-traits/syntactical-unstable.stderr diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 84c3c2eb49e..75ca289056e 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -30,6 +30,14 @@ pub enum StabilityLevel { Stable, } +#[derive(Copy, Clone)] +pub enum UnstableKind { + /// Enforcing regular stability of an item + Regular, + /// Enforcing const stability of an item + Const(Span), +} + /// An entry in the `depr_map`. #[derive(Copy, Clone, HashStable, Debug, Encodable, Decodable)] pub struct DeprecationEntry { @@ -108,10 +116,16 @@ pub fn report_unstable( is_soft: bool, span: Span, soft_handler: impl FnOnce(&'static Lint, Span, String), + kind: UnstableKind, ) { + let qual = match kind { + UnstableKind::Regular => "", + UnstableKind::Const(_) => " const", + }; + let msg = match reason { - Some(r) => format!("use of unstable library feature `{feature}`: {r}"), - None => format!("use of unstable library feature `{feature}`"), + Some(r) => format!("use of unstable{qual} library feature `{feature}`: {r}"), + None => format!("use of unstable{qual} library feature `{feature}`"), }; if is_soft { @@ -121,6 +135,9 @@ pub fn report_unstable( if let Some((inner_types, msg, sugg, applicability)) = suggestion { err.span_suggestion(inner_types, msg, sugg, applicability); } + if let UnstableKind::Const(kw) = kind { + err.span_label(kw, "trait is not stable as const yet"); + } err.emit(); } } @@ -587,6 +604,7 @@ impl<'tcx> TyCtxt<'tcx> { is_soft, span, soft_handler, + UnstableKind::Regular, ), EvalResult::Unmarked => unmarked(span, def_id), } @@ -594,6 +612,73 @@ impl<'tcx> TyCtxt<'tcx> { is_allowed } + /// This function is analogous to `check_optional_stability` but with the logic in + /// `eval_stability_allow_unstable` inlined, and which operating on const stability + /// instead of regular stability. + /// + /// This enforces *syntactical* const stability of const traits. In other words, + /// it enforces the ability to name `~const`/`const` traits in trait bounds in various + /// syntax positions in HIR (including in the trait of an impl header). + pub fn check_const_stability(self, def_id: DefId, span: Span, const_kw_span: Span) { + let is_staged_api = self.lookup_stability(def_id.krate.as_def_id()).is_some(); + if !is_staged_api { + return; + } + + // Only the cross-crate scenario matters when checking unstable APIs + let cross_crate = !def_id.is_local(); + if !cross_crate { + return; + } + + let stability = self.lookup_const_stability(def_id); + debug!( + "stability: \ + inspecting def_id={:?} span={:?} of stability={:?}", + def_id, span, stability + ); + + match stability { + Some(ConstStability { + level: attr::StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. }, + feature, + .. + }) => { + assert!(!is_soft); + + if span.allows_unstable(feature) { + debug!("body stability: skipping span={:?} since it is internal", span); + return; + } + if self.features().enabled(feature) { + return; + } + + // If this item was previously part of a now-stabilized feature which is still + // enabled (i.e. the user hasn't removed the attribute for the stabilized feature + // yet) then allow use of this item. + if let Some(implied_by) = implied_by + && self.features().enabled(implied_by) + { + return; + } + + report_unstable( + self.sess, + feature, + reason.to_opt_reason(), + issue, + None, + false, + span, + |_, _, _| {}, + UnstableKind::Const(const_kw_span), + ); + } + Some(_) | None => {} + } + } + pub fn lookup_deprecation(self, id: DefId) -> Option<Deprecation> { self.lookup_deprecation_entry(id).map(|depr| depr.attr) } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 30f9e698521..aabc33b015e 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -593,9 +593,11 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { } fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) { - 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.def_kind(def_id.to_def_id()) == DefKind::Trait + && self.tcx.is_const_trait(def_id.to_def_id())); - // Reachable const fn must have a stability attribute. + // Reachable const fn/trait must have a stability attribute. if is_const && self.effective_visibilities.is_reachable(def_id) && self.tcx.lookup_const_stability(def_id).is_none() @@ -772,7 +774,13 @@ 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, .. }) => { + 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()); @@ -814,6 +822,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { } } + match constness { + rustc_hir::Constness::Const => { + if let Some(def_id) = t.trait_def_id() { + // FIXME(const_trait_impl): Improve the span here. + self.tcx.check_const_stability(def_id, t.path.span, t.path.span); + } + } + rustc_hir::Constness::NotConst => {} + } + for impl_item_ref in *items { let impl_item = self.tcx.associated_item(impl_item_ref.id.owner_id); @@ -829,6 +847,18 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { intravisit::walk_item(self, item); } + fn visit_poly_trait_ref(&mut self, t: &'tcx hir::PolyTraitRef<'tcx>) { + match t.modifiers.constness { + hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) => { + if let Some(def_id) = t.trait_ref.trait_def_id() { + self.tcx.check_const_stability(def_id, t.trait_ref.path.span, span); + } + } + hir::BoundConstness::Never => {} + } + intravisit::walk_poly_trait_ref(self, t); + } + fn visit_path(&mut self, path: &hir::Path<'tcx>, id: hir::HirId) { if let Some(def_id) = path.res.opt_def_id() { let method_span = path.segments.last().map(|s| s.ident.span); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index b24e343c58d..25e35fead7e 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1031,6 +1031,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { is_soft, span, soft_handler, + stability::UnstableKind::Regular, ); } } diff --git a/library/core/src/intrinsics/fallback.rs b/library/core/src/intrinsics/fallback.rs index 1779126b180..70484e4d0f2 100644 --- a/library/core/src/intrinsics/fallback.rs +++ b/library/core/src/intrinsics/fallback.rs @@ -8,6 +8,7 @@ #![allow(missing_docs)] #[const_trait] +#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")] pub trait CarryingMulAdd: Copy + 'static { type Unsigned: Copy + 'static; fn carrying_mul_add( diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 4af9b666e54..01af964a83e 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -952,6 +952,7 @@ marker_impls! { /// This should be used for `~const` bounds, /// as non-const bounds will always hold for every type. #[unstable(feature = "const_destruct", issue = "133214")] +#[rustc_const_unstable(feature = "const_destruct", issue = "133214")] #[lang = "destruct"] #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] #[rustc_deny_explicit_impl] diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 810b906b871..fe7ff2d9ede 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -65,6 +65,7 @@ /// ``` #[lang = "add"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "90080")] #[rustc_on_unimplemented( on(all(_Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",), on(all(_Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",), diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index ed0d30a0f50..11490ea2bfc 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -134,6 +134,7 @@ #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Deref"] #[const_trait] +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] pub trait Deref { /// The resulting type after dereferencing. #[stable(feature = "rust1", since = "1.0.0")] @@ -263,6 +264,7 @@ impl<T: ?Sized> const Deref for &mut T { #[doc(alias = "*")] #[stable(feature = "rust1", since = "1.0.0")] #[const_trait] +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] pub trait DerefMut: ~const Deref { /// Mutably dereferences the value. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index 78b5252195f..e024b7fb4d3 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -204,6 +204,7 @@ #[lang = "drop"] #[stable(feature = "rust1", since = "1.0.0")] #[const_trait] +#[rustc_const_unstable(feature = "const_destruct", issue = "133214")] pub trait Drop { /// Executes the destructor for this type. /// diff --git a/tests/ui/consts/promoted-const-drop.rs b/tests/ui/consts/promoted-const-drop.rs index e09c30ea785..1d1897e15d4 100644 --- a/tests/ui/consts/promoted-const-drop.rs +++ b/tests/ui/consts/promoted-const-drop.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl)] +#![feature(const_trait_impl, const_destruct)] struct A(); diff --git a/tests/ui/consts/promoted_const_call.rs b/tests/ui/consts/promoted_const_call.rs index c3920ff7241..79cb2ea2a02 100644 --- a/tests/ui/consts/promoted_const_call.rs +++ b/tests/ui/consts/promoted_const_call.rs @@ -1,6 +1,4 @@ -//@ known-bug: #103507 - -#![feature(const_trait_impl)] +#![feature(const_trait_impl, const_destruct)] struct Panic; impl const Drop for Panic { fn drop(&mut self) { panic!(); } } @@ -8,15 +6,15 @@ impl const Drop for Panic { fn drop(&mut self) { panic!(); } } pub const fn id<T>(x: T) -> T { x } pub const C: () = { let _: &'static _ = &id(&Panic); - //FIXME ~^ ERROR: temporary value dropped while borrowed - //FIXME ~| ERROR: temporary value dropped while borrowed + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed }; fn main() { let _: &'static _ = &id(&Panic); - //FIXME ~^ ERROR: temporary value dropped while borrowed - //FIXME ~| ERROR: temporary value dropped while borrowed + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed let _: &'static _ = &&(Panic, 0).1; - //FIXME~^ ERROR: temporary value dropped while borrowed - //FIXME~| ERROR: temporary value dropped while borrowed + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed } diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr index 40c6d083b06..7a9cdd68704 100644 --- a/tests/ui/consts/promoted_const_call.stderr +++ b/tests/ui/consts/promoted_const_call.stderr @@ -1,17 +1,25 @@ -error[E0493]: destructor of `Panic` cannot be evaluated at compile-time - --> $DIR/promoted_const_call.rs:10:30 +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:8:26 | LL | let _: &'static _ = &id(&Panic); - | ^^^^^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constants - | - = note: see issue #133214 <https://github.com/rust-lang/rust/issues/133214> for more information - = help: add `#![feature(const_destruct)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | }; + | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:16:26 + --> $DIR/promoted_const_call.rs:8:30 + | +LL | let _: &'static _ = &id(&Panic); + | ---------- ^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:14:26 | LL | let _: &'static _ = &id(&Panic); | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -22,7 +30,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:16:30 + --> $DIR/promoted_const_call.rs:14:30 | LL | let _: &'static _ = &id(&Panic); | ---------- ^^^^^ - temporary value is freed at the end of this statement @@ -31,7 +39,7 @@ LL | let _: &'static _ = &id(&Panic); | type annotation requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:19:26 + --> $DIR/promoted_const_call.rs:17:26 | LL | let _: &'static _ = &&(Panic, 0).1; | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -42,7 +50,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:19:27 + --> $DIR/promoted_const_call.rs:17:27 | LL | let _: &'static _ = &&(Panic, 0).1; | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -52,7 +60,6 @@ LL | let _: &'static _ = &&(Panic, 0).1; LL | } | - temporary value is freed at the end of this statement -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0493, E0716. -For more information about an error, try `rustc --explain E0493`. +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/stability-attribute/missing-const-stability.rs b/tests/ui/stability-attribute/missing-const-stability.rs index 19820730736..c3e72e83948 100644 --- a/tests/ui/stability-attribute/missing-const-stability.rs +++ b/tests/ui/stability-attribute/missing-const-stability.rs @@ -22,6 +22,7 @@ impl Foo { #[stable(feature = "stable", since = "1.0.0")] #[const_trait] pub trait Bar { +//~^ ERROR trait has missing const stability attribute #[stable(feature = "stable", since = "1.0.0")] fn fun(); } diff --git a/tests/ui/stability-attribute/missing-const-stability.stderr b/tests/ui/stability-attribute/missing-const-stability.stderr index baa4c34af06..09461e6fb54 100644 --- a/tests/ui/stability-attribute/missing-const-stability.stderr +++ b/tests/ui/stability-attribute/missing-const-stability.stderr @@ -4,8 +4,18 @@ error: function has missing const stability attribute LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ +error: trait has missing const stability attribute + --> $DIR/missing-const-stability.rs:24:1 + | +LL | / pub trait Bar { +LL | | +LL | | #[stable(feature = "stable", since = "1.0.0")] +LL | | fn fun(); +LL | | } + | |_^ + error: function has missing const stability attribute - --> $DIR/missing-const-stability.rs:36:1 + --> $DIR/missing-const-stability.rs:37:1 | LL | pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,5 +26,5 @@ error: associated function has missing const stability attribute LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/traits/const-traits/auxiliary/staged-api.rs b/tests/ui/traits/const-traits/auxiliary/staged-api.rs index abe22db702c..933a25769dc 100644 --- a/tests/ui/traits/const-traits/auxiliary/staged-api.rs +++ b/tests/ui/traits/const-traits/auxiliary/staged-api.rs @@ -4,6 +4,7 @@ #![stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "unstable", issue = "none")] #[const_trait] pub trait MyTrait { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/tests/ui/traits/const-traits/call-const-trait-method-pass.rs b/tests/ui/traits/const-traits/call-const-trait-method-pass.rs index b854b422b3a..3004647ede0 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-pass.rs +++ b/tests/ui/traits/const-traits/call-const-trait-method-pass.rs @@ -1,6 +1,6 @@ //@ known-bug: #110395 -#![feature(const_trait_impl)] +#![feature(const_trait_impl, const_ops)] struct Int(i32); diff --git a/tests/ui/traits/const-traits/const-and-non-const-impl.rs b/tests/ui/traits/const-traits/const-and-non-const-impl.rs index 6b96fcf0ae3..85e2c5d3df6 100644 --- a/tests/ui/traits/const-traits/const-and-non-const-impl.rs +++ b/tests/ui/traits/const-traits/const-and-non-const-impl.rs @@ -1,6 +1,6 @@ //@ known-bug: #110395 -#![feature(const_trait_impl)] +#![feature(const_trait_impl, const_ops)] pub struct Int(i32); diff --git a/tests/ui/traits/const-traits/generic-bound.rs b/tests/ui/traits/const-traits/generic-bound.rs index 5eb236acde2..99de21471b2 100644 --- a/tests/ui/traits/const-traits/generic-bound.rs +++ b/tests/ui/traits/const-traits/generic-bound.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(const_trait_impl)] +#![feature(const_trait_impl, const_ops)] use std::marker::PhantomData; diff --git a/tests/ui/traits/const-traits/syntactical-unstable.rs b/tests/ui/traits/const-traits/syntactical-unstable.rs new file mode 100644 index 00000000000..e192e80fabd --- /dev/null +++ b/tests/ui/traits/const-traits/syntactical-unstable.rs @@ -0,0 +1,34 @@ +//@ aux-build:staged-api.rs + +// Ensure that we enforce const stability of traits in `~const`/`const` bounds. + +#![feature(const_trait_impl)] + +use std::ops::Deref; + +extern crate staged_api; +use staged_api::MyTrait; + +#[const_trait] +trait Foo: ~const MyTrait { + //~^ ERROR use of unstable const library feature `unstable` + type Item: ~const MyTrait; + //~^ ERROR use of unstable const library feature `unstable` +} + +const fn where_clause<T>() where T: ~const MyTrait {} +//~^ ERROR use of unstable const library feature `unstable` + +const fn nested<T>() where T: Deref<Target: ~const MyTrait> {} +//~^ ERROR use of unstable const library feature `unstable` + +const fn rpit() -> impl ~const MyTrait { Local } +//~^ ERROR use of unstable const library feature `unstable` + +struct Local; +impl const MyTrait for Local { +//~^ ERROR use of unstable const library feature `unstable` + fn func() {} +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/syntactical-unstable.stderr b/tests/ui/traits/const-traits/syntactical-unstable.stderr new file mode 100644 index 00000000000..a2ce2f2b6e9 --- /dev/null +++ b/tests/ui/traits/const-traits/syntactical-unstable.stderr @@ -0,0 +1,67 @@ +error[E0658]: use of unstable const library feature `unstable` + --> $DIR/syntactical-unstable.rs:13:19 + | +LL | trait Foo: ~const MyTrait { + | ------ ^^^^^^^ + | | + | trait is not stable as const yet + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable const library feature `unstable` + --> $DIR/syntactical-unstable.rs:19:44 + | +LL | const fn where_clause<T>() where T: ~const MyTrait {} + | ------ ^^^^^^^ + | | + | trait is not stable as const yet + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable const library feature `unstable` + --> $DIR/syntactical-unstable.rs:22:52 + | +LL | const fn nested<T>() where T: Deref<Target: ~const MyTrait> {} + | ------ ^^^^^^^ + | | + | trait is not stable as const yet + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable const library feature `unstable` + --> $DIR/syntactical-unstable.rs:25:32 + | +LL | const fn rpit() -> impl ~const MyTrait { Local } + | ------ ^^^^^^^ + | | + | trait is not stable as const yet + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable const library feature `unstable` + --> $DIR/syntactical-unstable.rs:29:12 + | +LL | impl const MyTrait for Local { + | ^^^^^^^ trait is not stable as const yet + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable const library feature `unstable` + --> $DIR/syntactical-unstable.rs:15:23 + | +LL | type Item: ~const MyTrait; + | ------ ^^^^^^^ + | | + | trait is not stable as const yet + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/trait-default-body-stability.rs b/tests/ui/traits/const-traits/trait-default-body-stability.rs index 5f7486eb176..567f1b3c284 100644 --- a/tests/ui/traits/const-traits/trait-default-body-stability.rs +++ b/tests/ui/traits/const-traits/trait-default-body-stability.rs @@ -38,6 +38,7 @@ impl const FromResidual for T { } #[stable(feature = "foo", since = "1.0")] +#[rustc_const_unstable(feature = "const_tr", issue = "none")] #[const_trait] pub trait Tr { #[stable(feature = "foo", since = "1.0")] diff --git a/tests/ui/traits/const-traits/trait-default-body-stability.stderr b/tests/ui/traits/const-traits/trait-default-body-stability.stderr index 77b81211e81..a13d9a1e075 100644 --- a/tests/ui/traits/const-traits/trait-default-body-stability.stderr +++ b/tests/ui/traits/const-traits/trait-default-body-stability.stderr @@ -17,7 +17,7 @@ LL | impl const FromResidual for T { = note: adding a non-const method body in the future would be a breaking change error[E0015]: `?` is not allowed on `T` in constant functions - --> $DIR/trait-default-body-stability.rs:45:9 + --> $DIR/trait-default-body-stability.rs:46:9 | LL | T? | ^^ @@ -25,7 +25,7 @@ LL | T? = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error[E0015]: `?` is not allowed on `T` in constant functions - --> $DIR/trait-default-body-stability.rs:45:9 + --> $DIR/trait-default-body-stability.rs:46:9 | LL | T? | ^^