From c8ebff6aeea5bc9242269e5f072442db62be734b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 21 Dec 2022 05:07:50 +0000 Subject: [PATCH 1/5] Remove some unnecessary try_map_bound --- .../src/traits/error_reporting/suggestions.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) 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 036e8f6d47bba..60f67491364df 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3185,14 +3185,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx) && let Some(pred) = predicates.predicates.get(*idx) { - if let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred { - ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred), - _ => Err(()), - }) - && let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred { - ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred), - _ => Err(()), - }) + if let Some(trait_pred) = pred.to_opt_poly_trait_pred() + && let Some(trait_predicate) = predicate.to_opt_poly_trait_pred() { let mut c = CollectAllMismatches { infcx: self.infcx, From 0c09e2bf5afb535aa7e84bbcd8cce509a0e015b1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 21 Dec 2022 05:36:26 +0000 Subject: [PATCH 2/5] Substitute things correctly --- .../src/traits/error_reporting/suggestions.rs | 3 ++- src/test/ui/iterators/invalid-iterator-chain.stderr | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) 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 60f67491364df..1edc9357e12c4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3182,7 +3182,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut type_diffs = vec![]; if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref() - && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx) + && let Some(node_substs) = typeck_results.node_substs_opt(call_hir_id) + && let predicates = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_substs) && let Some(pred) = predicates.predicates.get(*idx) { if let Some(trait_pred) = pred.to_opt_poly_trait_pred() diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index d76a4bfb7b3ea..f3dceca7e4139 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -52,14 +52,14 @@ LL | .sum::(), > note: the method call chain might not have had the expected associated types - --> $DIR/invalid-iterator-chain.rs:20:14 + --> $DIR/invalid-iterator-chain.rs:25:14 | LL | vec![0, 1] | ---------- this expression has type `Vec<{integer}>` LL | .iter() | ------ `Iterator::Item` is `&{integer}` here LL | .map(|x| x * 2) - | ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here + | -------------- `Iterator::Item` changed to `{integer}` here LL | .map(|x| x as f64) | ----------------- `Iterator::Item` changed to `f64` here LL | .map(|x| x as i64) @@ -84,14 +84,14 @@ LL | .sum::(), > note: the method call chain might not have had the expected associated types - --> $DIR/invalid-iterator-chain.rs:32:14 + --> $DIR/invalid-iterator-chain.rs:33:14 | LL | vec![0, 1] | ---------- this expression has type `Vec<{integer}>` LL | .iter() | ------ `Iterator::Item` is `&{integer}` here LL | .map(|x| x * 2) - | ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here + | -------------- `Iterator::Item` changed to `{integer}` here LL | .map(|x| x as f64) | ^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `f64` here LL | .filter(|x| *x > 0.0) From 978dd2e3b804ebbb39684aaabcea5c0a39bd59d9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 21 Dec 2022 05:53:55 +0000 Subject: [PATCH 3/5] Rename things to be a bit clearer --- .../src/traits/error_reporting/suggestions.rs | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) 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 1edc9357e12c4..ba1ef3248667c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3147,7 +3147,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err: &mut Diagnostic, parent_code: &ObligationCauseCode<'tcx>, param_env: ty::ParamEnv<'tcx>, - predicate: ty::Predicate<'tcx>, + failed_pred: ty::Predicate<'tcx>, call_hir_id: HirId, ) { let tcx = self.tcx; @@ -3183,31 +3183,28 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref() && let Some(node_substs) = typeck_results.node_substs_opt(call_hir_id) - && let predicates = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_substs) - && let Some(pred) = predicates.predicates.get(*idx) + && let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_substs) + && let Some(where_pred) = where_clauses.predicates.get(*idx) { - if let Some(trait_pred) = pred.to_opt_poly_trait_pred() - && let Some(trait_predicate) = predicate.to_opt_poly_trait_pred() + if let Some(where_pred) = where_pred.to_opt_poly_trait_pred() + && let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred() { let mut c = CollectAllMismatches { infcx: self.infcx, param_env, errors: vec![], }; - if let Ok(_) = c.relate(trait_pred, trait_predicate) { + if let Ok(_) = c.relate(where_pred, failed_pred) { type_diffs = c.errors; } - } else if let ty::PredicateKind::Clause( - ty::Clause::Projection(proj) - ) = pred.kind().skip_binder() - && let ty::PredicateKind::Clause( - ty::Clause::Projection(projection) - ) = predicate.kind().skip_binder() + } else if let Some(where_pred) = where_pred.to_opt_poly_projection_pred() + && let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred() + && let Some(found) = failed_pred.skip_binder().term.ty() { type_diffs = vec![ Sorts(ty::error::ExpectedFound { - expected: self.tcx.mk_ty(ty::Alias(ty::Projection, proj.projection_ty)), - found: projection.term.ty().unwrap(), + expected: self.tcx.mk_ty(ty::Alias(ty::Projection, where_pred.skip_binder().projection_ty)), + found, }), ]; } From c6ef53477ee68ace77bead81439971a71669b22f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 21 Dec 2022 05:42:48 +0000 Subject: [PATCH 4/5] CollectAllMismatches relation should respect int/float infer vars --- .../traits/error_reporting/method_chain.rs | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs index cb373d657721b..27c207528c735 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs @@ -14,21 +14,27 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> { fn tag(&self) -> &'static str { "CollectAllMismatches" } + fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } + fn intercrate(&self) -> bool { false } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env } + fn a_is_expected(&self) -> bool { true - } // irrelevant + } + fn mark_ambiguous(&mut self) { bug!() } + fn relate_with_variance>( &mut self, _: ty::Variance, @@ -38,6 +44,7 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> { ) -> RelateResult<'tcx, T> { self.relate(a, b) } + fn regions( &mut self, a: ty::Region<'tcx>, @@ -45,15 +52,20 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> { ) -> RelateResult<'tcx, ty::Region<'tcx>> { Ok(a) } + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - if a == b || matches!(a.kind(), ty::Infer(_)) || matches!(b.kind(), ty::Infer(_)) { - return Ok(a); - } - relate::super_relate_tys(self, a, b).or_else(|e| { - self.errors.push(e); - Ok(a) + self.infcx.probe(|_| { + if a.is_ty_infer() || b.is_ty_infer() { + Ok(a) + } else { + self.infcx.super_combine_tys(self, a, b).or_else(|e| { + self.errors.push(e); + Ok(a) + }) + } }) } + fn consts( &mut self, a: ty::Const<'tcx>, @@ -64,6 +76,7 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> { } relate::super_relate_consts(self, a, b) // could do something similar here for constants! } + fn binders>( &mut self, a: ty::Binder<'tcx, T>, From 85a9d85435ec60b840f54a03460412c261517d12 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 21 Dec 2022 05:49:12 +0000 Subject: [PATCH 5/5] Don't call typeck if we have no typeck results This has a 10000000% chance of us causing a cycle if we're not careful --- .../src/traits/error_reporting/suggestions.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) 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 ba1ef3248667c..eb5e1d5ad5c1d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -335,7 +335,7 @@ pub trait TypeErrCtxtExt<'tcx> { err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, ); - fn function_argument_obligation( + fn note_function_argument_obligation( &self, arg_hir_id: HirId, err: &mut Diagnostic, @@ -2909,7 +2909,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ref parent_code, .. } => { - self.function_argument_obligation( + self.note_function_argument_obligation( arg_hir_id, err, parent_code, @@ -3141,7 +3141,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } } - fn function_argument_obligation( + fn note_function_argument_obligation( &self, arg_hir_id: HirId, err: &mut Diagnostic, @@ -3152,12 +3152,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) { let tcx = self.tcx; let hir = tcx.hir(); - if let Some(Node::Expr(expr)) = hir.find(arg_hir_id) { - let parent_id = hir.get_parent_item(arg_hir_id); - let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results { - Some(t) if t.hir_owner == parent_id => t, - _ => self.tcx.typeck(parent_id.def_id), - }; + if let Some(Node::Expr(expr)) = hir.find(arg_hir_id) + && let Some(typeck_results) = &self.typeck_results + { if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr { let expr = expr.peel_blocks(); let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()); @@ -3219,9 +3216,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // If the expression we're calling on is a binding, we want to point at the // `let` when talking about the type. Otherwise we'll point at every part // of the method chain with the type. - self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err); + self.point_at_chain(binding_expr, &typeck_results, type_diffs, param_env, err); } else { - self.point_at_chain(expr, typeck_results, type_diffs, param_env, err); + self.point_at_chain(expr, &typeck_results, type_diffs, param_env, err); } } let call_node = hir.find(call_hir_id);