diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index cbd81cae98901..5862fad937e3a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -3032,8 +3032,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.report_similar_impl_candidates_for_root_obligation(&obligation, *trait_predicate, body_def_id, err); } - self.maybe_suggest_convert_to_slice( + self.suggest_convert_to_slice( err, + obligation, trait_ref, impl_candidates.as_slice(), span, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 1eb4447ae4eeb..973e27280ee7d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -398,9 +398,10 @@ pub trait TypeErrCtxtExt<'tcx> { param_env: ty::ParamEnv<'tcx>, ) -> Vec))>>; - fn maybe_suggest_convert_to_slice( + fn suggest_convert_to_slice( &self, err: &mut Diagnostic, + obligation: &PredicateObligation<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, candidate_impls: &[ImplCandidate<'tcx>], span: Span, @@ -3954,13 +3955,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { /// If the type that failed selection is an array or a reference to an array, /// but the trait is implemented for slices, suggest that the user converts /// the array into a slice. - fn maybe_suggest_convert_to_slice( + fn suggest_convert_to_slice( &self, err: &mut Diagnostic, + obligation: &PredicateObligation<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, candidate_impls: &[ImplCandidate<'tcx>], span: Span, ) { + // We can only suggest the slice coersion for function arguments since the suggestion + // would make no sense in turbofish or call + let ObligationCauseCode::FunctionArgumentObligation { .. } = obligation.cause.code() else { + return; + }; + // Three cases where we can make a suggestion: // 1. `[T; _]` (array of T) // 2. `&[T; _]` (reference to array of T) diff --git a/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.rs b/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.rs new file mode 100644 index 0000000000000..c6ef8379f455c --- /dev/null +++ b/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.rs @@ -0,0 +1,13 @@ +trait Test {} +impl Test for &[u8] {} + +fn needs_test() -> T { + panic!() +} + +fn main() { + needs_test::<[u8; 1]>(); + //~^ ERROR the trait bound + let x: [u8; 1] = needs_test(); + //~^ ERROR the trait bound +} diff --git a/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.stderr b/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.stderr new file mode 100644 index 0000000000000..6752a484448c5 --- /dev/null +++ b/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `[u8; 1]: Test` is not satisfied + --> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:9:18 + | +LL | needs_test::<[u8; 1]>(); + | ^^^^^^^ the trait `Test` is not implemented for `[u8; 1]` + | + = help: the trait `Test` is implemented for `&[u8]` +note: required by a bound in `needs_test` + --> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:4:18 + | +LL | fn needs_test() -> T { + | ^^^^ required by this bound in `needs_test` + +error[E0277]: the trait bound `[u8; 1]: Test` is not satisfied + --> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:11:22 + | +LL | let x: [u8; 1] = needs_test(); + | ^^^^^^^^^^ the trait `Test` is not implemented for `[u8; 1]` + | + = help: the trait `Test` is implemented for `&[u8]` +note: required by a bound in `needs_test` + --> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:4:18 + | +LL | fn needs_test() -> T { + | ^^^^ required by this bound in `needs_test` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`.