From 2ab69ba970db4e85151dc25cc0cc9796b6ac2bba Mon Sep 17 00:00:00 2001 From: Jacob Adam Date: Wed, 8 Apr 2026 21:08:27 +0100 Subject: [PATCH 1/2] Suggest the `[const] Destruct` bound for type parameters in const functions When a const function drops a value whose type is a type parameter, suggest adding a `[const] Destruct` bound so the destructor can be evaluated at compile-time. --- .../rustc_const_eval/src/check_consts/ops.rs | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index d64cf8e032935..a2f5be5fb64ce 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -591,7 +591,7 @@ impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> { } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - if self.needs_non_const_drop { + let mut err = if self.needs_non_const_drop { ccx.dcx().create_err(errors::LiveDrop { span, dropped_ty: self.dropped_ty, @@ -608,7 +608,27 @@ impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> { }, sym::const_destruct, ) + }; + + // If the dropped type is a type parameter, suggest adding a `[const] Destruct` bound. + if let Param(param_ty) = self.dropped_ty.kind() { + let tcx = ccx.tcx; + let caller = ccx.def_id(); + if let Some(generics) = tcx.hir_node_by_def_id(caller).generics() { + let destruct_def_id = tcx.lang_items().destruct_trait(); + suggest_constraining_type_param( + tcx, + generics, + &mut err, + param_ty.name.as_str(), + "[const] Destruct", + destruct_def_id, + None, + ); + } } + + err } } From 2f950f95dc9e3edcb7a6d8efc50b63ce167d03ee Mon Sep 17 00:00:00 2001 From: Jacob Adam Date: Wed, 8 Apr 2026 21:38:07 +0100 Subject: [PATCH 2/2] Bless tests affected by the `[const] Destruct` suggestion --- tests/ui/consts/min_const_fn/min_const_fn.stderr | 5 +++++ tests/ui/consts/unstable-const-fn-in-libcore.stderr | 5 +++++ tests/ui/static/static-drop-scope.stderr | 5 +++++ tests/ui/traits/const-traits/minicore-drop-fail.stderr | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/tests/ui/consts/min_const_fn/min_const_fn.stderr b/tests/ui/consts/min_const_fn/min_const_fn.stderr index 0e939e5121aa9..0904de2af0d46 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn.stderr @@ -73,6 +73,11 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} | ^^ - value is dropped here | | | the destructor for this type cannot be evaluated in constant functions + | +help: consider restricting opaque type `impl std::fmt::Debug` with unstable trait `Destruct` + | +LL | const fn no_apit(_x: impl std::fmt::Debug + [const] Destruct) {} + | ++++++++++++++++++ error: aborting due to 9 previous errors diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index 16db7791cd849..9dcd2b0ac0326 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -6,6 +6,11 @@ LL | const fn unwrap_or_else T>(self, f: F) -> T { ... LL | } | - value is dropped here + | +help: consider further restricting type parameter `F` with unstable trait `Destruct` + | +LL | const fn unwrap_or_else T + [const] Destruct>(self, f: F) -> T { + | ++++++++++++++++++ error[E0493]: destructor of `Opt` cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:19:55 diff --git a/tests/ui/static/static-drop-scope.stderr b/tests/ui/static/static-drop-scope.stderr index 0fdf081e23432..84e99a3988121 100644 --- a/tests/ui/static/static-drop-scope.stderr +++ b/tests/ui/static/static-drop-scope.stderr @@ -37,6 +37,11 @@ LL | const fn const_drop(_: T) {} | ^ - value is dropped here | | | the destructor for this type cannot be evaluated in constant functions + | +help: consider restricting type parameter `T` with unstable trait `Destruct` + | +LL | const fn const_drop(_: T) {} + | ++++++++++++++++++ error[E0493]: destructor of `(T, ())` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:17:5 diff --git a/tests/ui/traits/const-traits/minicore-drop-fail.stderr b/tests/ui/traits/const-traits/minicore-drop-fail.stderr index 12d1877a18aba..2cb1256e37667 100644 --- a/tests/ui/traits/const-traits/minicore-drop-fail.stderr +++ b/tests/ui/traits/const-traits/minicore-drop-fail.stderr @@ -30,6 +30,11 @@ LL | const fn drop_arbitrary(_: T) { LL | LL | } | - value is dropped here + | +help: consider restricting type parameter `T` with trait `Destruct` + | +LL | const fn drop_arbitrary(_: T) { + | ++++++++++++++++++ error: aborting due to 4 previous errors