From bc60d50eaa045f6c17b1c127e486d0e3232f1e89 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Dec 2022 17:34:24 +0000 Subject: [PATCH 01/12] Provide associated type information in method chains When encountering an unmet obligation that affects a method chain, like in iterator chains where one of the links has the wrong associated type, we point at every method call and mention their evaluated associated type at that point to give context to the user of where expectations diverged from the code as written. ``` note: the expression is of type `Map, [closure@$DIR/invalid-iterator-chain.rs:12:18: 12:21]>` --> $DIR/invalid-iterator-chain.rs:12:14 | LL | vec![0, 1] | ---------- this expression has type `Vec<{integer}>` LL | .iter() | ------ associated type `std::iter::Iterator::Item` is `&{integer}` here LL | .map(|x| { x; }) | ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here ``` --- .../src/traits/error_reporting/mod.rs | 6 +- .../src/traits/error_reporting/suggestions.rs | 291 ++++++++++++++++-- src/test/ui/issues/issue-34334.stderr | 8 + ...e-66923-show-error-for-correct-call.stderr | 14 + .../ui/iterators/invalid-iterator-chain.rs | 17 + .../iterators/invalid-iterator-chain.stderr | 111 +++++++ 6 files changed, 413 insertions(+), 34 deletions(-) create mode 100644 src/test/ui/iterators/invalid-iterator-chain.rs create mode 100644 src/test/ui/iterators/invalid-iterator-chain.stderr 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 dda7b2b2fa5b0..78364253adbca 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -536,7 +536,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { |err| { self.note_obligation_cause_code( err, - &predicate, + predicate, obligation.param_env, obligation.cause.code(), &mut vec![], @@ -1586,7 +1586,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { { self.note_obligation_cause_code( &mut diag, - &error.obligation.predicate, + error.obligation.predicate, error.obligation.param_env, code, &mut vec![], @@ -2601,7 +2601,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if !self.maybe_note_obligation_cause_for_async_await(err, obligation) { self.note_obligation_cause_code( err, - &obligation.predicate, + obligation.predicate, obligation.param_env, obligation.cause.code(), &mut vec![], 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 9f5814a6bda73..8bfa405cbeae1 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1,8 +1,9 @@ +// ignore-tidy-filelength use super::{DefIdOrName, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation}; use crate::autoderef::Autoderef; use crate::infer::InferCtxt; -use crate::traits::NormalizeExt; +use crate::traits::{NormalizeExt, ObligationCtxt}; use hir::def::CtorOf; use hir::HirId; @@ -22,16 +23,18 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{InferOk, LateBoundRegionConversionTime}; use rustc_middle::hir::map; +use rustc_middle::ty::error::TypeError::{self, Sorts}; +use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree, - GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, IsSuggestable, - ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, + GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts, + IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeVisitable, TypeckResults, }; -use rustc_middle::ty::{TypeAndMut, TypeckResults}; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{BytePos, DesugaringKind, ExpnKind, Span, DUMMY_SP}; use rustc_target::spec::abi; -use std::fmt; +use std::ops::Deref; use super::InferCtxtPrivExt; use crate::infer::InferCtxtExt as _; @@ -292,13 +295,13 @@ pub trait TypeErrCtxtExt<'tcx> { fn note_obligation_cause_code( &self, err: &mut Diagnostic, - predicate: &T, + predicate: T, param_env: ty::ParamEnv<'tcx>, cause_code: &ObligationCauseCode<'tcx>, obligated_types: &mut Vec>, seen_requirements: &mut FxHashSet, ) where - T: fmt::Display + ToPredicate<'tcx>; + T: ToPredicate<'tcx>; /// Suggest to await before try: future? => future.await? fn suggest_await_before_try( @@ -2336,7 +2339,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { debug!(?next_code); self.note_obligation_cause_code( err, - &obligation.predicate, + obligation.predicate, obligation.param_env, next_code.unwrap(), &mut Vec::new(), @@ -2347,15 +2350,16 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn note_obligation_cause_code( &self, err: &mut Diagnostic, - predicate: &T, + predicate: T, param_env: ty::ParamEnv<'tcx>, cause_code: &ObligationCauseCode<'tcx>, obligated_types: &mut Vec>, seen_requirements: &mut FxHashSet, ) where - T: fmt::Display + ToPredicate<'tcx>, + T: ToPredicate<'tcx>, { let tcx = self.tcx; + let predicate = predicate.to_predicate(tcx); match *cause_code { ObligationCauseCode::ExprAssignable | ObligationCauseCode::MatchExpressionArm { .. } @@ -2689,7 +2693,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ensure_sufficient_stack(|| { self.note_obligation_cause_code( err, - &parent_predicate, + parent_predicate, param_env, &data.parent_code, obligated_types, @@ -2700,7 +2704,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ensure_sufficient_stack(|| { self.note_obligation_cause_code( err, - &parent_predicate, + parent_predicate, param_env, cause_code.peel_derives(), obligated_types, @@ -2809,7 +2813,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ensure_sufficient_stack(|| { self.note_obligation_cause_code( err, - &parent_predicate, + parent_predicate, param_env, &data.parent_code, obligated_types, @@ -2824,7 +2828,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ensure_sufficient_stack(|| { self.note_obligation_cause_code( err, - &parent_predicate, + parent_predicate, param_env, &data.parent_code, obligated_types, @@ -2838,26 +2842,183 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ref parent_code, } => { let hir = self.tcx.hir(); - if let Some(Node::Expr(expr @ hir::Expr { kind: hir::ExprKind::Block(..), .. })) = - hir.find(arg_hir_id) - { + 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), }; - let expr = expr.peel_blocks(); - let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()); + 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()); + let span = expr.span; + if Some(span) != err.span.primary_span() { + err.span_label( + span, + if ty.references_error() { + String::new() + } else { + format!("this tail expression is of type `{:?}`", ty) + }, + ); + } + } + let span = expr.span; - if Some(span) != err.span.primary_span() { - err.span_label( - span, - if ty.references_error() { - String::new() - } else { - format!("this tail expression is of type `{:?}`", ty) - }, + let mut multi_span: MultiSpan = match expr.kind { + hir::ExprKind::MethodCall(_, _, _, span) => span.into(), + _ => span.into(), + }; + + // FIXME: visit the ty to see if there's any closure involved, and if there is, + // check whether its evaluated return type is the same as the one corresponding + // to an associated type (as seen from `trait_pred`) in the predicate. Like in + // trait_pred `S: Sum<::Item>` and predicate `i32: Sum<&()>` + 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(pred) = predicates.predicates.get(*idx) + && let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() + { + let mut c = CollectAllMismatches { + infcx: self.infcx, + param_env: param_env, + errors: vec![], + }; + if let ty::PredicateKind::Clause(ty::Clause::Trait( + predicate + )) = predicate.kind().skip_binder() + { + if let Ok(_) = c.relate(trait_pred, predicate) { + type_diffs = c.errors; + } + } + } + let point_at_chain = |expr: &hir::Expr<'_>| { + let mut expr = expr; + let mut prev_ty = self.resolve_vars_if_possible( + typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()), ); + let outer_ty = prev_ty; + let mut assoc_seen = 0; + while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = + expr.kind + { + // Point at every method call in the chain with the resulting type. + // vec![1, 2, 3].iter().map(mapper).sum() + // ^^^^^^ ^^^^^^^^^^^ + expr = rcvr_expr; + + let ocx = ObligationCtxt::new_in_snapshot(self.infcx); + for diff in &type_diffs { + let Sorts(expected_found) = diff else { continue; }; + let ty::Projection(proj) = expected_found.expected.kind() else { continue; }; + assoc_seen += 1; + + let origin = TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + }; + let trait_def_id = proj.trait_def_id(self.tcx); + // Make `Self` be equivalent to the type of the call chain + // expression we're looking at now, so that we can tell what + // for example `Iterator::Item` is at this point in the chain. + let substs = + InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| { + match param.kind { + ty::GenericParamDefKind::Type { .. } => { + if param.index == 0 { + return prev_ty.into(); + } + } + ty::GenericParamDefKind::Lifetime + | ty::GenericParamDefKind::Const { .. } => {} + } + self.var_for_def(span, param) + }); + // This will hold the resolved type of the associated type, if the + // current expression implements the trait that associated type is + // in. For example, this would be what `Iterator::Item` is here. + let ty_var = self.infcx.next_ty_var(origin); + // This corresponds to `::Item = _`. + let trait_ref = ty::Binder::dummy(ty::PredicateKind::Clause( + ty::Clause::Projection(ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + substs, + item_def_id: proj.item_def_id, + }, + term: ty_var.into(), + }), + )); + // Add `::Item = _` obligation. + ocx.register_obligation(Obligation::misc( + self.tcx, + span, + expr.hir_id, + param_env, + trait_ref, + )); + if ocx.select_where_possible().is_empty() { + // `ty_var` now holds the type that `Item` is for `ExprTy`. + let assoc = self.tcx.def_path_str(proj.item_def_id); + multi_span.push_span_label( + span, + &format!( + "associated type `{assoc}` is `{}` here", + self.resolve_vars_if_possible(ty_var), + ), + ); + } else { + // `` didn't select, so likely we've + // reached the end of the iterator chain, like the originating + // `Vec<_>`. + multi_span.push_span_label( + span, + format!("this call has type `{prev_ty}`"), + ); + } + } + prev_ty = self.resolve_vars_if_possible( + typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()), + ); + } + + // We want the type before deref coercions, otherwise we talk about `&[_]` + // instead of `Vec<_>`. + if let Some(ty) = typeck_results.expr_ty_opt(expr) { + let ty = self.resolve_vars_if_possible(ty); + // Point at the root expression + // vec![1, 2, 3].iter().map(mapper).sum() + // ^^^^^^^^^^^^^ + multi_span.push_span_label( + expr.span, + format!("this expression has type `{ty}`"), + ); + }; + if assoc_seen > 0 { + // Only show this if it is not a "trivial" expression (not a method + // chain) and there are associated types to talk about. + err.span_note( + multi_span, + format!("the expression is of type `{outer_ty}`"), + ); + } + }; + if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind + && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path + && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id) + && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id) + && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id) + && let Some(binding_expr) = local.init + { + // 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. + point_at_chain(binding_expr); + } else { + point_at_chain(expr); } } if let Some(Node::Expr(hir::Expr { @@ -2888,9 +3049,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ObligationCauseCode::CompareImplItemObligation { trait_item_def_id, kind, .. } => { let item_name = self.tcx.item_name(trait_item_def_id); let msg = format!( - "the requirement `{}` appears on the `impl`'s {kind} `{}` but not on the \ - corresponding trait's {kind}", - predicate, item_name, + "the requirement `{predicate}` appears on the `impl`'s {kind} \ + `{item_name}` but not on the corresponding trait's {kind}", ); let sp = self .tcx @@ -2900,7 +3060,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut assoc_span: MultiSpan = sp.into(); assoc_span.push_span_label( sp, - format!("this trait's {kind} doesn't have the requirement `{}`", predicate), + format!("this trait's {kind} doesn't have the requirement `{predicate}`"), ); if let Some(ident) = self .tcx @@ -3286,3 +3446,72 @@ impl<'tcx> TypeFolder<'tcx> for ReplaceImplTraitFolder<'tcx> { self.tcx } } + +pub struct CollectAllMismatches<'a, 'tcx> { + pub infcx: &'a InferCtxt<'tcx>, + pub param_env: ty::ParamEnv<'tcx>, + pub errors: Vec>, +} + +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, + _: ty::VarianceDiagInfo<'tcx>, + a: T, + b: T, + ) -> RelateResult<'tcx, T> { + self.relate(a, b) + } + fn regions( + &mut self, + a: ty::Region<'tcx>, + _b: ty::Region<'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) + }) + } + fn consts( + &mut self, + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ty::Const<'tcx>> { + if a == b { + return Ok(a); + } + relate::super_relate_consts(self, a, b) // could do something similar here for constants! + } + fn binders>( + &mut self, + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> { + Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?)) + } +} diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index 3188cd80cca83..5e84dcdef3059 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -22,6 +22,14 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece | = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` = help: the trait `FromIterator` is implemented for `Vec` +note: the expression is of type `Map, [closure@$DIR/issue-34334.rs:5:47: 5:82]>` + --> $DIR/issue-34334.rs:5:43 + | +LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); + | -- ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here + | | | + | | associated type `std::iter::Iterator::Item` is `&(_, _, _)` here + | this expression has type `Vec<(_, _, _)>` note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr index ce38c3320bb35..5ee287b1b15a4 100644 --- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -8,6 +8,13 @@ LL | let x2: Vec = x1.into_iter().collect(); | = help: the trait `FromIterator<&f64>` is not implemented for `Vec` = help: the trait `FromIterator` is implemented for `Vec` +note: the expression is of type `std::slice::Iter<'_, f64>` + --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27 + | +LL | let x2: Vec = x1.into_iter().collect(); + | -- ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here + | | + | this expression has type `&[f64]` note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -24,6 +31,13 @@ LL | let x3 = x1.into_iter().collect::>(); | = help: the trait `FromIterator<&f64>` is not implemented for `Vec` = help: the trait `FromIterator` is implemented for `Vec` +note: the expression is of type `std::slice::Iter<'_, f64>` + --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17 + | +LL | let x3 = x1.into_iter().collect::>(); + | -- ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here + | | + | this expression has type `&[f64]` note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/iterators/invalid-iterator-chain.rs b/src/test/ui/iterators/invalid-iterator-chain.rs new file mode 100644 index 0000000000000..de174807ab631 --- /dev/null +++ b/src/test/ui/iterators/invalid-iterator-chain.rs @@ -0,0 +1,17 @@ +fn main() { + let scores = vec![(0, 0)] + .iter() + .map(|(a, b)| { + a + b; + }); + println!("{}", scores.sum::()); //~ ERROR E0277 + println!( + "{}", + vec![0, 1] //~ ERROR E0277 + .iter() + .map(|x| { x; }) + .sum::(), + ); + println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); //~ ERROR E0277 + println!("{}", vec![(), ()].iter().sum::()); //~ ERROR E0277 +} diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr new file mode 100644 index 0000000000000..03298089d88bd --- /dev/null +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -0,0 +1,111 @@ +error[E0277]: the trait bound `i32: Sum<()>` is not satisfied + --> $DIR/invalid-iterator-chain.rs:7:20 + | +LL | println!("{}", scores.sum::()); + | ^^^^^^ --- required by a bound introduced by this call + | | + | the trait `Sum<()>` is not implemented for `i32` + | + = help: the following other types implement trait `Sum`: + > + +note: the expression is of type `Map, [closure@$DIR/invalid-iterator-chain.rs:4:14: 4:22]>` + --> $DIR/invalid-iterator-chain.rs:7:20 + | +LL | let scores = vec![(0, 0)] + | ------------ this expression has type `Vec<({integer}, {integer})>` +LL | .iter() + | ------ associated type `std::iter::Iterator::Item` is `&({integer}, {integer})` here +LL | .map(|(a, b)| { + | __________- +LL | | a + b; +LL | | }); + | |__________- associated type `std::iter::Iterator::Item` is `()` here +LL | println!("{}", scores.sum::()); + | ^^^^^^ +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | S: Sum, + | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` + +error[E0277]: the trait bound `i32: Sum<()>` is not satisfied + --> $DIR/invalid-iterator-chain.rs:10:9 + | +LL | / vec![0, 1] +LL | | .iter() +LL | | .map(|x| { x; }) + | |____________________________^ the trait `Sum<()>` is not implemented for `i32` +LL | .sum::(), + | --- required by a bound introduced by this call + | + = help: the following other types implement trait `Sum`: + > + +note: the expression is of type `Map, [closure@$DIR/invalid-iterator-chain.rs:12:18: 12:21]>` + --> $DIR/invalid-iterator-chain.rs:12:14 + | +LL | vec![0, 1] + | ---------- this expression has type `Vec<{integer}>` +LL | .iter() + | ------ associated type `std::iter::Iterator::Item` is `&{integer}` here +LL | .map(|x| { x; }) + | ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | S: Sum, + | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` + +error[E0277]: the trait bound `i32: Sum<()>` is not satisfied + --> $DIR/invalid-iterator-chain.rs:15:20 + | +LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call + | | + | the trait `Sum<()>` is not implemented for `i32` + | + = help: the following other types implement trait `Sum`: + > + +note: the expression is of type `Map, [closure@$DIR/invalid-iterator-chain.rs:15:42: 15:45]>` + --> $DIR/invalid-iterator-chain.rs:15:38 + | +LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); + | ---------- ------ ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here + | | | + | | associated type `std::iter::Iterator::Item` is `&{integer}` here + | this expression has type `Vec<{integer}>` +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | S: Sum, + | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` + +error[E0277]: the trait bound `i32: Sum<&()>` is not satisfied + --> $DIR/invalid-iterator-chain.rs:16:20 + | +LL | println!("{}", vec![(), ()].iter().sum::()); + | ^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call + | | + | the trait `Sum<&()>` is not implemented for `i32` + | + = help: the following other types implement trait `Sum`: + > + +note: the expression is of type `std::slice::Iter<'_, ()>` + --> $DIR/invalid-iterator-chain.rs:16:33 + | +LL | println!("{}", vec![(), ()].iter().sum::()); + | ------------ ^^^^^^ associated type `std::iter::Iterator::Item` is `&()` here + | | + | this expression has type `Vec<()>` +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | S: Sum, + | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. From 49d5bef5867012a3ec39a04c81694b64b22f0067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 6 Dec 2022 10:32:49 -0800 Subject: [PATCH 02/12] Expand iterator chain test --- .../ui/iterators/invalid-iterator-chain.rs | 5 ++++ .../iterators/invalid-iterator-chain.stderr | 28 ++++++++++++++----- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/test/ui/iterators/invalid-iterator-chain.rs b/src/test/ui/iterators/invalid-iterator-chain.rs index de174807ab631..3d4801b373230 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.rs +++ b/src/test/ui/iterators/invalid-iterator-chain.rs @@ -9,6 +9,11 @@ fn main() { "{}", vec![0, 1] //~ ERROR E0277 .iter() + .map(|x| x * 2) + .map(|x| x as f64) + .map(|x| x as i64) + .filter(|x| *x > 0) + .map(|x| { x + 1 }) .map(|x| { x; }) .sum::(), ); diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index 03298089d88bd..0b3e0653864d9 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -34,6 +34,10 @@ error[E0277]: the trait bound `i32: Sum<()>` is not satisfied | LL | / vec![0, 1] LL | | .iter() +LL | | .map(|x| x * 2) +LL | | .map(|x| x as f64) +... | +LL | | .map(|x| { x + 1 }) LL | | .map(|x| { x; }) | |____________________________^ the trait `Sum<()>` is not implemented for `i32` LL | .sum::(), @@ -42,13 +46,23 @@ LL | .sum::(), = help: the following other types implement trait `Sum`: > -note: the expression is of type `Map, [closure@$DIR/invalid-iterator-chain.rs:12:18: 12:21]>` - --> $DIR/invalid-iterator-chain.rs:12:14 +note: the expression is of type `Map, [closure@$DIR/invalid-iterator-chain.rs:12:18: 12:21]>, [closure@$DIR/invalid-iterator-chain.rs:13:18: 13:21]>, [closure@$DIR/invalid-iterator-chain.rs:14:18: 14:21]>, [closure@$DIR/invalid-iterator-chain.rs:15:21: 15:24]>, [closure@$DIR/invalid-iterator-chain.rs:16:18: 16:21]>, [closure@$DIR/invalid-iterator-chain.rs:17:18: 17:21]>` + --> $DIR/invalid-iterator-chain.rs:17:14 | LL | vec![0, 1] | ---------- this expression has type `Vec<{integer}>` LL | .iter() | ------ associated type `std::iter::Iterator::Item` is `&{integer}` here +LL | .map(|x| x * 2) + | -------------- associated type `std::iter::Iterator::Item` is `{integer}` here +LL | .map(|x| x as f64) + | ----------------- associated type `std::iter::Iterator::Item` is `f64` here +LL | .map(|x| x as i64) + | ----------------- associated type `std::iter::Iterator::Item` is `i64` here +LL | .filter(|x| *x > 0) + | ------------------ associated type `std::iter::Iterator::Item` is `i64` here +LL | .map(|x| { x + 1 }) + | ------------------ associated type `std::iter::Iterator::Item` is `i64` here LL | .map(|x| { x; }) | ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here note: required by a bound in `std::iter::Iterator::sum` @@ -58,7 +72,7 @@ LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` error[E0277]: the trait bound `i32: Sum<()>` is not satisfied - --> $DIR/invalid-iterator-chain.rs:15:20 + --> $DIR/invalid-iterator-chain.rs:20:20 | LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call @@ -68,8 +82,8 @@ LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); = help: the following other types implement trait `Sum`: > -note: the expression is of type `Map, [closure@$DIR/invalid-iterator-chain.rs:15:42: 15:45]>` - --> $DIR/invalid-iterator-chain.rs:15:38 +note: the expression is of type `Map, [closure@$DIR/invalid-iterator-chain.rs:20:42: 20:45]>` + --> $DIR/invalid-iterator-chain.rs:20:38 | LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); | ---------- ------ ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here @@ -83,7 +97,7 @@ LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` error[E0277]: the trait bound `i32: Sum<&()>` is not satisfied - --> $DIR/invalid-iterator-chain.rs:16:20 + --> $DIR/invalid-iterator-chain.rs:21:20 | LL | println!("{}", vec![(), ()].iter().sum::()); | ^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call @@ -94,7 +108,7 @@ LL | println!("{}", vec![(), ()].iter().sum::()); > note: the expression is of type `std::slice::Iter<'_, ()>` - --> $DIR/invalid-iterator-chain.rs:16:33 + --> $DIR/invalid-iterator-chain.rs:21:33 | LL | println!("{}", vec![(), ()].iter().sum::()); | ------------ ^^^^^^ associated type `std::iter::Iterator::Item` is `&()` here From 64bc975d27f86aaa1d3d94921c9c042477b4e88b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 6 Dec 2022 12:08:17 -0800 Subject: [PATCH 03/12] Mention only assoc types changes --- .../src/traits/error_reporting/suggestions.rs | 96 +++++++++++++------ src/test/ui/issues/issue-34334.stderr | 6 +- ...e-66923-show-error-for-correct-call.stderr | 4 +- .../iterators/invalid-iterator-chain.stderr | 38 ++++---- 4 files changed, 92 insertions(+), 52 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 8bfa405cbeae1..2f9b8c2107153 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2865,11 +2865,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - let span = expr.span; - let mut multi_span: MultiSpan = match expr.kind { - hir::ExprKind::MethodCall(_, _, _, span) => span.into(), - _ => span.into(), - }; + let mut primary_spans = vec![]; + let mut span_labels = vec![]; // FIXME: visit the ty to see if there's any closure involved, and if there is, // check whether its evaluated return type is the same as the one corresponding @@ -2897,12 +2894,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } let point_at_chain = |expr: &hir::Expr<'_>| { + let mut assocs = vec![]; + // We still want to point at the different methods even if there hasn't + // been a change of assoc type. + let mut call_spans = vec![]; let mut expr = expr; let mut prev_ty = self.resolve_vars_if_possible( typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()), ); - let outer_ty = prev_ty; - let mut assoc_seen = 0; while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind { @@ -2910,12 +2909,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // vec![1, 2, 3].iter().map(mapper).sum() // ^^^^^^ ^^^^^^^^^^^ expr = rcvr_expr; + let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len()); + call_spans.push(span); let ocx = ObligationCtxt::new_in_snapshot(self.infcx); for diff in &type_diffs { let Sorts(expected_found) = diff else { continue; }; let ty::Projection(proj) = expected_found.expected.kind() else { continue; }; - assoc_seen += 1; let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, @@ -2963,23 +2963,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if ocx.select_where_possible().is_empty() { // `ty_var` now holds the type that `Item` is for `ExprTy`. let assoc = self.tcx.def_path_str(proj.item_def_id); - multi_span.push_span_label( - span, - &format!( - "associated type `{assoc}` is `{}` here", - self.resolve_vars_if_possible(ty_var), - ), - ); + let ty_var = self.resolve_vars_if_possible(ty_var); + assocs_in_this_method.push(Some((span, (assoc, ty_var)))); } else { // `` didn't select, so likely we've // reached the end of the iterator chain, like the originating // `Vec<_>`. - multi_span.push_span_label( - span, - format!("this call has type `{prev_ty}`"), - ); + // Keep the space consistent for later zipping. + assocs_in_this_method.push(None); } } + assocs.push(assocs_in_this_method); prev_ty = self.resolve_vars_if_possible( typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()), ); @@ -2992,17 +2986,65 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Point at the root expression // vec![1, 2, 3].iter().map(mapper).sum() // ^^^^^^^^^^^^^ - multi_span.push_span_label( - expr.span, - format!("this expression has type `{ty}`"), - ); + span_labels + .push((expr.span, format!("this expression has type `{ty}`"))); }; - if assoc_seen > 0 { - // Only show this if it is not a "trivial" expression (not a method - // chain) and there are associated types to talk about. + // Only show this if it is not a "trivial" expression (not a method + // chain) and there are associated types to talk about. + let mut assocs = assocs.into_iter().peekable(); + while let Some(assocs_in_method) = assocs.next() { + let Some(prev_assoc_in_method) = assocs.peek() else { + for entry in assocs_in_method { + let Some((span, (assoc, ty))) = entry else { continue; }; + primary_spans.push(span); + span_labels.push(( + span, + format!("associated type `{assoc}` is `{ty}` here"), + )); + } + break; + }; + for (entry, prev_entry) in + assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter()) + { + match (entry, prev_entry) { + (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => { + if ty != *prev_ty { + primary_spans.push(span); + span_labels.push(( + span, + format!("associated type `{assoc}` changed to `{ty}` here"), + )); + } + } + (Some((span, (assoc, ty))), None) => { + span_labels.push(( + span, + format!("associated type `{assoc}` is `{ty}` here"), + )); + } + (None, Some(_)) | (None, None) => {} + } + } + } + for span in call_spans { + if span_labels.iter().find(|(s, _)| *s == span).is_none() { + // Ensure we are showing the entire chain, even if the assoc types + // haven't changed. + span_labels.push((span, String::new())); + } + } + if !primary_spans.is_empty() { + let mut multi_span: MultiSpan = primary_spans.into(); + for (span, label) in span_labels { + multi_span.push_span_label(span, label); + } err.span_note( multi_span, - format!("the expression is of type `{outer_ty}`"), + format!( + "the method call chain might not have had the expected \ + associated types", + ), ); } }; diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index 5e84dcdef3059..eca961633dce9 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -22,11 +22,11 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece | = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` = help: the trait `FromIterator` is implemented for `Vec` -note: the expression is of type `Map, [closure@$DIR/issue-34334.rs:5:47: 5:82]>` - --> $DIR/issue-34334.rs:5:43 +note: the method call chain might not have had the expected associated types + --> $DIR/issue-34334.rs:5:36 | LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); - | -- ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here + | -- ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here | | | | | associated type `std::iter::Iterator::Item` is `&(_, _, _)` here | this expression has type `Vec<(_, _, _)>` diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr index 5ee287b1b15a4..7f97b5bfcbe36 100644 --- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -8,7 +8,7 @@ LL | let x2: Vec = x1.into_iter().collect(); | = help: the trait `FromIterator<&f64>` is not implemented for `Vec` = help: the trait `FromIterator` is implemented for `Vec` -note: the expression is of type `std::slice::Iter<'_, f64>` +note: the method call chain might not have had the expected associated types --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27 | LL | let x2: Vec = x1.into_iter().collect(); @@ -31,7 +31,7 @@ LL | let x3 = x1.into_iter().collect::>(); | = help: the trait `FromIterator<&f64>` is not implemented for `Vec` = help: the trait `FromIterator` is implemented for `Vec` -note: the expression is of type `std::slice::Iter<'_, f64>` +note: the method call chain might not have had the expected associated types --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17 | LL | let x3 = x1.into_iter().collect::>(); diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index 0b3e0653864d9..57be01a24422d 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -9,20 +9,18 @@ LL | println!("{}", scores.sum::()); = help: the following other types implement trait `Sum`: > -note: the expression is of type `Map, [closure@$DIR/invalid-iterator-chain.rs:4:14: 4:22]>` - --> $DIR/invalid-iterator-chain.rs:7:20 +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:3:10 | LL | let scores = vec![(0, 0)] | ------------ this expression has type `Vec<({integer}, {integer})>` LL | .iter() - | ------ associated type `std::iter::Iterator::Item` is `&({integer}, {integer})` here + | ^^^^^^ associated type `std::iter::Iterator::Item` is `&({integer}, {integer})` here LL | .map(|(a, b)| { - | __________- + | __________^ LL | | a + b; LL | | }); - | |__________- associated type `std::iter::Iterator::Item` is `()` here -LL | println!("{}", scores.sum::()); - | ^^^^^^ + | |__________^ associated type `std::iter::Iterator::Item` changed to `()` here note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -46,25 +44,25 @@ LL | .sum::(), = help: the following other types implement trait `Sum`: > -note: the expression is of type `Map, [closure@$DIR/invalid-iterator-chain.rs:12:18: 12:21]>, [closure@$DIR/invalid-iterator-chain.rs:13:18: 13:21]>, [closure@$DIR/invalid-iterator-chain.rs:14:18: 14:21]>, [closure@$DIR/invalid-iterator-chain.rs:15:21: 15:24]>, [closure@$DIR/invalid-iterator-chain.rs:16:18: 16:21]>, [closure@$DIR/invalid-iterator-chain.rs:17:18: 17:21]>` - --> $DIR/invalid-iterator-chain.rs:17:14 +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:11:14 | LL | vec![0, 1] | ---------- this expression has type `Vec<{integer}>` LL | .iter() - | ------ associated type `std::iter::Iterator::Item` is `&{integer}` here + | ^^^^^^ associated type `std::iter::Iterator::Item` is `&{integer}` here LL | .map(|x| x * 2) - | -------------- associated type `std::iter::Iterator::Item` is `{integer}` here + | ^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `{integer}` here LL | .map(|x| x as f64) - | ----------------- associated type `std::iter::Iterator::Item` is `f64` here + | ^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `f64` here LL | .map(|x| x as i64) - | ----------------- associated type `std::iter::Iterator::Item` is `i64` here + | ^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `i64` here LL | .filter(|x| *x > 0) - | ------------------ associated type `std::iter::Iterator::Item` is `i64` here + | ------------------ LL | .map(|x| { x + 1 }) - | ------------------ associated type `std::iter::Iterator::Item` is `i64` here + | ------------------ LL | .map(|x| { x; }) - | ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here + | ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -82,11 +80,11 @@ LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); = help: the following other types implement trait `Sum`: > -note: the expression is of type `Map, [closure@$DIR/invalid-iterator-chain.rs:20:42: 20:45]>` - --> $DIR/invalid-iterator-chain.rs:20:38 +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:20:31 | LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); - | ---------- ------ ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here + | ---------- ^^^^^^ ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here | | | | | associated type `std::iter::Iterator::Item` is `&{integer}` here | this expression has type `Vec<{integer}>` @@ -107,7 +105,7 @@ LL | println!("{}", vec![(), ()].iter().sum::()); = help: the following other types implement trait `Sum`: > -note: the expression is of type `std::slice::Iter<'_, ()>` +note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:21:33 | LL | println!("{}", vec![(), ()].iter().sum::()); From 71db025cfa85ea3c1e7d628f4c596ca498c7acf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 7 Dec 2022 11:11:06 -0800 Subject: [PATCH 04/12] Account for method call chains split across multiple bindings --- .../src/traits/error_reporting/suggestions.rs | 12 +++++++ src/test/ui/issues/issue-34334.stderr | 10 +++--- ...e-66923-show-error-for-correct-call.stderr | 13 +++---- .../ui/iterators/invalid-iterator-chain.rs | 9 +++++ .../iterators/invalid-iterator-chain.stderr | 36 ++++++++++++++++++- 5 files changed, 69 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 2f9b8c2107153..87ab863fa7bcd 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2977,6 +2977,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { prev_ty = self.resolve_vars_if_possible( typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()), ); + + if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind + && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path + && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id) + && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id) + && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id) + && let Some(binding_expr) = local.init + { + // We've reached the root of the method call chain and it is a + // binding. Get the binding creation and try to continue the chain. + expr = binding_expr; + } } // We want the type before deref coercions, otherwise we talk about `&[_]` diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index eca961633dce9..89f5c45d7a978 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -25,11 +25,13 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece note: the method call chain might not have had the expected associated types --> $DIR/issue-34334.rs:5:36 | +LL | let sr: Vec<(u32, _, _) = vec![]; + | ------ this expression has type `Vec<(_, _, _)>` +... LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); - | -- ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here - | | | - | | associated type `std::iter::Iterator::Item` is `&(_, _, _)` here - | this expression has type `Vec<(_, _, _)>` + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here + | | + | associated type `std::iter::Iterator::Item` is `&(_, _, _)` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr index 7f97b5bfcbe36..7fe786dcfb503 100644 --- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -11,10 +11,10 @@ LL | let x2: Vec = x1.into_iter().collect(); note: the method call chain might not have had the expected associated types --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27 | +LL | let x1: &[f64] = &v; + | -- this expression has type `&Vec` LL | let x2: Vec = x1.into_iter().collect(); - | -- ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here - | | - | this expression has type `&[f64]` + | ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -34,10 +34,11 @@ LL | let x3 = x1.into_iter().collect::>(); note: the method call chain might not have had the expected associated types --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17 | +LL | let x1: &[f64] = &v; + | -- this expression has type `&Vec` +... LL | let x3 = x1.into_iter().collect::>(); - | -- ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here - | | - | this expression has type `&[f64]` + | ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/iterators/invalid-iterator-chain.rs b/src/test/ui/iterators/invalid-iterator-chain.rs index 3d4801b373230..e17b471b69293 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.rs +++ b/src/test/ui/iterators/invalid-iterator-chain.rs @@ -19,4 +19,13 @@ fn main() { ); println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); //~ ERROR E0277 println!("{}", vec![(), ()].iter().sum::()); //~ ERROR E0277 + let a = vec![0]; + let b = a.into_iter(); + let c = b.map(|x| x + 1); + let d = c.filter(|x| *x > 10 ); + let e = d.map(|x| { + x + 1; + }); + let f = e.filter(|_| false); + let g: Vec = f.collect(); //~ ERROR E0277 } diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index 57be01a24422d..8bf7eb93a720b 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -118,6 +118,40 @@ note: required by a bound in `std::iter::Iterator::sum` LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` -error: aborting due to 4 previous errors +error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain.rs:30:23 + | +LL | let g: Vec = f.collect(); + | ^ ------- required by a bound introduced by this call + | | + | value of type `Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<()>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:23:15 + | +LL | let a = vec![0]; + | ------- this expression has type `Vec<{integer}>` +LL | let b = a.into_iter(); + | ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `{integer}` here +LL | let c = b.map(|x| x + 1); + | -------------- +LL | let d = c.filter(|x| *x > 10 ); + | -------------------- +LL | let e = d.map(|x| { + | _______________^ +LL | | x + 1; +LL | | }); + | |______^ associated type `std::iter::Iterator::Item` changed to `()` here +LL | let f = e.filter(|_| false); + | ----------------- +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. From c77ad2d76576b97f6b2ea8c8b5ddb672c3383512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 7 Dec 2022 11:32:26 -0800 Subject: [PATCH 05/12] Remove mention of "assoc type" in label as it is already in the `note` message --- .../src/traits/error_reporting/suggestions.rs | 12 ++++------ src/test/ui/issues/issue-34334.stderr | 4 ++-- ...e-66923-show-error-for-correct-call.stderr | 4 ++-- .../iterators/invalid-iterator-chain.stderr | 24 +++++++++---------- 4 files changed, 21 insertions(+), 23 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 87ab863fa7bcd..bef2a067ae310 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3011,7 +3011,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { primary_spans.push(span); span_labels.push(( span, - format!("associated type `{assoc}` is `{ty}` here"), + format!("`{assoc}` is `{ty}` here"), )); } break; @@ -3025,15 +3025,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { primary_spans.push(span); span_labels.push(( span, - format!("associated type `{assoc}` changed to `{ty}` here"), + format!("`{assoc}` changed to `{ty}` here"), )); } } (Some((span, (assoc, ty))), None) => { - span_labels.push(( - span, - format!("associated type `{assoc}` is `{ty}` here"), - )); + span_labels + .push((span, format!("`{assoc}` is `{ty}` here"))); } (None, Some(_)) | (None, None) => {} } @@ -3055,7 +3053,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { multi_span, format!( "the method call chain might not have had the expected \ - associated types", + associated types", ), ); } diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index 89f5c45d7a978..ac3b3e95faf30 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -29,9 +29,9 @@ LL | let sr: Vec<(u32, _, _) = vec![]; | ------ this expression has type `Vec<(_, _, _)>` ... LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); - | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `()` here | | - | associated type `std::iter::Iterator::Item` is `&(_, _, _)` here + | `std::iter::Iterator::Item` is `&(_, _, _)` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr index 7fe786dcfb503..9a560c631fec4 100644 --- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -14,7 +14,7 @@ note: the method call chain might not have had the expected associated types LL | let x1: &[f64] = &v; | -- this expression has type `&Vec` LL | let x2: Vec = x1.into_iter().collect(); - | ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here + | ^^^^^^^^^^^ `std::iter::Iterator::Item` is `&f64` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -38,7 +38,7 @@ LL | let x1: &[f64] = &v; | -- this expression has type `&Vec` ... LL | let x3 = x1.into_iter().collect::>(); - | ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here + | ^^^^^^^^^^^ `std::iter::Iterator::Item` is `&f64` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index 8bf7eb93a720b..0505dd86af32c 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -15,12 +15,12 @@ note: the method call chain might not have had the expected associated types LL | let scores = vec![(0, 0)] | ------------ this expression has type `Vec<({integer}, {integer})>` LL | .iter() - | ^^^^^^ associated type `std::iter::Iterator::Item` is `&({integer}, {integer})` here + | ^^^^^^ `std::iter::Iterator::Item` is `&({integer}, {integer})` here LL | .map(|(a, b)| { | __________^ LL | | a + b; LL | | }); - | |__________^ associated type `std::iter::Iterator::Item` changed to `()` here + | |__________^ `std::iter::Iterator::Item` changed to `()` here note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -50,19 +50,19 @@ note: the method call chain might not have had the expected associated types LL | vec![0, 1] | ---------- this expression has type `Vec<{integer}>` LL | .iter() - | ^^^^^^ associated type `std::iter::Iterator::Item` is `&{integer}` here + | ^^^^^^ `std::iter::Iterator::Item` is `&{integer}` here LL | .map(|x| x * 2) - | ^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `{integer}` here + | ^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `{integer}` here LL | .map(|x| x as f64) - | ^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `f64` here + | ^^^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `f64` here LL | .map(|x| x as i64) - | ^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `i64` here + | ^^^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `i64` here LL | .filter(|x| *x > 0) | ------------------ LL | .map(|x| { x + 1 }) | ------------------ LL | .map(|x| { x; }) - | ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here + | ^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `()` here note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -84,9 +84,9 @@ note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:20:31 | LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); - | ---------- ^^^^^^ ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here + | ---------- ^^^^^^ ^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `()` here | | | - | | associated type `std::iter::Iterator::Item` is `&{integer}` here + | | `std::iter::Iterator::Item` is `&{integer}` here | this expression has type `Vec<{integer}>` note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL @@ -109,7 +109,7 @@ note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:21:33 | LL | println!("{}", vec![(), ()].iter().sum::()); - | ------------ ^^^^^^ associated type `std::iter::Iterator::Item` is `&()` here + | ------------ ^^^^^^ `std::iter::Iterator::Item` is `&()` here | | | this expression has type `Vec<()>` note: required by a bound in `std::iter::Iterator::sum` @@ -134,7 +134,7 @@ note: the method call chain might not have had the expected associated types LL | let a = vec![0]; | ------- this expression has type `Vec<{integer}>` LL | let b = a.into_iter(); - | ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `{integer}` here + | ^^^^^^^^^^^ `std::iter::Iterator::Item` is `{integer}` here LL | let c = b.map(|x| x + 1); | -------------- LL | let d = c.filter(|x| *x > 10 ); @@ -143,7 +143,7 @@ LL | let e = d.map(|x| { | _______________^ LL | | x + 1; LL | | }); - | |______^ associated type `std::iter::Iterator::Item` changed to `()` here + | |______^ `std::iter::Iterator::Item` changed to `()` here LL | let f = e.filter(|_| false); | ----------------- note: required by a bound in `collect` From aff0ab43c8fecbf9473d60d30e5d03f8612efd91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 7 Dec 2022 12:25:49 -0800 Subject: [PATCH 06/12] Add label to method chains where assoc type remains the same --- .../src/traits/error_reporting/suggestions.rs | 5 +++++ src/test/ui/iterators/invalid-iterator-chain.stderr | 10 +++++----- 2 files changed, 10 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 bef2a067ae310..1d6e749b9e385 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3027,6 +3027,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { span, format!("`{assoc}` changed to `{ty}` here"), )); + } else { + span_labels.push(( + span, + format!("`{assoc}` remains `{ty}` here"), + )); } } (Some((span, (assoc, ty))), None) => { diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index 0505dd86af32c..14e430726f6db 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -58,9 +58,9 @@ LL | .map(|x| x as f64) LL | .map(|x| x as i64) | ^^^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `i64` here LL | .filter(|x| *x > 0) - | ------------------ + | ------------------ `std::iter::Iterator::Item` remains `i64` here LL | .map(|x| { x + 1 }) - | ------------------ + | ------------------ `std::iter::Iterator::Item` remains `i64` here LL | .map(|x| { x; }) | ^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `()` here note: required by a bound in `std::iter::Iterator::sum` @@ -136,16 +136,16 @@ LL | let a = vec![0]; LL | let b = a.into_iter(); | ^^^^^^^^^^^ `std::iter::Iterator::Item` is `{integer}` here LL | let c = b.map(|x| x + 1); - | -------------- + | -------------- `std::iter::Iterator::Item` remains `{integer}` here LL | let d = c.filter(|x| *x > 10 ); - | -------------------- + | -------------------- `std::iter::Iterator::Item` remains `{integer}` here LL | let e = d.map(|x| { | _______________^ LL | | x + 1; LL | | }); | |______^ `std::iter::Iterator::Item` changed to `()` here LL | let f = e.filter(|_| false); - | ----------------- + | ----------------- `std::iter::Iterator::Item` remains `()` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | From 78f97595a3e7ef9d796b77cd5572676a1a41fb71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 7 Dec 2022 14:16:37 -0800 Subject: [PATCH 07/12] Only point at methods that might be relevant --- .../src/traits/error_reporting/suggestions.rs | 19 +++++- src/test/ui/issues/issue-34334.stderr | 4 +- .../ui/iterators/invalid-iterator-chain.rs | 10 +++ .../iterators/invalid-iterator-chain.stderr | 67 ++++++++++++++----- 4 files changed, 81 insertions(+), 19 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 1d6e749b9e385..cfd7c20767f28 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3008,7 +3008,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let Some(prev_assoc_in_method) = assocs.peek() else { for entry in assocs_in_method { let Some((span, (assoc, ty))) = entry else { continue; }; - primary_spans.push(span); + if type_diffs.iter().any(|diff| { + let Sorts(expected_found) = diff else { return false; }; + self.can_eq(param_env, expected_found.found, ty).is_ok() + }) { + // FIXME: this doesn't quite work for `Iterator::collect` + // because we have `Vec` and `()`, but we'd want `i32` + // to point at the `.into_iter()` call, but as long as we + // still point at the other method calls that might have + // introduced the issue, this is fine for now. + primary_spans.push(span); + } span_labels.push(( span, format!("`{assoc}` is `{ty}` here"), @@ -3022,7 +3032,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { match (entry, prev_entry) { (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => { if ty != *prev_ty { - primary_spans.push(span); + if type_diffs.iter().any(|diff| { + let Sorts(expected_found) = diff else { return false; }; + self.can_eq(param_env, expected_found.found, ty).is_ok() + }) { + primary_spans.push(span); + } span_labels.push(( span, format!("`{assoc}` changed to `{ty}` here"), diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index ac3b3e95faf30..688a532adc6a6 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -23,13 +23,13 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` = help: the trait `FromIterator` is implemented for `Vec` note: the method call chain might not have had the expected associated types - --> $DIR/issue-34334.rs:5:36 + --> $DIR/issue-34334.rs:5:43 | LL | let sr: Vec<(u32, _, _) = vec![]; | ------ this expression has type `Vec<(_, _, _)>` ... LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); - | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `()` here + | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `()` here | | | `std::iter::Iterator::Item` is `&(_, _, _)` here note: required by a bound in `collect` diff --git a/src/test/ui/iterators/invalid-iterator-chain.rs b/src/test/ui/iterators/invalid-iterator-chain.rs index e17b471b69293..32141bf0fb84e 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.rs +++ b/src/test/ui/iterators/invalid-iterator-chain.rs @@ -17,6 +17,16 @@ fn main() { .map(|x| { x; }) .sum::(), ); + println!( + "{}", + vec![0, 1] //~ ERROR E0277 + .iter() + .map(|x| x * 2) + .map(|x| x as f64) + .filter(|x| *x > 0.0) + .map(|x| { x + 1.0 }) + .sum::(), + ); println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); //~ ERROR E0277 println!("{}", vec![(), ()].iter().sum::()); //~ ERROR E0277 let a = vec![0]; diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index 14e430726f6db..55788ae80e601 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -10,12 +10,12 @@ LL | println!("{}", scores.sum::()); > note: the method call chain might not have had the expected associated types - --> $DIR/invalid-iterator-chain.rs:3:10 + --> $DIR/invalid-iterator-chain.rs:4:10 | LL | let scores = vec![(0, 0)] | ------------ this expression has type `Vec<({integer}, {integer})>` LL | .iter() - | ^^^^^^ `std::iter::Iterator::Item` is `&({integer}, {integer})` here + | ------ `std::iter::Iterator::Item` is `&({integer}, {integer})` here LL | .map(|(a, b)| { | __________^ LL | | a + b; @@ -45,18 +45,18 @@ LL | .sum::(), > note: the method call chain might not have had the expected associated types - --> $DIR/invalid-iterator-chain.rs:11:14 + --> $DIR/invalid-iterator-chain.rs:12:14 | LL | vec![0, 1] | ---------- this expression has type `Vec<{integer}>` LL | .iter() - | ^^^^^^ `std::iter::Iterator::Item` is `&{integer}` here + | ------ `std::iter::Iterator::Item` is `&{integer}` here LL | .map(|x| x * 2) | ^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `{integer}` here LL | .map(|x| x as f64) - | ^^^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `f64` here + | ----------------- `std::iter::Iterator::Item` changed to `f64` here LL | .map(|x| x as i64) - | ^^^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `i64` here + | ----------------- `std::iter::Iterator::Item` changed to `i64` here LL | .filter(|x| *x > 0) | ------------------ `std::iter::Iterator::Item` remains `i64` here LL | .map(|x| { x + 1 }) @@ -69,8 +69,45 @@ note: required by a bound in `std::iter::Iterator::sum` LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` +error[E0277]: the trait bound `i32: Sum` is not satisfied + --> $DIR/invalid-iterator-chain.rs:22:9 + | +LL | / vec![0, 1] +LL | | .iter() +LL | | .map(|x| x * 2) +LL | | .map(|x| x as f64) +LL | | .filter(|x| *x > 0.0) +LL | | .map(|x| { x + 1.0 }) + | |_________________________________^ the trait `Sum` is not implemented for `i32` +LL | .sum::(), + | --- required by a bound introduced by this call + | + = help: the following other types implement trait `Sum`: + > + +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:24:14 + | +LL | vec![0, 1] + | ---------- this expression has type `Vec<{integer}>` +LL | .iter() + | ------ `std::iter::Iterator::Item` is `&{integer}` here +LL | .map(|x| x * 2) + | ^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `{integer}` here +LL | .map(|x| x as f64) + | ^^^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `f64` here +LL | .filter(|x| *x > 0.0) + | -------------------- `std::iter::Iterator::Item` remains `f64` here +LL | .map(|x| { x + 1.0 }) + | -------------------- `std::iter::Iterator::Item` remains `f64` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | S: Sum, + | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` + error[E0277]: the trait bound `i32: Sum<()>` is not satisfied - --> $DIR/invalid-iterator-chain.rs:20:20 + --> $DIR/invalid-iterator-chain.rs:30:20 | LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call @@ -81,10 +118,10 @@ LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); > note: the method call chain might not have had the expected associated types - --> $DIR/invalid-iterator-chain.rs:20:31 + --> $DIR/invalid-iterator-chain.rs:30:38 | LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); - | ---------- ^^^^^^ ^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `()` here + | ---------- ------ ^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `()` here | | | | | `std::iter::Iterator::Item` is `&{integer}` here | this expression has type `Vec<{integer}>` @@ -95,7 +132,7 @@ LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` error[E0277]: the trait bound `i32: Sum<&()>` is not satisfied - --> $DIR/invalid-iterator-chain.rs:21:20 + --> $DIR/invalid-iterator-chain.rs:31:20 | LL | println!("{}", vec![(), ()].iter().sum::()); | ^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call @@ -106,7 +143,7 @@ LL | println!("{}", vec![(), ()].iter().sum::()); > note: the method call chain might not have had the expected associated types - --> $DIR/invalid-iterator-chain.rs:21:33 + --> $DIR/invalid-iterator-chain.rs:31:33 | LL | println!("{}", vec![(), ()].iter().sum::()); | ------------ ^^^^^^ `std::iter::Iterator::Item` is `&()` here @@ -119,7 +156,7 @@ LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `()` - --> $DIR/invalid-iterator-chain.rs:30:23 + --> $DIR/invalid-iterator-chain.rs:40:23 | LL | let g: Vec = f.collect(); | ^ ------- required by a bound introduced by this call @@ -129,12 +166,12 @@ LL | let g: Vec = f.collect(); = help: the trait `FromIterator<()>` is not implemented for `Vec` = help: the trait `FromIterator` is implemented for `Vec` note: the method call chain might not have had the expected associated types - --> $DIR/invalid-iterator-chain.rs:23:15 + --> $DIR/invalid-iterator-chain.rs:36:15 | LL | let a = vec![0]; | ------- this expression has type `Vec<{integer}>` LL | let b = a.into_iter(); - | ^^^^^^^^^^^ `std::iter::Iterator::Item` is `{integer}` here + | ----------- `std::iter::Iterator::Item` is `{integer}` here LL | let c = b.map(|x| x + 1); | -------------- `std::iter::Iterator::Item` remains `{integer}` here LL | let d = c.filter(|x| *x > 10 ); @@ -152,6 +189,6 @@ note: required by a bound in `collect` LL | fn collect>(self) -> B | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. From 8d9ffa379e2b6e0d8f4813c035daf6c567887c1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 10 Dec 2022 19:08:59 -0800 Subject: [PATCH 08/12] fix rebase --- .../iterators/invalid-iterator-chain.stderr | 25 +++++++++++-------- src/test/ui/on-unimplemented/sum.stderr | 14 +++++++++++ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index 55788ae80e601..833a5a7474aba 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -1,11 +1,12 @@ -error[E0277]: the trait bound `i32: Sum<()>` is not satisfied +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` --> $DIR/invalid-iterator-chain.rs:7:20 | LL | println!("{}", scores.sum::()); | ^^^^^^ --- required by a bound introduced by this call | | - | the trait `Sum<()>` is not implemented for `i32` + | value of type `i32` cannot be made by summing a `std::iter::Iterator` | + = help: the trait `Sum<()>` is not implemented for `i32` = help: the following other types implement trait `Sum`: > @@ -27,7 +28,7 @@ note: required by a bound in `std::iter::Iterator::sum` LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` -error[E0277]: the trait bound `i32: Sum<()>` is not satisfied +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` --> $DIR/invalid-iterator-chain.rs:10:9 | LL | / vec![0, 1] @@ -37,10 +38,11 @@ LL | | .map(|x| x as f64) ... | LL | | .map(|x| { x + 1 }) LL | | .map(|x| { x; }) - | |____________________________^ the trait `Sum<()>` is not implemented for `i32` + | |____________________________^ value of type `i32` cannot be made by summing a `std::iter::Iterator` LL | .sum::(), | --- required by a bound introduced by this call | + = help: the trait `Sum<()>` is not implemented for `i32` = help: the following other types implement trait `Sum`: > @@ -69,7 +71,7 @@ note: required by a bound in `std::iter::Iterator::sum` LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` -error[E0277]: the trait bound `i32: Sum` is not satisfied +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64` --> $DIR/invalid-iterator-chain.rs:22:9 | LL | / vec![0, 1] @@ -78,10 +80,11 @@ LL | | .map(|x| x * 2) LL | | .map(|x| x as f64) LL | | .filter(|x| *x > 0.0) LL | | .map(|x| { x + 1.0 }) - | |_________________________________^ the trait `Sum` is not implemented for `i32` + | |_________________________________^ value of type `i32` cannot be made by summing a `std::iter::Iterator` LL | .sum::(), | --- required by a bound introduced by this call | + = help: the trait `Sum` is not implemented for `i32` = help: the following other types implement trait `Sum`: > @@ -106,14 +109,15 @@ note: required by a bound in `std::iter::Iterator::sum` LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` -error[E0277]: the trait bound `i32: Sum<()>` is not satisfied +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` --> $DIR/invalid-iterator-chain.rs:30:20 | LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call | | - | the trait `Sum<()>` is not implemented for `i32` + | value of type `i32` cannot be made by summing a `std::iter::Iterator` | + = help: the trait `Sum<()>` is not implemented for `i32` = help: the following other types implement trait `Sum`: > @@ -131,14 +135,15 @@ note: required by a bound in `std::iter::Iterator::sum` LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` -error[E0277]: the trait bound `i32: Sum<&()>` is not satisfied +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()` --> $DIR/invalid-iterator-chain.rs:31:20 | LL | println!("{}", vec![(), ()].iter().sum::()); | ^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call | | - | the trait `Sum<&()>` is not implemented for `i32` + | value of type `i32` cannot be made by summing a `std::iter::Iterator` | + = help: the trait `Sum<&()>` is not implemented for `i32` = help: the following other types implement trait `Sum`: > diff --git a/src/test/ui/on-unimplemented/sum.stderr b/src/test/ui/on-unimplemented/sum.stderr index c3103671178b5..6405be01e674f 100644 --- a/src/test/ui/on-unimplemented/sum.stderr +++ b/src/test/ui/on-unimplemented/sum.stderr @@ -10,6 +10,13 @@ LL | vec![(), ()].iter().sum::(); = help: the following other types implement trait `Sum`: > +note: the method call chain might not have had the expected associated types + --> $DIR/sum.rs:4:18 + | +LL | vec![(), ()].iter().sum::(); + | ------------ ^^^^^^ `std::iter::Iterator::Item` is `&()` here + | | + | this expression has type `Vec<()>` note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -28,6 +35,13 @@ LL | vec![(), ()].iter().product::(); = help: the following other types implement trait `Product`: > +note: the method call chain might not have had the expected associated types + --> $DIR/sum.rs:7:18 + | +LL | vec![(), ()].iter().product::(); + | ------------ ^^^^^^ `std::iter::Iterator::Item` is `&()` here + | | + | this expression has type `Vec<()>` note: required by a bound in `std::iter::Iterator::product` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | From ce486d538b909658f72d6016dae758f075089d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 11 Dec 2022 11:38:43 -0800 Subject: [PATCH 09/12] Use `with_forced_trimmed_paths` --- .../src/traits/error_reporting/suggestions.rs | 41 +++++++++----- .../ruby_style_closure.stderr | 2 +- src/test/ui/issues/issue-34334.stderr | 4 +- ...e-66923-show-error-for-correct-call.stderr | 4 +- .../iterators/invalid-iterator-chain.stderr | 56 +++++++++---------- .../feature-gate-never_type_fallback.stderr | 2 +- src/test/ui/on-unimplemented/sum.stderr | 4 +- 7 files changed, 64 insertions(+), 49 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 cfd7c20767f28..adc64463b3b7a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2394,12 +2394,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err.note("only the last element of a tuple may have a dynamically sized type"); } ObligationCauseCode::ProjectionWf(data) => { - err.note(&format!("required so that the projection `{}` is well-formed", data,)); + err.note(&format!("required so that the projection `{data}` is well-formed")); } ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => { err.note(&format!( - "required so that reference `{}` does not outlive its referent", - ref_ty, + "required so that reference `{ref_ty}` does not outlive its referent" )); } ObligationCauseCode::ObjectTypeBound(object_ty, region) => { @@ -2859,7 +2858,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if ty.references_error() { String::new() } else { - format!("this tail expression is of type `{:?}`", ty) + let ty = with_forced_trimmed_paths!(self.ty_to_string(ty)); + format!("this tail expression is of type `{ty}`") }, ); } @@ -2962,9 +2962,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { )); if ocx.select_where_possible().is_empty() { // `ty_var` now holds the type that `Item` is for `ExprTy`. - let assoc = self.tcx.def_path_str(proj.item_def_id); let ty_var = self.resolve_vars_if_possible(ty_var); - assocs_in_this_method.push(Some((span, (assoc, ty_var)))); + assocs_in_this_method + .push(Some((span, (proj.item_def_id, ty_var)))); } else { // `` didn't select, so likely we've // reached the end of the iterator chain, like the originating @@ -2994,7 +2994,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // We want the type before deref coercions, otherwise we talk about `&[_]` // instead of `Vec<_>`. if let Some(ty) = typeck_results.expr_ty_opt(expr) { - let ty = self.resolve_vars_if_possible(ty); + let ty = with_forced_trimmed_paths!(self.ty_to_string(ty)); // Point at the root expression // vec![1, 2, 3].iter().map(mapper).sum() // ^^^^^^^^^^^^^ @@ -3021,7 +3021,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } span_labels.push(( span, - format!("`{assoc}` is `{ty}` here"), + with_forced_trimmed_paths!(format!( + "`{}` is `{ty}` here", + self.tcx.def_path_str(assoc), + )), )); } break; @@ -3031,6 +3034,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { { match (entry, prev_entry) { (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => { + let ty_str = + with_forced_trimmed_paths!(self.ty_to_string(ty)); + + let assoc = with_forced_trimmed_paths!( + self.tcx.def_path_str(assoc) + ); if ty != *prev_ty { if type_diffs.iter().any(|diff| { let Sorts(expected_found) = diff else { return false; }; @@ -3040,18 +3049,24 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } span_labels.push(( span, - format!("`{assoc}` changed to `{ty}` here"), + format!("`{assoc}` changed to `{ty_str}` here"), )); } else { span_labels.push(( span, - format!("`{assoc}` remains `{ty}` here"), + format!("`{assoc}` remains `{ty_str}` here"), )); } } (Some((span, (assoc, ty))), None) => { - span_labels - .push((span, format!("`{assoc}` is `{ty}` here"))); + span_labels.push(( + span, + with_forced_trimmed_paths!(format!( + "`{}` is `{}` here", + self.tcx.def_path_str(assoc), + self.ty_to_string(ty), + )), + )); } (None, Some(_)) | (None, None) => {} } @@ -3151,7 +3166,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ObligationCauseCode::OpaqueReturnType(expr_info) => { if let Some((expr_ty, expr_span)) = expr_info { - let expr_ty = self.resolve_vars_if_possible(expr_ty); + let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr_ty)); err.span_label( expr_span, format!("return type was inferred to be `{expr_ty}` here"), diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr index 759d79493a9cf..c7ed8e0de384c 100644 --- a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr +++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr @@ -14,7 +14,7 @@ LL | let p = Some(45).and_then({ LL | | LL | | |x| println!("doubling {}", x); LL | | Some(x * 2) - | | ----------- this tail expression is of type `std::option::Option<_>` + | | ----------- this tail expression is of type `Option<_>` LL | | LL | | }); | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>` diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index 688a532adc6a6..a86da627b7edb 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -29,9 +29,9 @@ LL | let sr: Vec<(u32, _, _) = vec![]; | ------ this expression has type `Vec<(_, _, _)>` ... LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); - | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `()` here + | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here | | - | `std::iter::Iterator::Item` is `&(_, _, _)` here + | `Iterator::Item` is `&(_, _, _)` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr index 9a560c631fec4..7dd135d91fb2f 100644 --- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -14,7 +14,7 @@ note: the method call chain might not have had the expected associated types LL | let x1: &[f64] = &v; | -- this expression has type `&Vec` LL | let x2: Vec = x1.into_iter().collect(); - | ^^^^^^^^^^^ `std::iter::Iterator::Item` is `&f64` here + | ^^^^^^^^^^^ `Iterator::Item` is `&f64` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -38,7 +38,7 @@ LL | let x1: &[f64] = &v; | -- this expression has type `&Vec` ... LL | let x3 = x1.into_iter().collect::>(); - | ^^^^^^^^^^^ `std::iter::Iterator::Item` is `&f64` here + | ^^^^^^^^^^^ `Iterator::Item` is `&f64` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index 833a5a7474aba..f8464c7ce766c 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -16,17 +16,17 @@ note: the method call chain might not have had the expected associated types LL | let scores = vec![(0, 0)] | ------------ this expression has type `Vec<({integer}, {integer})>` LL | .iter() - | ------ `std::iter::Iterator::Item` is `&({integer}, {integer})` here + | ------ `Iterator::Item` is `&({integer}, {integer})` here LL | .map(|(a, b)| { | __________^ LL | | a + b; LL | | }); - | |__________^ `std::iter::Iterator::Item` changed to `()` here + | |__________^ `Iterator::Item` changed to `()` here note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | LL | S: Sum, - | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` + | ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum` error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` --> $DIR/invalid-iterator-chain.rs:10:9 @@ -52,24 +52,24 @@ note: the method call chain might not have had the expected associated types LL | vec![0, 1] | ---------- this expression has type `Vec<{integer}>` LL | .iter() - | ------ `std::iter::Iterator::Item` is `&{integer}` here + | ------ `Iterator::Item` is `&{integer}` here LL | .map(|x| x * 2) - | ^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `{integer}` here + | ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here LL | .map(|x| x as f64) - | ----------------- `std::iter::Iterator::Item` changed to `f64` here + | ----------------- `Iterator::Item` changed to `f64` here LL | .map(|x| x as i64) - | ----------------- `std::iter::Iterator::Item` changed to `i64` here + | ----------------- `Iterator::Item` changed to `i64` here LL | .filter(|x| *x > 0) - | ------------------ `std::iter::Iterator::Item` remains `i64` here + | ------------------ `Iterator::Item` remains `i64` here LL | .map(|x| { x + 1 }) - | ------------------ `std::iter::Iterator::Item` remains `i64` here + | ------------------ `Iterator::Item` remains `i64` here LL | .map(|x| { x; }) - | ^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `()` here + | ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | LL | S: Sum, - | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` + | ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum` error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64` --> $DIR/invalid-iterator-chain.rs:22:9 @@ -94,20 +94,20 @@ note: the method call chain might not have had the expected associated types LL | vec![0, 1] | ---------- this expression has type `Vec<{integer}>` LL | .iter() - | ------ `std::iter::Iterator::Item` is `&{integer}` here + | ------ `Iterator::Item` is `&{integer}` here LL | .map(|x| x * 2) - | ^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `{integer}` here + | ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here LL | .map(|x| x as f64) - | ^^^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `f64` here + | ^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `f64` here LL | .filter(|x| *x > 0.0) - | -------------------- `std::iter::Iterator::Item` remains `f64` here + | -------------------- `Iterator::Item` remains `f64` here LL | .map(|x| { x + 1.0 }) - | -------------------- `std::iter::Iterator::Item` remains `f64` here + | -------------------- `Iterator::Item` remains `f64` here note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | LL | S: Sum, - | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` + | ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum` error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` --> $DIR/invalid-iterator-chain.rs:30:20 @@ -125,15 +125,15 @@ note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:30:38 | LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); - | ---------- ------ ^^^^^^^^^^^^^^^ `std::iter::Iterator::Item` changed to `()` here + | ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here | | | - | | `std::iter::Iterator::Item` is `&{integer}` here + | | `Iterator::Item` is `&{integer}` here | this expression has type `Vec<{integer}>` note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | LL | S: Sum, - | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` + | ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum` error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()` --> $DIR/invalid-iterator-chain.rs:31:20 @@ -151,14 +151,14 @@ note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:31:33 | LL | println!("{}", vec![(), ()].iter().sum::()); - | ------------ ^^^^^^ `std::iter::Iterator::Item` is `&()` here + | ------------ ^^^^^^ `Iterator::Item` is `&()` here | | | this expression has type `Vec<()>` note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | LL | S: Sum, - | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` + | ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum` error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `()` --> $DIR/invalid-iterator-chain.rs:40:23 @@ -176,23 +176,23 @@ note: the method call chain might not have had the expected associated types LL | let a = vec![0]; | ------- this expression has type `Vec<{integer}>` LL | let b = a.into_iter(); - | ----------- `std::iter::Iterator::Item` is `{integer}` here + | ----------- `Iterator::Item` is `{integer}` here LL | let c = b.map(|x| x + 1); - | -------------- `std::iter::Iterator::Item` remains `{integer}` here + | -------------- `Iterator::Item` remains `{integer}` here LL | let d = c.filter(|x| *x > 10 ); - | -------------------- `std::iter::Iterator::Item` remains `{integer}` here + | -------------------- `Iterator::Item` remains `{integer}` here LL | let e = d.map(|x| { | _______________^ LL | | x + 1; LL | | }); - | |______^ `std::iter::Iterator::Item` changed to `()` here + | |______^ `Iterator::Item` changed to `()` here LL | let f = e.filter(|_| false); - | ----------------- `std::iter::Iterator::Item` remains `()` here + | ----------------- `Iterator::Item` remains `()` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | LL | fn collect>(self) -> B - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect` error: aborting due to 6 previous errors diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr index 6dc039fc35db7..2db1cc4b77690 100644 --- a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr +++ b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr @@ -5,7 +5,7 @@ LL | foo(panic!()) | --- ^^^^^^^^ | | | | | the trait `T` is not implemented for `()` - | | this tail expression is of type `_` + | | this tail expression is of type `()` | required by a bound introduced by this call | note: required by a bound in `foo` diff --git a/src/test/ui/on-unimplemented/sum.stderr b/src/test/ui/on-unimplemented/sum.stderr index 6405be01e674f..c99f06da7a4d1 100644 --- a/src/test/ui/on-unimplemented/sum.stderr +++ b/src/test/ui/on-unimplemented/sum.stderr @@ -14,7 +14,7 @@ note: the method call chain might not have had the expected associated types --> $DIR/sum.rs:4:18 | LL | vec![(), ()].iter().sum::(); - | ------------ ^^^^^^ `std::iter::Iterator::Item` is `&()` here + | ------------ ^^^^^^ `Iterator::Item` is `&()` here | | | this expression has type `Vec<()>` note: required by a bound in `std::iter::Iterator::sum` @@ -39,7 +39,7 @@ note: the method call chain might not have had the expected associated types --> $DIR/sum.rs:7:18 | LL | vec![(), ()].iter().product::(); - | ------------ ^^^^^^ `std::iter::Iterator::Item` is `&()` here + | ------------ ^^^^^^ `Iterator::Item` is `&()` here | | | this expression has type `Vec<()>` note: required by a bound in `std::iter::Iterator::product` From 2838b8e515d139245fba71895277fab26082d522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 11 Dec 2022 14:49:50 -0800 Subject: [PATCH 10/12] Point at method call when it is the source of the bound error --- compiler/rustc_errors/src/diagnostic.rs | 6 +- .../src/traits/error_reporting/suggestions.rs | 10 ++++ .../issue-101020.stderr | 6 +- src/test/ui/issues/issue-20162.stderr | 6 +- src/test/ui/issues/issue-31173.rs | 3 +- src/test/ui/issues/issue-31173.stderr | 32 ++++------- src/test/ui/issues/issue-33941.stderr | 6 +- src/test/ui/issues/issue-34334.stderr | 6 +- ...e-66923-show-error-for-correct-call.stderr | 12 ++-- src/test/ui/iterators/collect-into-array.rs | 1 - .../ui/iterators/collect-into-array.stderr | 6 +- src/test/ui/iterators/collect-into-slice.rs | 1 - .../ui/iterators/collect-into-slice.stderr | 6 +- .../ui/iterators/invalid-iterator-chain.rs | 8 +-- .../iterators/invalid-iterator-chain.stderr | 55 ++++++------------- .../branches.stderr | 6 +- .../recursion4.stderr | 12 ++-- .../method-help-unsatisfied-bound.stderr | 6 +- src/test/ui/not-clone-closure.stderr | 6 +- src/test/ui/on-unimplemented/sum.stderr | 12 ++-- .../const-default-method-bodies.stderr | 6 +- .../cross-crate.gatednc.stderr | 6 +- .../cross-crate.stocknc.stderr | 6 +- ...-method-body-is-const-same-trait-ck.stderr | 6 +- .../super-traits-fail-2.yn.stderr | 6 +- .../super-traits-fail-2.yy.stderr | 6 +- .../issue-71394-no-from-impl.stderr | 6 +- src/test/ui/traits/issue-97576.stderr | 6 +- src/test/ui/unsized/issue-71659.stderr | 6 +- 29 files changed, 96 insertions(+), 164 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 06bb5edc090f4..6bc0c26156549 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -370,7 +370,11 @@ impl Diagnostic { self.set_span(after); for span_label in before.span_labels() { if let Some(label) = span_label.label { - self.span.push_span_label(after, label); + if span_label.is_primary { + self.span.push_span_label(after, label); + } else { + self.span.push_span_label(span_label.span, label); + } } } self 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 adc64463b3b7a..162e73faa2a8a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3108,6 +3108,16 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { point_at_chain(expr); } } + let call_node = hir.find(call_hir_id); + if let Some(Node::Expr(hir::Expr { + kind: hir::ExprKind::MethodCall(path, rcvr, ..), + .. + })) = call_node + { + if Some(rcvr.span) == err.span.primary_span() { + err.replace_span_with(path.ident.span); + } + } if let Some(Node::Expr(hir::Expr { kind: hir::ExprKind::Call(hir::Expr { span, .. }, _) diff --git a/src/test/ui/generic-associated-types/issue-101020.stderr b/src/test/ui/generic-associated-types/issue-101020.stderr index b4e94cb83f738..422ac5484271d 100644 --- a/src/test/ui/generic-associated-types/issue-101020.stderr +++ b/src/test/ui/generic-associated-types/issue-101020.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satisfied - --> $DIR/issue-101020.rs:31:5 + --> $DIR/issue-101020.rs:31:22 | LL | (&mut EmptyIter).consume(()); - | ^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call - | | - | the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()` + | ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()` | note: required for `&'a mut ()` to implement `for<'a> FuncInput<'a, &'a mut ()>` --> $DIR/issue-101020.rs:27:20 diff --git a/src/test/ui/issues/issue-20162.stderr b/src/test/ui/issues/issue-20162.stderr index 3f9b3be985179..d70bf6e1d921c 100644 --- a/src/test/ui/issues/issue-20162.stderr +++ b/src/test/ui/issues/issue-20162.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `X: Ord` is not satisfied - --> $DIR/issue-20162.rs:5:5 + --> $DIR/issue-20162.rs:5:7 | LL | b.sort(); - | ^ ---- required by a bound introduced by this call - | | - | the trait `Ord` is not implemented for `X` + | ^^^^ the trait `Ord` is not implemented for `X` | note: required by a bound in `slice::::sort` --> $SRC_DIR/alloc/src/slice.rs:LL:COL diff --git a/src/test/ui/issues/issue-31173.rs b/src/test/ui/issues/issue-31173.rs index 04efa27189b74..f678df5b42b60 100644 --- a/src/test/ui/issues/issue-31173.rs +++ b/src/test/ui/issues/issue-31173.rs @@ -4,12 +4,11 @@ pub fn get_tok(it: &mut IntoIter) { let mut found_e = false; let temp: Vec = it - //~^ ERROR to be an iterator that yields `&_`, but it yields `u8` .take_while(|&x| { found_e = true; false }) - .cloned() + .cloned() //~ ERROR to be an iterator that yields `&_`, but it yields `u8` .collect(); //~ ERROR the method } diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 58d9b564427a7..62d841f37893f 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -1,16 +1,8 @@ -error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter, [closure@$DIR/issue-31173.rs:8:21: 8:25]>` to be an iterator that yields `&_`, but it yields `u8` - --> $DIR/issue-31173.rs:6:25 - | -LL | let temp: Vec = it - | _________________________^ -LL | | -LL | | .take_while(|&x| { -LL | | found_e = true; -LL | | false -LL | | }) - | |__________^ expected reference, found `u8` -LL | .cloned() - | ------ required by a bound introduced by this call +error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter, [closure@$DIR/issue-31173.rs:7:21: 7:25]>` to be an iterator that yields `&_`, but it yields `u8` + --> $DIR/issue-31173.rs:11:10 + | +LL | .cloned() + | ^^^^^^ expected reference, found `u8` | = note: expected reference `&_` found type `u8` @@ -20,11 +12,11 @@ note: required by a bound in `cloned` LL | Self: Sized + Iterator, | ^^^^^^^^^^^^ required by this bound in `Iterator::cloned` -error[E0599]: the method `collect` exists for struct `Cloned, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>`, but its trait bounds were not satisfied - --> $DIR/issue-31173.rs:13:10 +error[E0599]: the method `collect` exists for struct `Cloned, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>`, but its trait bounds were not satisfied + --> $DIR/issue-31173.rs:12:10 | LL | .collect(); - | ^^^^^^^ method cannot be called on `Cloned, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>` due to unsatisfied trait bounds + | ^^^^^^^ method cannot be called on `Cloned, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>` due to unsatisfied trait bounds | ::: $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL | @@ -37,10 +29,10 @@ LL | pub struct Cloned { | -------------------- doesn't satisfy `_: Iterator` | = note: the following trait bounds were not satisfied: - `, [closure@$DIR/issue-31173.rs:8:21: 8:25]> as Iterator>::Item = &_` - which is required by `Cloned, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator` - `Cloned, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator` - which is required by `&mut Cloned, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator` + `, [closure@$DIR/issue-31173.rs:7:21: 7:25]> as Iterator>::Item = &_` + which is required by `Cloned, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator` + `Cloned, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator` + which is required by `&mut Cloned, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index c28986a29854b..73a9b786fe2b5 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -1,10 +1,8 @@ error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - --> $DIR/issue-33941.rs:6:14 + --> $DIR/issue-33941.rs:6:36 | LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^^^^^^^^^^^^^^^^ ------ required by a bound introduced by this call - | | - | expected reference, found tuple + | ^^^^^^ expected reference, found tuple | = note: expected reference `&_` found tuple `(&_, &_)` diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index a86da627b7edb..b610e5c136668 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -13,12 +13,10 @@ LL | let sr: Vec<(u32, _, _)> = vec![]; | + error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()` - --> $DIR/issue-34334.rs:5:33 + --> $DIR/issue-34334.rs:5:87 | LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call - | | - | value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator` + | ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` = help: the trait `FromIterator` is implemented for `Vec` diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr index 7dd135d91fb2f..c6352978613aa 100644 --- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -1,10 +1,8 @@ error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `&f64` - --> $DIR/issue-66923-show-error-for-correct-call.rs:8:24 + --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39 | LL | let x2: Vec = x1.into_iter().collect(); - | ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call - | | - | value of type `Vec` cannot be built from `std::iter::Iterator` + | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<&f64>` is not implemented for `Vec` = help: the trait `FromIterator` is implemented for `Vec` @@ -22,12 +20,10 @@ LL | fn collect>(self) -> B | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect` error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `&f64` - --> $DIR/issue-66923-show-error-for-correct-call.rs:12:14 + --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29 | LL | let x3 = x1.into_iter().collect::>(); - | ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call - | | - | value of type `Vec` cannot be built from `std::iter::Iterator` + | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<&f64>` is not implemented for `Vec` = help: the trait `FromIterator` is implemented for `Vec` diff --git a/src/test/ui/iterators/collect-into-array.rs b/src/test/ui/iterators/collect-into-array.rs index 4c424999b754d..99d0d9bd73553 100644 --- a/src/test/ui/iterators/collect-into-array.rs +++ b/src/test/ui/iterators/collect-into-array.rs @@ -3,5 +3,4 @@ fn main() { //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()` //~| NOTE required by a bound in `collect` - //~| NOTE required by a bound introduced by this call } diff --git a/src/test/ui/iterators/collect-into-array.stderr b/src/test/ui/iterators/collect-into-array.stderr index 544b1da178a3d..7a07fed1fae3a 100644 --- a/src/test/ui/iterators/collect-into-array.stderr +++ b/src/test/ui/iterators/collect-into-array.stderr @@ -1,10 +1,8 @@ error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator - --> $DIR/collect-into-array.rs:2:31 + --> $DIR/collect-into-array.rs:2:39 | LL | let whatever: [u32; 10] = (0..10).collect(); - | ^^^^^^^ ------- required by a bound introduced by this call - | | - | try collecting into a `Vec<{integer}>`, then using `.try_into()` + | ^^^^^^^ try collecting into a `Vec<{integer}>`, then using `.try_into()` | = help: the trait `FromIterator<{integer}>` is not implemented for `[u32; 10]` note: required by a bound in `collect` diff --git a/src/test/ui/iterators/collect-into-slice.rs b/src/test/ui/iterators/collect-into-slice.rs index 09832c260d04e..5a8aacb1a6df0 100644 --- a/src/test/ui/iterators/collect-into-slice.rs +++ b/src/test/ui/iterators/collect-into-slice.rs @@ -13,6 +13,5 @@ fn main() { //~| NOTE all local variables must have a statically known size //~| NOTE doesn't have a size known at compile-time //~| NOTE doesn't have a size known at compile-time - //~| NOTE required by a bound introduced by this call process_slice(&some_generated_vec); } diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr index 65ef124a46302..58da222e0397b 100644 --- a/src/test/ui/iterators/collect-into-slice.stderr +++ b/src/test/ui/iterators/collect-into-slice.stderr @@ -22,12 +22,10 @@ LL | fn collect>(self) -> B | ^ required by this bound in `Iterator::collect` error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size - --> $DIR/collect-into-slice.rs:6:30 + --> $DIR/collect-into-slice.rs:6:38 | LL | let some_generated_vec = (0..10).collect(); - | ^^^^^^^ ------- required by a bound introduced by this call - | | - | try explicitly collecting into a `Vec<{integer}>` + | ^^^^^^^ try explicitly collecting into a `Vec<{integer}>` | = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]` note: required by a bound in `collect` diff --git a/src/test/ui/iterators/invalid-iterator-chain.rs b/src/test/ui/iterators/invalid-iterator-chain.rs index 32141bf0fb84e..87116e4924570 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.rs +++ b/src/test/ui/iterators/invalid-iterator-chain.rs @@ -7,7 +7,7 @@ fn main() { println!("{}", scores.sum::()); //~ ERROR E0277 println!( "{}", - vec![0, 1] //~ ERROR E0277 + vec![0, 1] .iter() .map(|x| x * 2) .map(|x| x as f64) @@ -15,17 +15,17 @@ fn main() { .filter(|x| *x > 0) .map(|x| { x + 1 }) .map(|x| { x; }) - .sum::(), + .sum::(), //~ ERROR E0277 ); println!( "{}", - vec![0, 1] //~ ERROR E0277 + vec![0, 1] .iter() .map(|x| x * 2) .map(|x| x as f64) .filter(|x| *x > 0.0) .map(|x| { x + 1.0 }) - .sum::(), + .sum::(), //~ ERROR E0277 ); println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); //~ ERROR E0277 println!("{}", vec![(), ()].iter().sum::()); //~ ERROR E0277 diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index f8464c7ce766c..49651b20fb16d 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -1,10 +1,8 @@ error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` - --> $DIR/invalid-iterator-chain.rs:7:20 + --> $DIR/invalid-iterator-chain.rs:7:27 | LL | println!("{}", scores.sum::()); - | ^^^^^^ --- required by a bound introduced by this call - | | - | value of type `i32` cannot be made by summing a `std::iter::Iterator` + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` | = help: the trait `Sum<()>` is not implemented for `i32` = help: the following other types implement trait `Sum`: @@ -29,18 +27,10 @@ LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum` error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` - --> $DIR/invalid-iterator-chain.rs:10:9 - | -LL | / vec![0, 1] -LL | | .iter() -LL | | .map(|x| x * 2) -LL | | .map(|x| x as f64) -... | -LL | | .map(|x| { x + 1 }) -LL | | .map(|x| { x; }) - | |____________________________^ value of type `i32` cannot be made by summing a `std::iter::Iterator` -LL | .sum::(), - | --- required by a bound introduced by this call + --> $DIR/invalid-iterator-chain.rs:18:14 + | +LL | .sum::(), + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` | = help: the trait `Sum<()>` is not implemented for `i32` = help: the following other types implement trait `Sum`: @@ -72,17 +62,10 @@ LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum` error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64` - --> $DIR/invalid-iterator-chain.rs:22:9 - | -LL | / vec![0, 1] -LL | | .iter() -LL | | .map(|x| x * 2) -LL | | .map(|x| x as f64) -LL | | .filter(|x| *x > 0.0) -LL | | .map(|x| { x + 1.0 }) - | |_________________________________^ value of type `i32` cannot be made by summing a `std::iter::Iterator` -LL | .sum::(), - | --- required by a bound introduced by this call + --> $DIR/invalid-iterator-chain.rs:28:14 + | +LL | .sum::(), + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` | = help: the trait `Sum` is not implemented for `i32` = help: the following other types implement trait `Sum`: @@ -110,12 +93,10 @@ LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum` error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` - --> $DIR/invalid-iterator-chain.rs:30:20 + --> $DIR/invalid-iterator-chain.rs:30:54 | LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call - | | - | value of type `i32` cannot be made by summing a `std::iter::Iterator` + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` | = help: the trait `Sum<()>` is not implemented for `i32` = help: the following other types implement trait `Sum`: @@ -136,12 +117,10 @@ LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum` error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()` - --> $DIR/invalid-iterator-chain.rs:31:20 + --> $DIR/invalid-iterator-chain.rs:31:40 | LL | println!("{}", vec![(), ()].iter().sum::()); - | ^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call - | | - | value of type `i32` cannot be made by summing a `std::iter::Iterator` + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` | = help: the trait `Sum<&()>` is not implemented for `i32` = help: the following other types implement trait `Sum`: @@ -161,12 +140,10 @@ LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum` error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `()` - --> $DIR/invalid-iterator-chain.rs:40:23 + --> $DIR/invalid-iterator-chain.rs:40:25 | LL | let g: Vec = f.collect(); - | ^ ------- required by a bound introduced by this call - | | - | value of type `Vec` cannot be built from `std::iter::Iterator` + | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<()>` is not implemented for `Vec` = help: the trait `FromIterator` is implemented for `Vec` diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches.stderr b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr index 5a46027dd52ba..c66069c4d2570 100644 --- a/src/test/ui/lazy-type-alias-impl-trait/branches.stderr +++ b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr @@ -1,10 +1,8 @@ error[E0277]: a value of type `Bar` cannot be built from an iterator over elements of type `_` - --> $DIR/branches.rs:19:9 + --> $DIR/branches.rs:19:28 | LL | std::iter::empty().collect() - | ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call - | | - | value of type `Bar` cannot be built from `std::iter::Iterator` + | ^^^^^^^ value of type `Bar` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<_>` is not implemented for `Bar` note: required by a bound in `collect` diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr index a4b4968b7d24c..a92c3a6809eae 100644 --- a/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr +++ b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr @@ -1,10 +1,8 @@ error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_` - --> $DIR/recursion4.rs:10:9 + --> $DIR/recursion4.rs:10:28 | LL | x = std::iter::empty().collect(); - | ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call - | | - | value of type `Foo` cannot be built from `std::iter::Iterator` + | ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<_>` is not implemented for `Foo` note: required by a bound in `collect` @@ -14,12 +12,10 @@ LL | fn collect>(self) -> B | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect` error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_` - --> $DIR/recursion4.rs:19:9 + --> $DIR/recursion4.rs:19:28 | LL | x = std::iter::empty().collect(); - | ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call - | | - | value of type `impl Debug` cannot be built from `std::iter::Iterator` + | ^^^^^^^ value of type `impl Debug` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<_>` is not implemented for `impl Debug` note: required by a bound in `collect` diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index 36748fae13c94..c2515c40b1d77 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -1,10 +1,8 @@ error[E0277]: `Foo` doesn't implement `Debug` - --> $DIR/method-help-unsatisfied-bound.rs:5:5 + --> $DIR/method-help-unsatisfied-bound.rs:5:7 | LL | a.unwrap(); - | ^ ------ required by a bound introduced by this call - | | - | `Foo` cannot be formatted using `{:?}` + | ^^^^^^ `Foo` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `Foo` = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo` diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr index f61ee661bb7ed..37d94cf0ebd8c 100644 --- a/src/test/ui/not-clone-closure.stderr +++ b/src/test/ui/not-clone-closure.stderr @@ -1,13 +1,11 @@ error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]` - --> $DIR/not-clone-closure.rs:11:17 + --> $DIR/not-clone-closure.rs:11:23 | LL | let hello = move || { | ------- within this `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]` ... LL | let hello = hello.clone(); - | ^^^^^ ----- required by a bound introduced by this call - | | - | within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S` + | ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S` | note: required because it's used within this closure --> $DIR/not-clone-closure.rs:7:17 diff --git a/src/test/ui/on-unimplemented/sum.stderr b/src/test/ui/on-unimplemented/sum.stderr index c99f06da7a4d1..70706541ad650 100644 --- a/src/test/ui/on-unimplemented/sum.stderr +++ b/src/test/ui/on-unimplemented/sum.stderr @@ -1,10 +1,8 @@ error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()` - --> $DIR/sum.rs:4:5 + --> $DIR/sum.rs:4:25 | LL | vec![(), ()].iter().sum::(); - | ^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call - | | - | value of type `i32` cannot be made by summing a `std::iter::Iterator` + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` | = help: the trait `Sum<&()>` is not implemented for `i32` = help: the following other types implement trait `Sum`: @@ -24,12 +22,10 @@ LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum` error[E0277]: a value of type `i32` cannot be made by multiplying all elements of type `&()` from an iterator - --> $DIR/sum.rs:7:5 + --> $DIR/sum.rs:7:25 | LL | vec![(), ()].iter().product::(); - | ^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call - | | - | value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator` + | ^^^^^^^ value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator` | = help: the trait `Product<&()>` is not implemented for `i32` = help: the following other types implement trait `Product`: diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr index c64930db9bee2..f9d0d1f7875fb 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied - --> $DIR/const-default-method-bodies.rs:24:5 + --> $DIR/const-default-method-bodies.rs:24:18 | LL | NonConstImpl.a(); - | ^^^^^^^^^^^^ - required by a bound introduced by this call - | | - | the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl` + | ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl` | note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const` --> $DIR/const-default-method-bodies.rs:24:5 diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr index 925ae53e32499..633b7cc255a52 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied - --> $DIR/cross-crate.rs:17:5 + --> $DIR/cross-crate.rs:17:14 | LL | NonConst.func(); - | ^^^^^^^^ ---- required by a bound introduced by this call - | | - | the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst` + | ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst` | note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const` --> $DIR/cross-crate.rs:17:5 diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr index 11db0c2b8f290..9e97d3f113760 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `cross_crate::NonConst: cross_crate::MyTrait` is not satisfied - --> $DIR/cross-crate.rs:17:5 + --> $DIR/cross-crate.rs:17:14 | LL | NonConst.func(); - | ^^^^^^^^ ---- required by a bound introduced by this call - | | - | the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst` + | ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst` | note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const` --> $DIR/cross-crate.rs:17:5 diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr index c2c16921c2eb2..21ecddaffbb65 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `(): ~const Tr` is not satisfied - --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9 + --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12 | LL | ().a() - | ^^ - required by a bound introduced by this call - | | - | the trait `~const Tr` is not implemented for `()` + | ^ the trait `~const Tr` is not implemented for `()` | note: the trait `Tr` is implemented for `()`, but that implementation is not `const` --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9 diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr index b52eb2c0332fd..13fc719f28c5c 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-2.rs:15:5 + --> $DIR/super-traits-fail-2.rs:15:7 | LL | x.a(); - | ^ - required by a bound introduced by this call - | | - | the trait `~const Foo` is not implemented for `T` + | ^ the trait `~const Foo` is not implemented for `T` | note: the trait `Foo` is implemented for `T`, but that implementation is not `const` --> $DIR/super-traits-fail-2.rs:15:5 diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr index b52eb2c0332fd..13fc719f28c5c 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-2.rs:15:5 + --> $DIR/super-traits-fail-2.rs:15:7 | LL | x.a(); - | ^ - required by a bound introduced by this call - | | - | the trait `~const Foo` is not implemented for `T` + | ^ the trait `~const Foo` is not implemented for `T` | note: the trait `Foo` is implemented for `T`, but that implementation is not `const` --> $DIR/super-traits-fail-2.rs:15:5 diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr index 684db23e1355f..a5e6f5b5ffcb0 100644 --- a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied - --> $DIR/issue-71394-no-from-impl.rs:3:20 + --> $DIR/issue-71394-no-from-impl.rs:3:25 | LL | let _: &[i8] = data.into(); - | ^^^^ ---- required by a bound introduced by this call - | | - | the trait `From<&[u8]>` is not implemented for `&[i8]` + | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]` | = help: the following other types implement trait `From`: <[T; LANES] as From>> diff --git a/src/test/ui/traits/issue-97576.stderr b/src/test/ui/traits/issue-97576.stderr index 146d38d076a3c..9062a0fab630a 100644 --- a/src/test/ui/traits/issue-97576.stderr +++ b/src/test/ui/traits/issue-97576.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `String: From` is not satisfied - --> $DIR/issue-97576.rs:8:18 + --> $DIR/issue-97576.rs:8:22 | LL | bar: bar.into(), - | ^^^ ---- required by a bound introduced by this call - | | - | the trait `From` is not implemented for `String` + | ^^^^ the trait `From` is not implemented for `String` | = note: required for `impl ToString` to implement `Into` diff --git a/src/test/ui/unsized/issue-71659.stderr b/src/test/ui/unsized/issue-71659.stderr index 50060e53a49d6..d7b95f55769fd 100644 --- a/src/test/ui/unsized/issue-71659.stderr +++ b/src/test/ui/unsized/issue-71659.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied - --> $DIR/issue-71659.rs:30:13 + --> $DIR/issue-71659.rs:30:15 | LL | let x = x.cast::<[i32]>(); - | ^ ---- required by a bound introduced by this call - | | - | the trait `CastTo<[i32]>` is not implemented for `dyn Foo` + | ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo` | note: required by a bound in `Cast::cast` --> $DIR/issue-71659.rs:19:15 From 348386985d41852829c0785dd84e50c2780b7f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Dec 2022 09:13:27 -0800 Subject: [PATCH 11/12] Move logic to their own methods --- .../traits/error_reporting/method_chain.rs | 74 ++ .../src/traits/error_reporting/mod.rs | 1 + .../src/traits/error_reporting/suggestions.rs | 678 ++++++++---------- 3 files changed, 391 insertions(+), 362 deletions(-) create mode 100644 compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs 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 new file mode 100644 index 0000000000000..cb373d657721b --- /dev/null +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs @@ -0,0 +1,74 @@ +use crate::infer::InferCtxt; + +use rustc_middle::ty::error::TypeError; +use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; +use rustc_middle::ty::{self, Ty, TyCtxt}; + +pub struct CollectAllMismatches<'a, 'tcx> { + pub infcx: &'a InferCtxt<'tcx>, + pub param_env: ty::ParamEnv<'tcx>, + pub errors: Vec>, +} + +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, + _: ty::VarianceDiagInfo<'tcx>, + a: T, + b: T, + ) -> RelateResult<'tcx, T> { + self.relate(a, b) + } + fn regions( + &mut self, + a: ty::Region<'tcx>, + _b: ty::Region<'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) + }) + } + fn consts( + &mut self, + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ty::Const<'tcx>> { + if a == b { + return Ok(a); + } + relate::super_relate_consts(self, a, b) // could do something similar here for constants! + } + fn binders>( + &mut self, + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> { + Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?)) + } +} 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 78364253adbca..a0ed1fc751b9c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1,4 +1,5 @@ mod ambiguity; +pub mod method_chain; pub mod on_unimplemented; pub mod suggestions; 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 162e73faa2a8a..df470f6208910 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -24,7 +24,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi use rustc_infer::infer::{InferOk, LateBoundRegionConversionTime}; use rustc_middle::hir::map; use rustc_middle::ty::error::TypeError::{self, Sorts}; -use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; +use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree, GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts, @@ -36,6 +36,7 @@ use rustc_span::{BytePos, DesugaringKind, ExpnKind, Span, DUMMY_SP}; use rustc_target::spec::abi; use std::ops::Deref; +use super::method_chain::CollectAllMismatches; use super::InferCtxtPrivExt; use crate::infer::InferCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; @@ -332,6 +333,23 @@ pub trait TypeErrCtxtExt<'tcx> { err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, ); + fn function_argument_obligation( + &self, + arg_hir_id: HirId, + err: &mut Diagnostic, + parent_code: &ObligationCauseCode<'tcx>, + param_env: ty::ParamEnv<'tcx>, + predicate: ty::Predicate<'tcx>, + call_hir_id: HirId, + ); + fn point_at_chain( + &self, + expr: &hir::Expr<'_>, + typeck_results: &TypeckResults<'tcx>, + type_diffs: Vec>, + param_env: ty::ParamEnv<'tcx>, + err: &mut Diagnostic, + ); } fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) { @@ -2840,298 +2858,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { call_hir_id, ref parent_code, } => { - let hir = self.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 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()); - let span = expr.span; - if Some(span) != err.span.primary_span() { - err.span_label( - span, - if ty.references_error() { - String::new() - } else { - let ty = with_forced_trimmed_paths!(self.ty_to_string(ty)); - format!("this tail expression is of type `{ty}`") - }, - ); - } - } - - let mut primary_spans = vec![]; - let mut span_labels = vec![]; - - // FIXME: visit the ty to see if there's any closure involved, and if there is, - // check whether its evaluated return type is the same as the one corresponding - // to an associated type (as seen from `trait_pred`) in the predicate. Like in - // trait_pred `S: Sum<::Item>` and predicate `i32: Sum<&()>` - 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(pred) = predicates.predicates.get(*idx) - && let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() - { - let mut c = CollectAllMismatches { - infcx: self.infcx, - param_env: param_env, - errors: vec![], - }; - if let ty::PredicateKind::Clause(ty::Clause::Trait( - predicate - )) = predicate.kind().skip_binder() - { - if let Ok(_) = c.relate(trait_pred, predicate) { - type_diffs = c.errors; - } - } - } - let point_at_chain = |expr: &hir::Expr<'_>| { - let mut assocs = vec![]; - // We still want to point at the different methods even if there hasn't - // been a change of assoc type. - let mut call_spans = vec![]; - let mut expr = expr; - let mut prev_ty = self.resolve_vars_if_possible( - typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()), - ); - while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = - expr.kind - { - // Point at every method call in the chain with the resulting type. - // vec![1, 2, 3].iter().map(mapper).sum() - // ^^^^^^ ^^^^^^^^^^^ - expr = rcvr_expr; - let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len()); - call_spans.push(span); - - let ocx = ObligationCtxt::new_in_snapshot(self.infcx); - for diff in &type_diffs { - let Sorts(expected_found) = diff else { continue; }; - let ty::Projection(proj) = expected_found.expected.kind() else { continue; }; - - let origin = TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span, - }; - let trait_def_id = proj.trait_def_id(self.tcx); - // Make `Self` be equivalent to the type of the call chain - // expression we're looking at now, so that we can tell what - // for example `Iterator::Item` is at this point in the chain. - let substs = - InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| { - match param.kind { - ty::GenericParamDefKind::Type { .. } => { - if param.index == 0 { - return prev_ty.into(); - } - } - ty::GenericParamDefKind::Lifetime - | ty::GenericParamDefKind::Const { .. } => {} - } - self.var_for_def(span, param) - }); - // This will hold the resolved type of the associated type, if the - // current expression implements the trait that associated type is - // in. For example, this would be what `Iterator::Item` is here. - let ty_var = self.infcx.next_ty_var(origin); - // This corresponds to `::Item = _`. - let trait_ref = ty::Binder::dummy(ty::PredicateKind::Clause( - ty::Clause::Projection(ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { - substs, - item_def_id: proj.item_def_id, - }, - term: ty_var.into(), - }), - )); - // Add `::Item = _` obligation. - ocx.register_obligation(Obligation::misc( - self.tcx, - span, - expr.hir_id, - param_env, - trait_ref, - )); - if ocx.select_where_possible().is_empty() { - // `ty_var` now holds the type that `Item` is for `ExprTy`. - let ty_var = self.resolve_vars_if_possible(ty_var); - assocs_in_this_method - .push(Some((span, (proj.item_def_id, ty_var)))); - } else { - // `` didn't select, so likely we've - // reached the end of the iterator chain, like the originating - // `Vec<_>`. - // Keep the space consistent for later zipping. - assocs_in_this_method.push(None); - } - } - assocs.push(assocs_in_this_method); - prev_ty = self.resolve_vars_if_possible( - typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()), - ); - - if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind - && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path - && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id) - && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id) - && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id) - && let Some(binding_expr) = local.init - { - // We've reached the root of the method call chain and it is a - // binding. Get the binding creation and try to continue the chain. - expr = binding_expr; - } - } - - // We want the type before deref coercions, otherwise we talk about `&[_]` - // instead of `Vec<_>`. - if let Some(ty) = typeck_results.expr_ty_opt(expr) { - let ty = with_forced_trimmed_paths!(self.ty_to_string(ty)); - // Point at the root expression - // vec![1, 2, 3].iter().map(mapper).sum() - // ^^^^^^^^^^^^^ - span_labels - .push((expr.span, format!("this expression has type `{ty}`"))); - }; - // Only show this if it is not a "trivial" expression (not a method - // chain) and there are associated types to talk about. - let mut assocs = assocs.into_iter().peekable(); - while let Some(assocs_in_method) = assocs.next() { - let Some(prev_assoc_in_method) = assocs.peek() else { - for entry in assocs_in_method { - let Some((span, (assoc, ty))) = entry else { continue; }; - if type_diffs.iter().any(|diff| { - let Sorts(expected_found) = diff else { return false; }; - self.can_eq(param_env, expected_found.found, ty).is_ok() - }) { - // FIXME: this doesn't quite work for `Iterator::collect` - // because we have `Vec` and `()`, but we'd want `i32` - // to point at the `.into_iter()` call, but as long as we - // still point at the other method calls that might have - // introduced the issue, this is fine for now. - primary_spans.push(span); - } - span_labels.push(( - span, - with_forced_trimmed_paths!(format!( - "`{}` is `{ty}` here", - self.tcx.def_path_str(assoc), - )), - )); - } - break; - }; - for (entry, prev_entry) in - assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter()) - { - match (entry, prev_entry) { - (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => { - let ty_str = - with_forced_trimmed_paths!(self.ty_to_string(ty)); - - let assoc = with_forced_trimmed_paths!( - self.tcx.def_path_str(assoc) - ); - if ty != *prev_ty { - if type_diffs.iter().any(|diff| { - let Sorts(expected_found) = diff else { return false; }; - self.can_eq(param_env, expected_found.found, ty).is_ok() - }) { - primary_spans.push(span); - } - span_labels.push(( - span, - format!("`{assoc}` changed to `{ty_str}` here"), - )); - } else { - span_labels.push(( - span, - format!("`{assoc}` remains `{ty_str}` here"), - )); - } - } - (Some((span, (assoc, ty))), None) => { - span_labels.push(( - span, - with_forced_trimmed_paths!(format!( - "`{}` is `{}` here", - self.tcx.def_path_str(assoc), - self.ty_to_string(ty), - )), - )); - } - (None, Some(_)) | (None, None) => {} - } - } - } - for span in call_spans { - if span_labels.iter().find(|(s, _)| *s == span).is_none() { - // Ensure we are showing the entire chain, even if the assoc types - // haven't changed. - span_labels.push((span, String::new())); - } - } - if !primary_spans.is_empty() { - let mut multi_span: MultiSpan = primary_spans.into(); - for (span, label) in span_labels { - multi_span.push_span_label(span, label); - } - err.span_note( - multi_span, - format!( - "the method call chain might not have had the expected \ - associated types", - ), - ); - } - }; - if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind - && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path - && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id) - && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id) - && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id) - && let Some(binding_expr) = local.init - { - // 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. - point_at_chain(binding_expr); - } else { - point_at_chain(expr); - } - } - let call_node = hir.find(call_hir_id); - if let Some(Node::Expr(hir::Expr { - kind: hir::ExprKind::MethodCall(path, rcvr, ..), - .. - })) = call_node - { - if Some(rcvr.span) == err.span.primary_span() { - err.replace_span_with(path.ident.span); - } - } - if let Some(Node::Expr(hir::Expr { - kind: - hir::ExprKind::Call(hir::Expr { span, .. }, _) - | hir::ExprKind::MethodCall( - hir::PathSegment { ident: Ident { span, .. }, .. }, - .., - ), - .. - })) = hir.find(call_hir_id) - { - if Some(*span) != err.span.primary_span() { - err.span_label(*span, "required by a bound introduced by this call"); - } - } + self.function_argument_obligation( + arg_hir_id, + err, + parent_code, + param_env, + predicate, + call_hir_id, + ); ensure_sufficient_stack(|| { self.note_obligation_cause_code( err, @@ -3356,6 +3090,295 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } } + fn function_argument_obligation( + &self, + arg_hir_id: HirId, + err: &mut Diagnostic, + parent_code: &ObligationCauseCode<'tcx>, + param_env: ty::ParamEnv<'tcx>, + predicate: ty::Predicate<'tcx>, + call_hir_id: HirId, + ) { + 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 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()); + let span = expr.span; + if Some(span) != err.span.primary_span() { + err.span_label( + span, + if ty.references_error() { + String::new() + } else { + let ty = with_forced_trimmed_paths!(self.ty_to_string(ty)); + format!("this tail expression is of type `{ty}`") + }, + ); + } + } + + // FIXME: visit the ty to see if there's any closure involved, and if there is, + // check whether its evaluated return type is the same as the one corresponding + // to an associated type (as seen from `trait_pred`) in the predicate. Like in + // trait_pred `S: Sum<::Item>` and predicate `i32: Sum<&()>` + 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(pred) = predicates.predicates.get(*idx) + && let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() + { + let mut c = CollectAllMismatches { + infcx: self.infcx, + param_env, + errors: vec![], + }; + if let ty::PredicateKind::Clause(ty::Clause::Trait( + predicate + )) = predicate.kind().skip_binder() + { + if let Ok(_) = c.relate(trait_pred, predicate) { + type_diffs = c.errors; + } + } + } + if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind + && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path + && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id) + && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id) + && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id) + && let Some(binding_expr) = local.init + { + // 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); + } else { + self.point_at_chain(expr, typeck_results, type_diffs, param_env, err); + } + } + let call_node = hir.find(call_hir_id); + if let Some(Node::Expr(hir::Expr { + kind: hir::ExprKind::MethodCall(path, rcvr, ..), .. + })) = call_node + { + if Some(rcvr.span) == err.span.primary_span() { + err.replace_span_with(path.ident.span); + } + } + if let Some(Node::Expr(hir::Expr { + kind: + hir::ExprKind::Call(hir::Expr { span, .. }, _) + | hir::ExprKind::MethodCall(hir::PathSegment { ident: Ident { span, .. }, .. }, ..), + .. + })) = hir.find(call_hir_id) + { + if Some(*span) != err.span.primary_span() { + err.span_label(*span, "required by a bound introduced by this call"); + } + } + } + + fn point_at_chain( + &self, + expr: &hir::Expr<'_>, + typeck_results: &TypeckResults<'tcx>, + type_diffs: Vec>, + param_env: ty::ParamEnv<'tcx>, + err: &mut Diagnostic, + ) { + let mut primary_spans = vec![]; + let mut span_labels = vec![]; + + let tcx = self.tcx; + + let mut assocs = vec![]; + // We still want to point at the different methods even if there hasn't + // been a change of assoc type. + let mut call_spans = vec![]; + let mut expr = expr; + let mut prev_ty = self.resolve_vars_if_possible( + typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()), + ); + while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind { + // Point at every method call in the chain with the resulting type. + // vec![1, 2, 3].iter().map(mapper).sum() + // ^^^^^^ ^^^^^^^^^^^ + expr = rcvr_expr; + let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len()); + call_spans.push(span); + + let ocx = ObligationCtxt::new_in_snapshot(self.infcx); + for diff in &type_diffs { + let Sorts(expected_found) = diff else { continue; }; + let ty::Projection(proj) = expected_found.expected.kind() else { continue; }; + + let origin = + TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }; + let trait_def_id = proj.trait_def_id(self.tcx); + // Make `Self` be equivalent to the type of the call chain + // expression we're looking at now, so that we can tell what + // for example `Iterator::Item` is at this point in the chain. + let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| { + match param.kind { + ty::GenericParamDefKind::Type { .. } => { + if param.index == 0 { + return prev_ty.into(); + } + } + ty::GenericParamDefKind::Lifetime + | ty::GenericParamDefKind::Const { .. } => {} + } + self.var_for_def(span, param) + }); + // This will hold the resolved type of the associated type, if the + // current expression implements the trait that associated type is + // in. For example, this would be what `Iterator::Item` is here. + let ty_var = self.infcx.next_ty_var(origin); + // This corresponds to `::Item = _`. + let trait_ref = ty::Binder::dummy(ty::PredicateKind::Clause( + ty::Clause::Projection(ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { substs, item_def_id: proj.item_def_id }, + term: ty_var.into(), + }), + )); + // Add `::Item = _` obligation. + ocx.register_obligation(Obligation::misc( + self.tcx, + span, + expr.hir_id, + param_env, + trait_ref, + )); + if ocx.select_where_possible().is_empty() { + // `ty_var` now holds the type that `Item` is for `ExprTy`. + let ty_var = self.resolve_vars_if_possible(ty_var); + assocs_in_this_method.push(Some((span, (proj.item_def_id, ty_var)))); + } else { + // `` didn't select, so likely we've + // reached the end of the iterator chain, like the originating + // `Vec<_>`. + // Keep the space consistent for later zipping. + assocs_in_this_method.push(None); + } + } + assocs.push(assocs_in_this_method); + prev_ty = self.resolve_vars_if_possible( + typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()), + ); + + if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind + && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path + && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id) + && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id) + && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id) + && let Some(binding_expr) = local.init + { + // We've reached the root of the method call chain and it is a + // binding. Get the binding creation and try to continue the chain. + expr = binding_expr; + } + } + // We want the type before deref coercions, otherwise we talk about `&[_]` + // instead of `Vec<_>`. + if let Some(ty) = typeck_results.expr_ty_opt(expr) { + let ty = with_forced_trimmed_paths!(self.ty_to_string(ty)); + // Point at the root expression + // vec![1, 2, 3].iter().map(mapper).sum() + // ^^^^^^^^^^^^^ + span_labels.push((expr.span, format!("this expression has type `{ty}`"))); + }; + // Only show this if it is not a "trivial" expression (not a method + // chain) and there are associated types to talk about. + let mut assocs = assocs.into_iter().peekable(); + while let Some(assocs_in_method) = assocs.next() { + let Some(prev_assoc_in_method) = assocs.peek() else { + for entry in assocs_in_method { + let Some((span, (assoc, ty))) = entry else { continue; }; + if type_diffs.iter().any(|diff| { + let Sorts(expected_found) = diff else { return false; }; + self.can_eq(param_env, expected_found.found, ty).is_ok() + }) { + // FIXME: this doesn't quite work for `Iterator::collect` + // because we have `Vec` and `()`, but we'd want `i32` + // to point at the `.into_iter()` call, but as long as we + // still point at the other method calls that might have + // introduced the issue, this is fine for now. + primary_spans.push(span); + } + span_labels.push(( + span, + with_forced_trimmed_paths!(format!( + "`{}` is `{ty}` here", + self.tcx.def_path_str(assoc), + )), + )); + } + break; + }; + for (entry, prev_entry) in + assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter()) + { + match (entry, prev_entry) { + (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => { + let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty)); + + let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc)); + if ty != *prev_ty { + if type_diffs.iter().any(|diff| { + let Sorts(expected_found) = diff else { return false; }; + self.can_eq(param_env, expected_found.found, ty).is_ok() + }) { + primary_spans.push(span); + } + span_labels + .push((span, format!("`{assoc}` changed to `{ty_str}` here"))); + } else { + span_labels.push((span, format!("`{assoc}` remains `{ty_str}` here"))); + } + } + (Some((span, (assoc, ty))), None) => { + span_labels.push(( + span, + with_forced_trimmed_paths!(format!( + "`{}` is `{}` here", + self.tcx.def_path_str(assoc), + self.ty_to_string(ty), + )), + )); + } + (None, Some(_)) | (None, None) => {} + } + } + } + for span in call_spans { + if span_labels.iter().find(|(s, _)| *s == span).is_none() { + // Ensure we are showing the entire chain, even if the assoc types + // haven't changed. + span_labels.push((span, String::new())); + } + } + if !primary_spans.is_empty() { + let mut multi_span: MultiSpan = primary_spans.into(); + for (span, label) in span_labels { + multi_span.push_span_label(span, label); + } + err.span_note( + multi_span, + format!( + "the method call chain might not have had the expected \ + associated types", + ), + ); + } + } } /// Collect all the returned expressions within the input expression. @@ -3543,72 +3566,3 @@ impl<'tcx> TypeFolder<'tcx> for ReplaceImplTraitFolder<'tcx> { self.tcx } } - -pub struct CollectAllMismatches<'a, 'tcx> { - pub infcx: &'a InferCtxt<'tcx>, - pub param_env: ty::ParamEnv<'tcx>, - pub errors: Vec>, -} - -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, - _: ty::VarianceDiagInfo<'tcx>, - a: T, - b: T, - ) -> RelateResult<'tcx, T> { - self.relate(a, b) - } - fn regions( - &mut self, - a: ty::Region<'tcx>, - _b: ty::Region<'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) - }) - } - fn consts( - &mut self, - a: ty::Const<'tcx>, - b: ty::Const<'tcx>, - ) -> RelateResult<'tcx, ty::Const<'tcx>> { - if a == b { - return Ok(a); - } - relate::super_relate_consts(self, a, b) // could do something similar here for constants! - } - fn binders>( - &mut self, - a: ty::Binder<'tcx, T>, - b: ty::Binder<'tcx, T>, - ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> { - Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?)) - } -} From f4ed2d1cca0106eb4aec99b61670ecac378ca087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Dec 2022 11:53:39 -0800 Subject: [PATCH 12/12] Do not `skip_binder`s --- .../src/traits/error_reporting/suggestions.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 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 df470f6208910..40c8102547112 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3133,18 +3133,21 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref() && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx) && let Some(pred) = predicates.predicates.get(*idx) - && let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() + && 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 mut c = CollectAllMismatches { infcx: self.infcx, param_env, errors: vec![], }; - if let ty::PredicateKind::Clause(ty::Clause::Trait( - predicate - )) = predicate.kind().skip_binder() - { - if let Ok(_) = c.relate(trait_pred, predicate) { + if 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 Ok(_) = c.relate(trait_pred, trait_predicate) { type_diffs = c.errors; } }