diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 51282b900ed14..83be929776b0f 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -17,6 +17,8 @@ use crate::traits::Obligation; pub enum ScrubbedTraitError<'tcx> { /// A real error. This goal definitely does not hold. TrueError, + // A select error with pending obligations + Select(PredicateObligations<'tcx>), /// An ambiguity. This goal may hold if further inference is done. Ambiguity, /// An old-solver-style cycle error, which will fatal. @@ -26,7 +28,7 @@ pub enum ScrubbedTraitError<'tcx> { impl<'tcx> ScrubbedTraitError<'tcx> { pub fn is_true_error(&self) -> bool { match self { - ScrubbedTraitError::TrueError => true, + ScrubbedTraitError::TrueError | ScrubbedTraitError::Select(_) => true, ScrubbedTraitError::Ambiguity | ScrubbedTraitError::Cycle(_) => false, } } 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 4fb02f609438e..d2d766666a457 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 @@ -14,6 +14,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, LangItem, Node}; use rustc_infer::infer::{InferOk, TypeTrace}; +use rustc_infer::traits::ScrubbedTraitError; use rustc_middle::traits::SignatureMismatchData; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; @@ -1852,7 +1853,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { terrs.push(terr); } - if !ocx.select_where_possible().is_empty() { + + let errors = ocx.select_where_possible(); + + if !errors.is_empty() { + for error in errors.iter() { + if let ScrubbedTraitError::Select(obligations) = error { + for obligation in obligations.iter() { + let predicate = &obligation.predicate; + err.help(format!( + "the following constraint is not satisfied: `{}`", + predicate + )); + } + } + } return false; } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 7529ee128f5e4..d297a407f60db 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -942,8 +942,13 @@ impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for FulfillmentError<'tcx impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for ScrubbedTraitError<'tcx> { fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self { match error.0.error { - FulfillmentErrorCode::Select(_) - | FulfillmentErrorCode::Project(_) + FulfillmentErrorCode::Select(_) => { + let pendings_obligations = + error.0.backtrace.into_iter().map(|p| p.obligation).collect(); + + ScrubbedTraitError::Select(pendings_obligations) + } + FulfillmentErrorCode::Project(_) | FulfillmentErrorCode::Subtype(_, _) | FulfillmentErrorCode::ConstEquate(_, _) => ScrubbedTraitError::TrueError, FulfillmentErrorCode::Ambiguity { overflow: _ } => ScrubbedTraitError::Ambiguity,