From 294944dfec2c3eaf8f5e9b76e478c14b7247cda2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Dec 2022 17:39:08 -0800 Subject: [PATCH 1/5] Point at method chains on `E0271` errors --- .../src/traits/error_reporting/suggestions.rs | 208 ++++++++++-------- src/test/ui/issues/issue-31173.stderr | 12 + src/test/ui/issues/issue-33941.stderr | 7 + 3 files changed, 138 insertions(+), 89 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 dd5085bf4f300..b18f675e562f6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -352,6 +352,14 @@ pub trait TypeErrCtxtExt<'tcx> { param_env: ty::ParamEnv<'tcx>, err: &mut Diagnostic, ); + fn probe_assoc_types_at_expr( + &self, + type_diffs: &[TypeError<'tcx>], + span: Span, + prev_ty: Ty<'tcx>, + body_id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + ) -> Vec))>>; } fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) { @@ -3152,23 +3160,37 @@ 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 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 Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred { + if let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred { ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred), _ => Err(()), - }) { + }) + && let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred { + ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred), + _ => Err(()), + }) + { + let mut c = CollectAllMismatches { + infcx: self.infcx, + param_env, + errors: vec![], + }; if let Ok(_) = c.relate(trait_pred, trait_predicate) { type_diffs = c.errors; } + } else if let ty::PredicateKind::Clause( + ty::Clause::Projection(proj) + ) = pred.kind().skip_binder() + && let ty::PredicateKind::Clause( + ty::Clause::Projection(projection) + ) = predicate.kind().skip_binder() + { + type_diffs = vec![ + Sorts(ty::error::ExpectedFound { + expected: self.tcx.mk_ty(ty::Alias(ty::Projection, proj.projection_ty)), + found: projection.term.ty().unwrap(), + }), + ]; } } if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind @@ -3221,10 +3243,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let tcx = self.tcx; + let mut print_root_expr = true; 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()), @@ -3234,63 +3254,8 @@ 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::Alias(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 projection = ty::Binder::dummy(ty::PredicateKind::Clause( - ty::Clause::Projection(ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(proj.def_id, substs), - term: ty_var.into(), - }), - )); - // Add `::Item = _` obligation. - ocx.register_obligation(Obligation::misc( - self.tcx, - span, - expr.hir_id, - param_env, - projection, - )); - 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.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); - } - } + let assocs_in_this_method = + self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env); 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()), @@ -3300,17 +3265,32 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { && 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 + && let Some(parent) = self.tcx.hir().find(parent_hir_id) { - // 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've reached the root of the method call chain... + if let hir::Node::Local(local) = parent + && let Some(binding_expr) = local.init + { + // ...and it is a binding. Get the binding creation and continue the chain. + expr = binding_expr; + } + if let hir::Node::Param(param) = parent { + // ...and it is a an fn argument. + let prev_ty = self.resolve_vars_if_possible( + typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error()), + ); + let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, param.ty_span, prev_ty, param.hir_id, param_env); + if assocs_in_this_method.iter().any(|a| a.is_some()) { + assocs.push(assocs_in_this_method); + print_root_expr = false; + } + break; + } } } // We want the type before deref coercions, otherwise we talk about `&[_]` // instead of `Vec<_>`. - if let Some(ty) = typeck_results.expr_ty_opt(expr) { + if let Some(ty) = typeck_results.expr_ty_opt(expr) && print_root_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() @@ -3324,7 +3304,7 @@ 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; }; - if type_diffs.iter().any(|diff| { + if primary_spans.is_empty() || type_diffs.iter().any(|diff| { let Sorts(expected_found) = diff else { return false; }; self.can_eq(param_env, expected_found.found, ty).is_ok() }) { @@ -3380,13 +3360,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } } - 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 { @@ -3394,13 +3367,70 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } err.span_note( multi_span, - format!( - "the method call chain might not have had the expected \ - associated types", - ), + format!("the method call chain might not have had the expected associated types"), ); } } + + fn probe_assoc_types_at_expr( + &self, + type_diffs: &[TypeError<'tcx>], + span: Span, + prev_ty: Ty<'tcx>, + body_id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + ) -> Vec))>> { + let ocx = ObligationCtxt::new_in_snapshot(self.infcx); + let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len()); + for diff in type_diffs { + let Sorts(expected_found) = diff else { continue; }; + let ty::Alias(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 projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection( + ty::ProjectionPredicate { + projection_ty: self.tcx.mk_alias_ty(proj.def_id, substs), + term: ty_var.into(), + }, + ))); + // Add `::Item = _` obligation. + ocx.register_obligation(Obligation::misc( + self.tcx, span, body_id, param_env, projection, + )); + 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.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_in_this_method + } } /// Add a hint to add a missing borrow or remove an unnecessary one. diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index a32359c2b9f79..99f0519b14cc4 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -6,6 +6,18 @@ LL | .cloned() | = note: expected reference `&_` found type `u8` +note: the method call chain might not have had the expected associated types + --> $DIR/issue-31173.rs:3:20 + | +LL | pub fn get_tok(it: &mut IntoIter) { + | ^^^^^^^^^^^^^^^^^ `Iterator::Item` is `u8` here +... +LL | .take_while(|&x| { + | __________- +LL | | found_e = true; +LL | | false +LL | | }) + | |__________- `Iterator::Item` remains `u8` here note: required by a bound in `cloned` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index 49702c4765863..f33d33308d756 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -6,6 +6,13 @@ LL | for _ in HashMap::new().iter().cloned() {} | = note: expected reference `&_` found tuple `(&_, &_)` +note: the method call chain might not have had the expected associated types + --> $DIR/issue-33941.rs:6:29 + | +LL | for _ in HashMap::new().iter().cloned() {} + | -------------- ^^^^^^ `Iterator::Item` is `(&_, &_)` here + | | + | this expression has type `HashMap<_, _>` note: required by a bound in `cloned` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL From 30ae261c42af221173dcec2b5b926b3273eb90eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Dec 2022 15:52:16 -0800 Subject: [PATCH 2/5] Use `with_forced_trimmed_paths` more --- .../src/traits/error_reporting/mod.rs | 37 +++++++++++-------- .../associated-types-overridden-binding-2.rs | 2 +- ...sociated-types-overridden-binding-2.stderr | 2 +- src/test/ui/issues/issue-31173.stderr | 2 +- src/test/ui/issues/issue-33941.rs | 6 +-- src/test/ui/issues/issue-33941.stderr | 6 +-- src/test/ui/traits/assoc-type-in-superbad.rs | 2 +- .../ui/traits/assoc-type-in-superbad.stderr | 2 +- .../ui/type-alias-impl-trait/issue-57961.rs | 2 +- .../type-alias-impl-trait/issue-57961.stderr | 2 +- 10 files changed, 34 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 3c5e36123ecf5..181316427609e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -35,7 +35,7 @@ use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; -use rustc_middle::ty::print::{FmtPrinter, Print}; +use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print}; use rustc_middle::ty::{ self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitable, @@ -1757,21 +1757,26 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let trait_def_id = pred.projection_ty.trait_def_id(self.tcx); let self_ty = pred.projection_ty.self_ty(); - if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() { - Some(format!( - "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it returns `{normalized_ty}`", - fn_kind = self_ty.prefix_string(self.tcx) - )) - } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() { - Some(format!( - "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it resolves to `{normalized_ty}`" - )) - } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) { - Some(format!( - "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it yields `{normalized_ty}`" - )) - } else { - None + with_forced_trimmed_paths! { + if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() { + Some(format!( + "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it \ + returns `{normalized_ty}`", + fn_kind = self_ty.prefix_string(self.tcx) + )) + } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() { + Some(format!( + "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \ + resolves to `{normalized_ty}`" + )) + } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) { + Some(format!( + "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \ + yields `{normalized_ty}`" + )) + } else { + None + } } } diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.rs b/src/test/ui/associated-types/associated-types-overridden-binding-2.rs index 26b9f4b3a9266..fed60ccf089d0 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding-2.rs +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.rs @@ -4,5 +4,5 @@ trait I32Iterator = Iterator; fn main() { let _: &dyn I32Iterator = &vec![42].into_iter(); - //~^ ERROR expected `std::vec::IntoIter` to be an iterator that yields `i32`, but it yields `u32` + //~^ ERROR expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` } diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr index 2d25f68de44ad..a28a0b74e4acc 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `std::vec::IntoIter` to be an iterator that yields `i32`, but it yields `u32` +error[E0271]: expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` --> $DIR/associated-types-overridden-binding-2.rs:6:43 | LL | let _: &dyn I32Iterator = &vec![42].into_iter(); diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 99f0519b14cc4..73989c5182069 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -1,4 +1,4 @@ -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` +error[E0271]: expected `TakeWhile<&mut 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() diff --git a/src/test/ui/issues/issue-33941.rs b/src/test/ui/issues/issue-33941.rs index 8430e85df8715..e3b6dcf55a744 100644 --- a/src/test/ui/issues/issue-33941.rs +++ b/src/test/ui/issues/issue-33941.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; fn main() { - for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - //~^ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - //~| ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` + for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` + //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` + //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` } diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index f33d33308d756..668eaabca4c46 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` +error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` --> $DIR/issue-33941.rs:6:36 | LL | for _ in HashMap::new().iter().cloned() {} @@ -16,7 +16,7 @@ LL | for _ in HashMap::new().iter().cloned() {} note: required by a bound in `cloned` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` +error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` --> $DIR/issue-33941.rs:6:14 | LL | for _ in HashMap::new().iter().cloned() {} @@ -27,7 +27,7 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: required for `Cloned>` to implement `Iterator` = note: required for `Cloned>` to implement `IntoIterator` -error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` +error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` --> $DIR/issue-33941.rs:6:14 | LL | for _ in HashMap::new().iter().cloned() {} diff --git a/src/test/ui/traits/assoc-type-in-superbad.rs b/src/test/ui/traits/assoc-type-in-superbad.rs index d7d6241ef708c..65340b2a2092f 100644 --- a/src/test/ui/traits/assoc-type-in-superbad.rs +++ b/src/test/ui/traits/assoc-type-in-superbad.rs @@ -10,7 +10,7 @@ pub trait Foo: Iterator::Key> { impl Foo for IntoIter { type Key = u32; - //~^ ERROR expected `std::vec::IntoIter` to be an iterator that yields `u32`, but it yields `i32` + //~^ ERROR expected `IntoIter` to be an iterator that yields `u32`, but it yields `i32` } fn main() {} diff --git a/src/test/ui/traits/assoc-type-in-superbad.stderr b/src/test/ui/traits/assoc-type-in-superbad.stderr index 3e2d9d9038aa7..7fa1d2c2eed67 100644 --- a/src/test/ui/traits/assoc-type-in-superbad.stderr +++ b/src/test/ui/traits/assoc-type-in-superbad.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `std::vec::IntoIter` to be an iterator that yields `u32`, but it yields `i32` +error[E0271]: expected `IntoIter` to be an iterator that yields `u32`, but it yields `i32` --> $DIR/assoc-type-in-superbad.rs:12:16 | LL | type Key = u32; diff --git a/src/test/ui/type-alias-impl-trait/issue-57961.rs b/src/test/ui/type-alias-impl-trait/issue-57961.rs index 24b3a045856a6..4aa5966ff25d4 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57961.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57961.rs @@ -8,7 +8,7 @@ trait Foo { impl Foo for () { type Bar = std::vec::IntoIter; - //~^ ERROR expected `std::vec::IntoIter` to be an iterator that yields `X`, but it yields `u32` + //~^ ERROR expected `IntoIter` to be an iterator that yields `X`, but it yields `u32` } fn incoherent() { diff --git a/src/test/ui/type-alias-impl-trait/issue-57961.stderr b/src/test/ui/type-alias-impl-trait/issue-57961.stderr index fb40895c49f15..8d11b48888947 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57961.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57961.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `std::vec::IntoIter` to be an iterator that yields `X`, but it yields `u32` +error[E0271]: expected `IntoIter` to be an iterator that yields `X`, but it yields `u32` --> $DIR/issue-57961.rs:10:16 | LL | type X = impl Sized; From 4d4d4786f956ce8423bb591e7c542db95bf374dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Dec 2022 16:34:04 -0800 Subject: [PATCH 3/5] Shorten trimmed display of closures When `with_forced_trimmed_paths` is used, only print filename and start of the closure's span, to reduce their verbosity. --- compiler/rustc_middle/src/ty/print/pretty.rs | 8 +++++++- compiler/rustc_span/src/lib.rs | 7 +++++++ compiler/rustc_span/src/source_map.rs | 15 +++++++++++---- .../issue-62203-hrtb-ice.stderr | 2 +- src/test/ui/issues/issue-31173.stderr | 2 +- .../fallback-closure-wrap.fallback.stderr | 2 +- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index b1bc6eb8b81c5..a1d53506707c9 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -16,6 +16,7 @@ use rustc_session::config::TrimmedDefPaths; use rustc_session::cstore::{ExternCrate, ExternCrateSource}; use rustc_session::Limit; use rustc_span::symbol::{kw, Ident, Symbol}; +use rustc_span::FileNameDisplayPreference; use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; use smallvec::SmallVec; @@ -818,11 +819,16 @@ pub trait PrettyPrinter<'tcx>: p!("@", print_def_path(did.to_def_id(), substs)); } else { let span = self.tcx().def_span(did); + let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { + FileNameDisplayPreference::Short + } else { + FileNameDisplayPreference::Remapped + }; p!(write( "@{}", // This may end up in stderr diagnostics but it may also be emitted // into MIR. Hence we use the remapped path if available - self.tcx().sess.source_map().span_to_embeddable_string(span) + self.tcx().sess.source_map().span_to_string(span, preference) )); } } else { diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 5525eb5331c27..2181c090027b5 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -259,6 +259,10 @@ impl RealFileName { FileNameDisplayPreference::Remapped => { self.remapped_path_if_available().to_string_lossy() } + FileNameDisplayPreference::Short => self + .local_path_if_available() + .file_name() + .map_or_else(|| "".into(), |f| f.to_string_lossy()), } } } @@ -302,6 +306,9 @@ pub enum FileNameDisplayPreference { /// Display the path before the application of rewrite rules provided via `--remap-path-prefix`. /// This is appropriate for use in user-facing output (such as diagnostics). Local, + /// Display only the filename, as a way to reduce the verbosity of the output. + /// This is appropriate for use in user-facing output (such as diagnostics). + Short, } pub struct FileNameDisplay<'a> { diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index fb3e4a6c083f8..d9c87ac0ba82b 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -438,7 +438,11 @@ impl SourceMap { } } - fn span_to_string(&self, sp: Span, filename_display_pref: FileNameDisplayPreference) -> String { + pub fn span_to_string( + &self, + sp: Span, + filename_display_pref: FileNameDisplayPreference, + ) -> String { if self.files.borrow().source_files.is_empty() || sp.is_dummy() { return "no-location".to_string(); } @@ -446,12 +450,15 @@ impl SourceMap { let lo = self.lookup_char_pos(sp.lo()); let hi = self.lookup_char_pos(sp.hi()); format!( - "{}:{}:{}: {}:{}", + "{}:{}:{}{}", lo.file.name.display(filename_display_pref), lo.line, lo.col.to_usize() + 1, - hi.line, - hi.col.to_usize() + 1, + if let FileNameDisplayPreference::Short = filename_display_pref { + String::new() + } else { + format!(": {}:{}", hi.line, hi.col.to_usize() + 1) + } ) } diff --git a/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr b/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr index ab5598e364fc4..fdd192f431370 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr @@ -30,7 +30,7 @@ LL | where LL | F: for<'r> T0<'r, (>::V,), O = >::V>, | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` -error[E0271]: expected `[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]` to be a closure that returns `Unit3`, but it returns `Unit4` +error[E0271]: expected `[closure@issue-62203-hrtb-ice.rs:42:16]` to be a closure that returns `Unit3`, but it returns `Unit4` --> $DIR/issue-62203-hrtb-ice.rs:39:9 | LL | let v = Unit2.m( diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 73989c5182069..5b51c2e32bf7d 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `TakeWhile<&mut IntoIter, [closure@$DIR/issue-31173.rs:7:21: 7:25]>` to be an iterator that yields `&_`, but it yields `u8` +error[E0271]: expected `TakeWhile<&mut IntoIter, [closure@issue-31173.rs:7:21]>` to be an iterator that yields `&_`, but it yields `u8` --> $DIR/issue-31173.rs:11:10 | LL | .cloned() diff --git a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr index 45cf3723483f3..a0f790dba15ed 100644 --- a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr +++ b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]` to be a closure that returns `()`, but it returns `!` +error[E0271]: expected `[closure@fallback-closure-wrap.rs:18:40]` to be a closure that returns `()`, but it returns `!` --> $DIR/fallback-closure-wrap.rs:18:31 | LL | let error = Closure::wrap(Box::new(move || { From 3b938f73f380542b3572600111442e769591f9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Dec 2022 16:57:34 -0800 Subject: [PATCH 4/5] Trim paths in E0599 --- .../rustc_hir_typeck/src/method/suggest.rs | 14 +++++--- .../issue-33784.stderr | 4 +-- .../ui/empty/empty-struct-braces-expr.stderr | 8 ++--- .../fn-help-with-err.stderr | 4 +-- .../issue-30786.stderr | 6 ++-- .../no-method-suggested-traits.stderr | 32 +++++++++---------- src/test/ui/issues/issue-30123.stderr | 4 +-- src/test/ui/issues/issue-31173.stderr | 2 +- src/test/ui/issues/issue-41880.stderr | 2 +- ...ethod-not-found-generic-arg-elision.stderr | 2 +- .../ui/mismatched_types/issue-36053-2.stderr | 2 +- .../mut-borrow-needed-by-trait.stderr | 4 +-- ...ed-closures-static-call-wrong-trait.stderr | 4 +-- 13 files changed, 46 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 5c0d5f32f0fd0..9cd9480c7a1e1 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -25,7 +25,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; -use rustc_middle::ty::print::with_crate_prefix; +use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths}; use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable}; use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef}; use rustc_span::symbol::{kw, sym, Ident}; @@ -270,7 +270,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty); - let ty_str = self.ty_to_string(rcvr_ty); + let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty)); let is_method = mode == Mode::MethodCall; let item_kind = if is_method { "method" @@ -563,7 +563,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let term = pred.skip_binder().term; let obligation = format!("{} = {}", projection_ty, term); - let quiet = format!("{} = {}", quiet_projection_ty, term); + let quiet = with_forced_trimmed_paths!(format!( + "{} = {}", + quiet_projection_ty, term + )); bound_span_label(projection_ty.self_ty(), &obligation, &quiet); Some((obligation, projection_ty.self_ty())) @@ -573,7 +576,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let self_ty = p.self_ty(); let path = p.print_only_trait_path(); let obligation = format!("{}: {}", self_ty, path); - let quiet = format!("_: {}", path); + let quiet = with_forced_trimmed_paths!(format!("_: {}", path)); bound_span_label(self_ty, &obligation, &quiet); Some((obligation, self_ty)) } @@ -796,7 +799,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (None, None) }; let primary_message = primary_message.unwrap_or_else(|| format!( - "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied" + "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \ + but its trait bounds were not satisfied" )); err.set_primary_message(&primary_message); if let Some(label) = label { diff --git a/src/test/ui/confuse-field-and-method/issue-33784.stderr b/src/test/ui/confuse-field-and-method/issue-33784.stderr index 34debb6831734..3906d64c94624 100644 --- a/src/test/ui/confuse-field-and-method/issue-33784.stderr +++ b/src/test/ui/confuse-field-and-method/issue-33784.stderr @@ -1,4 +1,4 @@ -error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope +error[E0599]: no method named `closure` found for reference `&Obj<[closure@issue-33784.rs:25:43]>` in the current scope --> $DIR/issue-33784.rs:27:7 | LL | p.closure(); @@ -9,7 +9,7 @@ help: to call the function stored in `closure`, surround the field access with p LL | (p.closure)(); | + + -error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope +error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@issue-33784.rs:25:43]>` in the current scope --> $DIR/issue-33784.rs:29:7 | LL | q.fn_ptr(); diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr index e1a7a02a56869..0e580aedeaa92 100644 --- a/src/test/ui/empty/empty-struct-braces-expr.stderr +++ b/src/test/ui/empty/empty-struct-braces-expr.stderr @@ -100,22 +100,22 @@ help: a unit struct with a similar name exists LL | let xe1 = XEmpty2(); | ~~~~~~~ -error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope +error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope --> $DIR/empty-struct-braces-expr.rs:25:19 | LL | let xe3 = XE::Empty3; | ^^^^^^ | | - | variant or associated item not found in `empty_struct::XE` + | variant or associated item not found in `XE` | help: there is a variant with a similar name: `XEmpty3` -error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope +error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope --> $DIR/empty-struct-braces-expr.rs:26:19 | LL | let xe3 = XE::Empty3(); | ^^^^^^ | | - | variant or associated item not found in `empty_struct::XE` + | variant or associated item not found in `XE` | help: there is a variant with a similar name: `XEmpty3` error[E0599]: no variant named `Empty1` found for enum `empty_struct::XE` diff --git a/src/test/ui/functions-closures/fn-help-with-err.stderr b/src/test/ui/functions-closures/fn-help-with-err.stderr index 2296666219eef..463ac7684ecdf 100644 --- a/src/test/ui/functions-closures/fn-help-with-err.stderr +++ b/src/test/ui/functions-closures/fn-help-with-err.stderr @@ -17,11 +17,11 @@ note: `Bar` defines an item `bar`, perhaps you need to implement it LL | trait Bar { | ^^^^^^^^^ -error[E0599]: no method named `bar` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:22:36: 22:38]>` in the current scope +error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:22:36]>` in the current scope --> $DIR/fn-help-with-err.rs:23:10 | LL | arc2.bar(); - | ^^^ method not found in `Arc<[closure@$DIR/fn-help-with-err.rs:22:36: 22:38]>` + | ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:22:36]>` | = help: items from traits can only be used if the trait is implemented and in scope note: `Bar` defines an item `bar`, perhaps you need to implement it diff --git a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr index d1d76916b2639..0458d2535f2f5 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr @@ -1,4 +1,4 @@ -error[E0599]: the method `filterx` exists for struct `Map`, but its trait bounds were not satisfied +error[E0599]: the method `filterx` exists for struct `Map`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:118:22 | LL | pub struct Map { @@ -8,7 +8,7 @@ LL | pub struct Map { | doesn't satisfy `_: StreamExt` ... LL | let filter = map.filterx(|x: &_| true); - | ^^^^^^^ method cannot be called due to unsatisfied trait bounds + | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: `&'a mut &Map: Stream` @@ -19,7 +19,7 @@ note: the following trait bounds were not satisfied: LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} | --------- - ^^^^^^ unsatisfied trait bound introduced here -error[E0599]: the method `countx` exists for struct `Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>`, but its trait bounds were not satisfied +error[E0599]: the method `countx` exists for struct `Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@issue-30786.rs:129:30]>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:130:24 | LL | pub struct Filter { diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index 3d4ae11e57670..548c89d0a3871 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -145,11 +145,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it LL | pub trait Bar { | ^^^^^^^^^^^^^ -error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope +error[E0599]: no method named `method2` found for struct `Foo` in the current scope --> $DIR/no-method-suggested-traits.rs:50:37 | LL | no_method_suggested_traits::Foo.method2(); - | ^^^^^^^ method not found in `no_method_suggested_traits::Foo` + | ^^^^^^^ method not found in `Foo` | = help: items from traits can only be used if the trait is implemented and in scope note: `foo::Bar` defines an item `method2`, perhaps you need to implement it @@ -158,11 +158,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it LL | pub trait Bar { | ^^^^^^^^^^^^^ -error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope +error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Foo>>` in the current scope --> $DIR/no-method-suggested-traits.rs:52:71 | LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); - | ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>` + | ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>` | = help: items from traits can only be used if the trait is implemented and in scope note: `foo::Bar` defines an item `method2`, perhaps you need to implement it @@ -171,11 +171,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it LL | pub trait Bar { | ^^^^^^^^^^^^^ -error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope +error[E0599]: no method named `method2` found for enum `Bar` in the current scope --> $DIR/no-method-suggested-traits.rs:54:40 | LL | no_method_suggested_traits::Bar::X.method2(); - | ^^^^^^^ method not found in `no_method_suggested_traits::Bar` + | ^^^^^^^ method not found in `Bar` | = help: items from traits can only be used if the trait is implemented and in scope note: `foo::Bar` defines an item `method2`, perhaps you need to implement it @@ -184,11 +184,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it LL | pub trait Bar { | ^^^^^^^^^^^^^ -error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope +error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Bar>>` in the current scope --> $DIR/no-method-suggested-traits.rs:56:74 | LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); - | ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>` + | ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>` | = help: items from traits can only be used if the trait is implemented and in scope note: `foo::Bar` defines an item `method2`, perhaps you need to implement it @@ -255,29 +255,29 @@ error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&usize>>` LL | std::rc::Rc::new(&mut Box::new(&1_usize)).method3(); | ^^^^^^^ method not found in `Rc<&mut Box<&usize>>` -error[E0599]: no method named `method3` found for struct `no_method_suggested_traits::Foo` in the current scope +error[E0599]: no method named `method3` found for struct `Foo` in the current scope --> $DIR/no-method-suggested-traits.rs:71:37 | LL | no_method_suggested_traits::Foo.method3(); - | ^^^^^^^ method not found in `no_method_suggested_traits::Foo` + | ^^^^^^^ method not found in `Foo` -error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope +error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Foo>>` in the current scope --> $DIR/no-method-suggested-traits.rs:72:71 | LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3(); - | ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>` + | ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>` -error[E0599]: no method named `method3` found for enum `no_method_suggested_traits::Bar` in the current scope +error[E0599]: no method named `method3` found for enum `Bar` in the current scope --> $DIR/no-method-suggested-traits.rs:74:40 | LL | no_method_suggested_traits::Bar::X.method3(); - | ^^^^^^^ method not found in `no_method_suggested_traits::Bar` + | ^^^^^^^ method not found in `Bar` -error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope +error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Bar>>` in the current scope --> $DIR/no-method-suggested-traits.rs:75:74 | LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3(); - | ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>` + | ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>` error: aborting due to 24 previous errors diff --git a/src/test/ui/issues/issue-30123.stderr b/src/test/ui/issues/issue-30123.stderr index e9d934332f171..7808cbf8aa108 100644 --- a/src/test/ui/issues/issue-30123.stderr +++ b/src/test/ui/issues/issue-30123.stderr @@ -1,8 +1,8 @@ -error[E0599]: no function or associated item named `new_undirected` found for struct `issue_30123_aux::Graph` in the current scope +error[E0599]: no function or associated item named `new_undirected` found for struct `Graph` in the current scope --> $DIR/issue-30123.rs:7:33 | LL | let ug = Graph::::new_undirected(); - | ^^^^^^^^^^^^^^ function or associated item not found in `issue_30123_aux::Graph` + | ^^^^^^^^^^^^^^ function or associated item not found in `Graph` | = note: the function or associated item was found for - `issue_30123_aux::Graph` diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 5b51c2e32bf7d..f3be99f9bcb4b 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -21,7 +21,7 @@ LL | | }) note: required by a bound in `cloned` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -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 +error[E0599]: the method `collect` exists for struct `Cloned, [closure@issue-31173.rs:7:21]>>`, but its trait bounds were not satisfied --> $DIR/issue-31173.rs:12:10 | LL | .collect(); diff --git a/src/test/ui/issues/issue-41880.stderr b/src/test/ui/issues/issue-41880.stderr index fd694df30457e..00c375f8d2acf 100644 --- a/src/test/ui/issues/issue-41880.stderr +++ b/src/test/ui/issues/issue-41880.stderr @@ -5,7 +5,7 @@ LL | pub struct Iterate { | ------------------------ method `iter` not found for this struct ... LL | println!("{:?}", a.iter().take(10).collect::>()); - | ^^^^ method not found in `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:27]>` + | ^^^^ method not found in `Iterate<{integer}, [closure@issue-41880.rs:26:24]>` error: aborting due to previous error diff --git a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr index fc42d1a4dcd08..8846efba871b9 100644 --- a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr +++ b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr @@ -23,7 +23,7 @@ error[E0599]: no method named `extend` found for struct `Map` in the current sco --> $DIR/method-not-found-generic-arg-elision.rs:87:29 | LL | v.iter().map(|x| x * x).extend(std::iter::once(100)); - | ^^^^^^ method not found in `Map, [closure@$DIR/method-not-found-generic-arg-elision.rs:87:18: 87:21]>` + | ^^^^^^ method not found in `Map, [closure@method-not-found-generic-arg-elision.rs:87:18]>` error[E0599]: no method named `method` found for struct `Wrapper` in the current scope --> $DIR/method-not-found-generic-arg-elision.rs:90:13 diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 3151bc76891e4..72fb0e4d77431 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -13,7 +13,7 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); note: required by a bound in `filter` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error[E0599]: the method `count` exists for struct `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>`, but its trait bounds were not satisfied +error[E0599]: the method `count` exists for struct `Filter>, [closure@issue-36053-2.rs:7:39]>`, but its trait bounds were not satisfied --> $DIR/issue-36053-2.rs:7:55 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 2cb53ecce1040..6910b77d9bc3f 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -20,11 +20,11 @@ LL | let fp = BufWriter::new(fp); note: required by a bound in `BufWriter` --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL -error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn std::io::Write>`, but its trait bounds were not satisfied +error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, but its trait bounds were not satisfied --> $DIR/mut-borrow-needed-by-trait.rs:21:5 | LL | writeln!(fp, "hello world").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn std::io::Write>` due to unsatisfied trait bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL | = note: doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write` diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr index e5ca0edd7a91c..99ec517834003 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr @@ -1,8 +1,8 @@ -error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]` in the current scope +error[E0599]: no method named `call` found for closure `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]` in the current scope --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10 | LL | mut_.call((0, )); - | ^^^^ method not found in `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]` + | ^^^^ method not found in `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]` error: aborting due to previous error From 2492235c323e012ed49d93391754a59ce715ebc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Dec 2022 18:00:24 -0800 Subject: [PATCH 5/5] Consider lifetimes when comparing assoc types in method chain Do not say "Type changed to X here" when the only difference is caused by lifetimes. --- .../src/traits/error_reporting/suggestions.rs | 2 +- .../ui/iterators/invalid-iterator-chain.rs | 12 +++++ .../iterators/invalid-iterator-chain.stderr | 44 +++++++++++++------ 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index b18f675e562f6..e77b9da08f51a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3333,7 +3333,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { 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 self.can_eq(param_env, ty, *prev_ty).is_err() { 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() diff --git a/src/test/ui/iterators/invalid-iterator-chain.rs b/src/test/ui/iterators/invalid-iterator-chain.rs index 87116e4924570..ebdf33303c982 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.rs +++ b/src/test/ui/iterators/invalid-iterator-chain.rs @@ -1,3 +1,11 @@ +use std::collections::hash_set::Iter; +use std::collections::HashSet; + +fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec { + let i = i.map(|x| x.clone()); + i.collect() //~ ERROR E0277 +} + fn main() { let scores = vec![(0, 0)] .iter() @@ -38,4 +46,8 @@ fn main() { }); let f = e.filter(|_| false); let g: Vec = f.collect(); //~ ERROR E0277 + + let mut s = HashSet::new(); + s.insert(1u8); + println!("{:?}", iter_to_vec(s.iter())); } diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index 84bac7833f67b..d76a4bfb7b3ea 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -1,5 +1,23 @@ +error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `&X` + --> $DIR/invalid-iterator-chain.rs:6:7 + | +LL | i.collect() + | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<&X>` 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:4:26 + | +LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec { + | ^^^^^^^^^^^ `Iterator::Item` is `&X` here +LL | let i = i.map(|x| x.clone()); + | ------------------ `Iterator::Item` remains `&X` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` - --> $DIR/invalid-iterator-chain.rs:7:27 + --> $DIR/invalid-iterator-chain.rs:15:27 | LL | println!("{}", scores.sum::()); | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` @@ -9,7 +27,7 @@ LL | println!("{}", scores.sum::()); > note: the method call chain might not have had the expected associated types - --> $DIR/invalid-iterator-chain.rs:4:10 + --> $DIR/invalid-iterator-chain.rs:12:10 | LL | let scores = vec![(0, 0)] | ------------ this expression has type `Vec<({integer}, {integer})>` @@ -24,7 +42,7 @@ note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` - --> $DIR/invalid-iterator-chain.rs:18:14 + --> $DIR/invalid-iterator-chain.rs:26:14 | LL | .sum::(), | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` @@ -34,7 +52,7 @@ LL | .sum::(), > note: the method call chain might not have had the expected associated types - --> $DIR/invalid-iterator-chain.rs:12:14 + --> $DIR/invalid-iterator-chain.rs:20:14 | LL | vec![0, 1] | ---------- this expression has type `Vec<{integer}>` @@ -56,7 +74,7 @@ note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64` - --> $DIR/invalid-iterator-chain.rs:28:14 + --> $DIR/invalid-iterator-chain.rs:36:14 | LL | .sum::(), | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` @@ -66,7 +84,7 @@ LL | .sum::(), > note: the method call chain might not have had the expected associated types - --> $DIR/invalid-iterator-chain.rs:24:14 + --> $DIR/invalid-iterator-chain.rs:32:14 | LL | vec![0, 1] | ---------- this expression has type `Vec<{integer}>` @@ -84,7 +102,7 @@ note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` - --> $DIR/invalid-iterator-chain.rs:30:54 + --> $DIR/invalid-iterator-chain.rs:38:54 | LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` @@ -94,7 +112,7 @@ 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:30:38 + --> $DIR/invalid-iterator-chain.rs:38:38 | LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); | ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here @@ -105,7 +123,7 @@ note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()` - --> $DIR/invalid-iterator-chain.rs:31:40 + --> $DIR/invalid-iterator-chain.rs:39:40 | LL | println!("{}", vec![(), ()].iter().sum::()); | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` @@ -115,7 +133,7 @@ LL | println!("{}", vec![(), ()].iter().sum::()); > note: the method call chain might not have had the expected associated types - --> $DIR/invalid-iterator-chain.rs:31:33 + --> $DIR/invalid-iterator-chain.rs:39:33 | LL | println!("{}", vec![(), ()].iter().sum::()); | ------------ ^^^^^^ `Iterator::Item` is `&()` here @@ -125,7 +143,7 @@ note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `()` - --> $DIR/invalid-iterator-chain.rs:40:25 + --> $DIR/invalid-iterator-chain.rs:48:25 | LL | let g: Vec = f.collect(); | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` @@ -133,7 +151,7 @@ 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:36:15 + --> $DIR/invalid-iterator-chain.rs:44:15 | LL | let a = vec![0]; | ------- this expression has type `Vec<{integer}>` @@ -153,6 +171,6 @@ LL | let f = e.filter(|_| false); note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0277`.