diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 46953a61296..642bb3a6e1b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -414,7 +414,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { let trait_predicate = bound_predicate.rebind(trait_predicate); let trait_predicate = self.resolve_vars_if_possible(trait_predicate); - let trait_predicate = self.apply_do_not_recommend(trait_predicate, &mut obligation); // Let's use the root obligation as the main message, when we care about the // most general case ("X doesn't implement Pattern<'_>") over the case that @@ -996,12 +995,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { err.emit() } - fn apply_do_not_recommend( - &self, - mut trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, - obligation: &'_ mut PredicateObligation<'tcx>, - ) -> ty::Binder<'tcx, ty::TraitPredicate<'tcx>> { + fn apply_do_not_recommend(&self, obligation: &mut PredicateObligation<'tcx>) -> bool { let mut base_cause = obligation.cause.code().clone(); + let mut applied_do_not_recommend = false; loop { if let ObligationCauseCode::ImplDerived(ref c) = base_cause { if self.tcx.has_attrs_with_path( @@ -1011,7 +1007,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let code = (*c.derived.parent_code).clone(); obligation.cause.map_code(|_| code); obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx); - trait_predicate = c.derived.parent_trait_pred.clone(); + applied_do_not_recommend = true; } } if let Some((parent_cause, _parent_pred)) = base_cause.parent() { @@ -1021,7 +1017,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } - trait_predicate + applied_do_not_recommend } fn emit_specialized_closure_kind_error( @@ -1521,6 +1517,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { #[instrument(skip(self), level = "debug")] fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed { + let mut error = FulfillmentError { + obligation: error.obligation.clone(), + code: error.code.clone(), + root_obligation: error.root_obligation.clone(), + }; + if matches!( + error.code, + FulfillmentErrorCode::Select(crate::traits::SelectionError::Unimplemented) + | FulfillmentErrorCode::Project(_) + ) && self.apply_do_not_recommend(&mut error.obligation) + { + error.code = FulfillmentErrorCode::Select(SelectionError::Unimplemented); + } + match error.code { FulfillmentErrorCode::Select(ref selection_error) => self.report_selection_error( error.obligation.clone(), diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr new file mode 100644 index 00000000000..bcede8a255f --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr @@ -0,0 +1,15 @@ +error[E0277]: Very important message! + --> $DIR/type_mismatch.rs:25:14 + | +LL | verify::(); + | ^^ the trait `TheImportantOne` is not implemented for `u8` + | +note: required by a bound in `verify` + --> $DIR/type_mismatch.rs:22:14 + | +LL | fn verify() {} + | ^^^^^^^^^^^^^^^ required by this bound in `verify` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr new file mode 100644 index 00000000000..bcede8a255f --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr @@ -0,0 +1,15 @@ +error[E0277]: Very important message! + --> $DIR/type_mismatch.rs:25:14 + | +LL | verify::(); + | ^^ the trait `TheImportantOne` is not implemented for `u8` + | +note: required by a bound in `verify` + --> $DIR/type_mismatch.rs:22:14 + | +LL | fn verify() {} + | ^^^^^^^^^^^^^^^ required by this bound in `verify` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs new file mode 100644 index 00000000000..d6721ccc848 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs @@ -0,0 +1,27 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(do_not_recommend)] + +#[diagnostic::on_unimplemented(message = "Very important message!")] +trait TheImportantOne {} + +trait ImplementationDetail { + type Restriction; +} + +#[diagnostic::do_not_recommend] +impl> TheImportantOne for T {} + +// Comment out this `impl` to show the expected error message. +impl ImplementationDetail for u8 { + type Restriction = u8; +} + +fn verify() {} + +pub fn main() { + verify::(); + //~^ERROR: Very important message! [E0277] +}