From f84000d9bc93f7c09243144d1a729448da3d714d Mon Sep 17 00:00:00 2001 From: Waffle Date: Thu, 16 Sep 2021 20:57:12 +0300 Subject: [PATCH] Add a separate error for `dyn Trait` in `const fn` Previously "trait bounds other than `Sized` on const fn parameters are unstable" error was used for both trait bounds () and trait objects (dyn Trait). This was pretty confusing. This patch adds a separeta error for trait objects: "trait objects in const fn are unstable". The error for trait bounds is otherwise intact. --- .../src/transform/check_consts/check.rs | 4 +- .../src/transform/check_consts/ops.rs | 45 +++++++++++++++++-- src/test/ui/consts/const_fn_trait_bound.rs | 4 +- .../consts/const_fn_trait_bound.stock.stderr | 4 +- .../ui/consts/min_const_fn/min_const_fn.rs | 10 ++--- .../consts/min_const_fn/min_const_fn.stderr | 10 ++--- .../consts/min_const_fn/min_const_fn_dyn.rs | 4 +- .../min_const_fn/min_const_fn_dyn.stderr | 4 +- 8 files changed, 62 insertions(+), 23 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 d02b4286c17..ce957331b4b 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -384,11 +384,11 @@ fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) { match pred.skip_binder() { ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => { - self.check_op(ops::ty::TraitBound(kind)) + self.check_op(ops::ty::DynTrait(kind)) } ty::ExistentialPredicate::Trait(trait_ref) => { if Some(trait_ref.def_id) != self.tcx.lang_items().sized_trait() { - self.check_op(ops::ty::TraitBound(kind)) + self.check_op(ops::ty::DynTrait(kind)) } } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 2a296750838..1d0ee949a22 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -599,7 +599,7 @@ fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - let mut builder = feature_err( + let mut err = feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_trait_bound, span, @@ -608,12 +608,51 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder< match ccx.fn_sig() { Some(fn_sig) if !fn_sig.span.contains(span) => { - builder.span_label(fn_sig.span, "function declared as const here"); + err.span_label(fn_sig.span, "function declared as const here"); } _ => {} } - builder + err + } + } + + #[derive(Debug)] + pub struct DynTrait(pub mir::LocalKind); + impl NonConstOp for DynTrait { + fn importance(&self) -> DiagnosticImportance { + match self.0 { + mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary, + mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => { + DiagnosticImportance::Primary + } + } + } + + fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { + if ccx.const_kind() != hir::ConstContext::ConstFn { + Status::Allowed + } else { + Status::Unstable(sym::const_fn_trait_bound) + } + } + + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + let mut err = feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_fn_trait_bound, + span, + "trait objects in const fn are unstable", + ); + + match ccx.fn_sig() { + Some(fn_sig) if !fn_sig.span.contains(span) => { + err.span_label(fn_sig.span, "function declared as const here"); + } + _ => {} + } + + err } } diff --git a/src/test/ui/consts/const_fn_trait_bound.rs b/src/test/ui/consts/const_fn_trait_bound.rs index b1ef820d827..19c08b62144 100644 --- a/src/test/ui/consts/const_fn_trait_bound.rs +++ b/src/test/ui/consts/const_fn_trait_bound.rs @@ -8,9 +8,9 @@ const fn test1() {} //[stock]~^ trait bounds const fn test2(_x: &dyn Send) {} -//[stock]~^ trait bounds +//[stock]~^ trait objects in const fn are unstable const fn test3() -> &'static dyn Send { loop {} } -//[stock]~^ trait bounds +//[stock]~^ trait objects in const fn are unstable #[rustc_error] diff --git a/src/test/ui/consts/const_fn_trait_bound.stock.stderr b/src/test/ui/consts/const_fn_trait_bound.stock.stderr index 2ad45f3afde..d652b5268a8 100644 --- a/src/test/ui/consts/const_fn_trait_bound.stock.stderr +++ b/src/test/ui/consts/const_fn_trait_bound.stock.stderr @@ -7,7 +7,7 @@ LL | const fn test1() {} = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/const_fn_trait_bound.rs:10:16 | LL | const fn test2(_x: &dyn Send) {} @@ -16,7 +16,7 @@ LL | const fn test2(_x: &dyn Send) {} = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/const_fn_trait_bound.rs:12:21 | LL | const fn test3() -> &'static dyn Send { loop {} } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs index bb525d57197..10347a02074 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs @@ -130,16 +130,16 @@ const fn no_apit(_x: impl std::fmt::Debug) {} //~^ ERROR trait bounds other than `Sized` //~| ERROR destructor const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} -//~^ ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } -//~^ ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable const fn no_unsafe() { unsafe {} } const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } -//~^ ERROR trait bounds other than `Sized` -//~| ERROR trait bounds other than `Sized` -//~| ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable +//~| ERROR trait objects in const fn are unstable +//~| ERROR trait objects in const fn are unstable const fn no_fn_ptrs(_x: fn()) {} //~^ ERROR function pointer diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index d1c2a04d6a6..1e275d77bac 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -279,7 +279,7 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} | | | constant functions cannot evaluate destructors -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:132:23 | LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} @@ -288,7 +288,7 @@ LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:134:32 | LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } @@ -297,7 +297,7 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:139:41 | LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } @@ -308,7 +308,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:139:42 | LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } @@ -319,7 +319,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:139:42 | LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs index 6ca1e59b3af..1ab8253b414 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs @@ -7,9 +7,9 @@ struct HasDyn { const fn no_inner_dyn_trait(_x: Hide) {} const fn no_inner_dyn_trait2(x: Hide) { x.0.field; -//~^ ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable } const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } -//~^ ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr index 2cad8a862be..6eec1df5aec 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr @@ -1,4 +1,4 @@ -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn_dyn.rs:9:5 | LL | const fn no_inner_dyn_trait2(x: Hide) { @@ -9,7 +9,7 @@ LL | x.0.field; = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn_dyn.rs:12:66 | LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }