From 4dacf4f469de4fba4ac086f87c9263ff79a3bd13 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 25 Nov 2022 12:35:49 -0300 Subject: [PATCH 1/2] Use ocx.normalize in report_projection_error --- .../src/traits/engine.rs | 18 ++++++++ .../src/traits/error_reporting/mod.rs | 43 +++++++++++-------- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 64d01ddb09a49..c028e89e4ea29 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -112,6 +112,24 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { self.register_infer_ok_obligations(infer_ok) } + /// Makes `expected <: actual`. + pub fn eq_exp( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + a_is_expected: bool, + a: T, + b: T, + ) -> Result<(), TypeError<'tcx>> + where + T: ToTrace<'tcx>, + { + self.infcx + .at(cause, param_env) + .eq_exp(a_is_expected, a, b) + .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) + } + pub fn eq>( &self, cause: &ObligationCause<'tcx>, 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 049b24b39975d..203f6724cb25b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1576,9 +1576,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { return; } + let mut values = None; + self.probe(|_| { + let ocx = ObligationCtxt::new_in_snapshot(self); let mut err = error.err; - let mut values = None; // try to find the mismatched types to report the error with. // @@ -1588,21 +1590,16 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let ty::PredicateKind::Clause(ty::Clause::Projection(data)) = bound_predicate.skip_binder() { - let mut selcx = SelectionContext::new(self); let data = self.replace_bound_vars_with_fresh_vars( obligation.cause.span, infer::LateBoundRegionConversionTime::HigherRankedType, bound_predicate.rebind(data), ); - let mut obligations = vec![]; - // FIXME(normalization): Change this to use `At::normalize` - let normalized_ty = super::normalize_projection_type( - &mut selcx, + let normalized_ty = ocx.normalize( + &obligation.cause, obligation.param_env, - data.projection_ty, - obligation.cause.clone(), - 0, - &mut obligations, + self.tcx + .mk_projection(data.projection_ty.item_def_id, data.projection_ty.substs), ); debug!(?obligation.cause, ?obligation.param_env); @@ -1618,19 +1615,31 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | ObligationCauseCode::ObjectCastObligation(..) | ObligationCauseCode::OpaqueType ); - if let Err(new_err) = self.at(&obligation.cause, obligation.param_env).eq_exp( + let expected_ty = data.term.ty().unwrap(); + + // constrain inference variables a bit more to nested obligations from normalize so + // we can have more helpful errors. + ocx.select_where_possible(); + + if let Err(new_err) = ocx.eq_exp( + &obligation.cause, + obligation.param_env, is_normalized_ty_expected, normalized_ty, - data.term, + expected_ty, ) { - values = Some((data, is_normalized_ty_expected, normalized_ty, data.term)); + values = Some((data, is_normalized_ty_expected, normalized_ty, expected_ty)); err = new_err; } } let msg = values .and_then(|(predicate, _, normalized_ty, expected_ty)| { - self.maybe_detailed_projection_msg(predicate, normalized_ty, expected_ty) + self.maybe_detailed_projection_msg( + predicate, + normalized_ty.into(), + expected_ty.into(), + ) }) .unwrap_or_else(|| format!("type mismatch resolving `{}`", predicate)); let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}"); @@ -1672,11 +1681,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &mut diag, &obligation.cause, secondary_span, - values.map(|(_, is_normalized_ty_expected, normalized_ty, term)| { + values.map(|(_, is_normalized_ty_expected, normalized_ty, expected_ty)| { infer::ValuePairs::Terms(ExpectedFound::new( is_normalized_ty_expected, - normalized_ty, - term, + normalized_ty.into(), + expected_ty.into(), )) }), err, From 89047430f1233439ca666cc1b05a41ac4da924b7 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 30 Nov 2022 12:59:22 -0300 Subject: [PATCH 2/2] Define values and err as non mutable --- .../src/traits/error_reporting/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 203f6724cb25b..84e951e80230b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1576,18 +1576,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { return; } - let mut values = None; - self.probe(|_| { let ocx = ObligationCtxt::new_in_snapshot(self); - let mut err = error.err; // try to find the mismatched types to report the error with. // // this can fail if the problem was higher-ranked, in which // cause I have no idea for a good error message. let bound_predicate = predicate.kind(); - if let ty::PredicateKind::Clause(ty::Clause::Projection(data)) = + let (values, err) = if let ty::PredicateKind::Clause(ty::Clause::Projection(data)) = bound_predicate.skip_binder() { let data = self.replace_bound_vars_with_fresh_vars( @@ -1628,10 +1625,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { normalized_ty, expected_ty, ) { - values = Some((data, is_normalized_ty_expected, normalized_ty, expected_ty)); - err = new_err; + (Some((data, is_normalized_ty_expected, normalized_ty, expected_ty)), new_err) + } else { + (None, error.err) } - } + } else { + (None, error.err) + }; let msg = values .and_then(|(predicate, _, normalized_ty, expected_ty)| {