diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index dbf5465ee18b3..689911000ea8c 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -217,16 +217,26 @@ fn ensure_all_fields_are_const_destruct<'tcx>( unreachable!() }; let field_ty = eff.trait_ref.self_ty(); - let diag = struct_span_code_err!( + let mut diag = struct_span_code_err!( tcx.dcx(), error.root_obligation.cause.span, E0367, "`{field_ty}` does not implement `[const] Destruct`", ) .with_span_note(impl_span, "required for this `Drop` impl"); - if field_ty.has_param() { - // FIXME: suggest adding `[const] Destruct` by teaching - // `suggest_restricting_param_bound` about const traits. + if field_ty.has_param() + && let Some(generics) = tcx.hir_node_by_def_id(impl_def_id).generics() + { + let destruct_def_id = tcx.lang_items().destruct_trait(); + ty::suggest_constraining_type_param( + tcx, + generics, + &mut diag, + &field_ty.to_string(), + "[const] Destruct", + destruct_def_id, + None, + ); } Err(diag.emit()) }) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 0d6cd53dacab2..c46c042c886f7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -25,8 +25,8 @@ use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::{ - PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _, PrintTraitRefExt as _, - with_forced_trimmed_paths, + PrintPolyTraitPredicateExt, PrintPolyTraitRefExt as _, PrintTraitPredicateExt as _, + PrintTraitRefExt as _, with_forced_trimmed_paths, }; use rustc_middle::ty::{ self, GenericArgKind, TraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, @@ -886,6 +886,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } } + } else if let ty::Param(param) = trait_ref.self_ty().skip_binder().kind() + && let Some(generics) = + self.tcx.hir_node_by_def_id(main_obligation.cause.body_id).generics() + { + let constraint = ty::print::with_no_trimmed_paths!(format!( + "[const] {}", + trait_ref.map_bound(|tr| tr.trait_ref).print_trait_sugared(), + )); + ty::suggest_constraining_type_param( + self.tcx, + generics, + &mut diag, + param.name.as_str(), + &constraint, + Some(trait_ref.def_id()), + None, + ); } diag } @@ -2708,7 +2725,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn predicate_can_apply( &self, param_env: ty::ParamEnv<'tcx>, - pred: ty::PolyTraitPredicate<'tcx>, + pred: impl Upcast, ty::Predicate<'tcx>> + TypeFoldable>, ) -> bool { struct ParamToVarFolder<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, diff --git a/tests/ui/consts/drop-impl-nonconst-drop-field.stderr b/tests/ui/consts/drop-impl-nonconst-drop-field.stderr index 0e626176579c6..5a81044dfadb7 100644 --- a/tests/ui/consts/drop-impl-nonconst-drop-field.stderr +++ b/tests/ui/consts/drop-impl-nonconst-drop-field.stderr @@ -21,6 +21,10 @@ note: required for this `Drop` impl | LL | impl const Drop for ConstDrop2 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider restricting type parameter `T` with unstable trait `Destruct` + | +LL | impl const Drop for ConstDrop2 { + | ++++++++++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/consts/trait_alias.fail.stderr b/tests/ui/consts/trait_alias.fail.stderr index 16675206a7a4b..62f5ab1a7d2cd 100644 --- a/tests/ui/consts/trait_alias.fail.stderr +++ b/tests/ui/consts/trait_alias.fail.stderr @@ -3,6 +3,11 @@ error[E0277]: the trait bound `T: [const] Baz` is not satisfied | LL | x.baz(); | ^^^ + | +help: consider further restricting type parameter `T` with trait `Baz` + | +LL | const fn foo(x: &T) { + | +++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/consts/trait_alias.next_fail.stderr b/tests/ui/consts/trait_alias.next_fail.stderr index 16675206a7a4b..62f5ab1a7d2cd 100644 --- a/tests/ui/consts/trait_alias.next_fail.stderr +++ b/tests/ui/consts/trait_alias.next_fail.stderr @@ -3,6 +3,11 @@ error[E0277]: the trait bound `T: [const] Baz` is not satisfied | LL | x.baz(); | ^^^ + | +help: consider further restricting type parameter `T` with trait `Baz` + | +LL | const fn foo(x: &T) { + | +++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr index 65c6f833ccea1..3e93ce8cbd7a6 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr @@ -15,6 +15,11 @@ error[E0277]: the trait bound `T: [const] Foo` is not satisfied | LL | x.a(); | ^ + | +help: consider further restricting type parameter `T` with trait `Foo` + | +LL | const fn foo(x: &T) { + | +++++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr index c17a67132116e..ea637e1ab8db8 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr @@ -3,6 +3,11 @@ error[E0277]: the trait bound `T: [const] Foo` is not satisfied | LL | x.a(); | ^ + | +help: consider further restricting type parameter `T` with trait `Foo` + | +LL | const fn foo(x: &T) { + | +++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr index 7b5a1f7a6a230..6fd236a0de4fe 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr @@ -38,6 +38,11 @@ error[E0277]: the trait bound `T: [const] Foo` is not satisfied | LL | x.a(); | ^ + | +help: consider further restricting type parameter `T` with trait `Foo` + | +LL | const fn foo(x: &T) { + | +++++++++++++ error: aborting due to 4 previous errors