From 7cd4b673d050508544f0b200ab6a840bebc38f0f Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 25 Nov 2022 13:19:21 +0800 Subject: [PATCH 01/20] fix #104700, account for item-local in inner scope for E0425 --- compiler/rustc_resolve/src/late.rs | 6 +++++- .../rustc_resolve/src/late/diagnostics.rs | 16 ++++++++++++++ .../ui/resolve/issue-104700-inner_scope.rs | 11 ++++++++++ .../resolve/issue-104700-inner_scope.stderr | 21 +++++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/resolve/issue-104700-inner_scope.rs create mode 100644 src/test/ui/resolve/issue-104700-inner_scope.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 93b0f5814de..8faef4c6374 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -566,6 +566,9 @@ struct LateResolutionVisitor<'a, 'b, 'ast> { /// FIXME #4948: Reuse ribs to avoid allocation. ribs: PerNS>>, + /// Previous poped `rib`, only used for diagnostic. + last_block_rib: Option>, + /// The current set of local scopes, for labels. label_ribs: Vec>, @@ -1168,6 +1171,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { type_ns: vec![Rib::new(start_rib_kind)], macro_ns: vec![Rib::new(start_rib_kind)], }, + last_block_rib: None, label_ribs: Vec::new(), lifetime_ribs: Vec::new(), lifetime_elision_candidates: None, @@ -3756,7 +3760,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.ribs[ValueNS].pop(); self.label_ribs.pop(); } - self.ribs[ValueNS].pop(); + self.last_block_rib = self.ribs[ValueNS].pop(); if anonymous_module.is_some() { self.ribs[TypeNS].pop(); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b340bee28c3..b3dd5bb28a7 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -614,6 +614,22 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { return (true, candidates); } } + + // Try to find in last block rib + if let Some(rib) = &self.last_block_rib { + for (ident, &res) in &rib.bindings { + if let Res::Local(_) = res && path.len() == 1 && + ident.span.eq_ctxt(path[0].ident.span) && + ident.name == path[0].ident.name { + err.span_help( + ident.span, + &format!("the binding `{}` is available in a different scope in the same function", path_str), + ); + return (true, candidates); + } + } + } + return (false, candidates); } diff --git a/src/test/ui/resolve/issue-104700-inner_scope.rs b/src/test/ui/resolve/issue-104700-inner_scope.rs new file mode 100644 index 00000000000..e8f28c113e3 --- /dev/null +++ b/src/test/ui/resolve/issue-104700-inner_scope.rs @@ -0,0 +1,11 @@ +fn main() { + let foo = 1; + { + let bar = 2; + let test_func = |x| x > 3; + } + if bar == 2 { //~ ERROR cannot find value + println!("yes"); + } + test_func(1); //~ ERROR cannot find function +} diff --git a/src/test/ui/resolve/issue-104700-inner_scope.stderr b/src/test/ui/resolve/issue-104700-inner_scope.stderr new file mode 100644 index 00000000000..051b234fc72 --- /dev/null +++ b/src/test/ui/resolve/issue-104700-inner_scope.stderr @@ -0,0 +1,21 @@ +error[E0425]: cannot find value `bar` in this scope + --> $DIR/issue-104700-inner_scope.rs:7:8 + | +LL | if bar == 2 { + | ^^^ + | +help: the binding `bar` is available in a different scope in the same function + --> $DIR/issue-104700-inner_scope.rs:4:13 + | +LL | let bar = 2; + | ^^^ + +error[E0425]: cannot find function `test_func` in this scope + --> $DIR/issue-104700-inner_scope.rs:10:5 + | +LL | test_func(1); + | ^^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. From 68ea51602a492a02ed5d23580ac06f9c4cc830f5 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 25 Nov 2022 15:25:04 +0800 Subject: [PATCH 02/20] fix the crossing function issue --- compiler/rustc_resolve/src/late.rs | 2 ++ compiler/rustc_resolve/src/late/diagnostics.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 8faef4c6374..18dabfe8993 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -876,6 +876,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // Ignore errors in function bodies if this is rustdoc // Be sure not to set this until the function signature has been resolved. let previous_state = replace(&mut this.in_func_body, true); + // We only care block in the same function + this.last_block_rib = None; // Resolve the function body, potentially inside the body of an async closure this.with_lifetime_rib( LifetimeRibKind::Elided(LifetimeRes::Infer), diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b3dd5bb28a7..d82aecaadc3 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -616,7 +616,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } // Try to find in last block rib - if let Some(rib) = &self.last_block_rib { + if let Some(rib) = &self.last_block_rib && let RibKind::NormalRibKind = rib.kind { for (ident, &res) in &rib.bindings { if let Res::Local(_) = res && path.len() == 1 && ident.span.eq_ctxt(path[0].ident.span) && From bc60d50eaa045f6c17b1c127e486d0e3232f1e89 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Dec 2022 17:34:24 +0000 Subject: [PATCH 03/20] 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 dda7b2b2fa5..78364253adb 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 9f5814a6bda..8bfa405cbea 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 3188cd80cca..5e84dcdef30 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 ce38c3320bb..5ee287b1b15 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 00000000000..de174807ab6 --- /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 00000000000..03298089d88 --- /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 04/20] 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 de174807ab6..3d4801b3732 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 03298089d88..0b3e0653864 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 05/20] 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 8bfa405cbea..2f9b8c21071 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 5e84dcdef30..eca961633dc 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 5ee287b1b15..7f97b5bfcbe 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 0b3e0653864..57be01a2442 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 06/20] 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 2f9b8c21071..87ab863fa7b 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 eca961633dc..89f5c45d7a9 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 7f97b5bfcbe..7fe786dcfb5 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 3d4801b3732..e17b471b692 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 57be01a2442..8bf7eb93a72 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 07/20] 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 87ab863fa7b..bef2a067ae3 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 89f5c45d7a9..ac3b3e95faf 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 7fe786dcfb5..9a560c631fe 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 8bf7eb93a72..0505dd86af3 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 08/20] 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 bef2a067ae3..1d6e749b9e3 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 0505dd86af3..14e430726f6 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 09/20] 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 1d6e749b9e3..cfd7c20767f 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 ac3b3e95faf..688a532adc6 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 e17b471b692..32141bf0fb8 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 14e430726f6..55788ae80e6 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 10/20] 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 55788ae80e6..833a5a7474a 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 c3103671178..6405be01e67 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 11/20] 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 cfd7c20767f..adc64463b3b 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 759d79493a9..c7ed8e0de38 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 688a532adc6..a86da627b7e 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 9a560c631fe..7dd135d91fb 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 833a5a7474a..f8464c7ce76 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 6dc039fc35d..2db1cc4b776 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 6405be01e67..c99f06da7a4 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 12/20] 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 | 30 ++++------- 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 | 51 +++++-------------- .../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, 93 insertions(+), 161 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 06bb5edc090..6bc0c261565 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 adc64463b3b..162e73faa2a 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 b4e94cb83f7..422ac548427 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 3f9b3be9851..d70bf6e1d92 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 04efa27189b..f678df5b42b 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 58d9b564427..62d841f3789 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 +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 | 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 +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 c28986a2985..73a9b786fe2 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 a86da627b7e..b610e5c1366 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 7dd135d91fb..c6352978613 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 4c424999b75..99d0d9bd735 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 544b1da178a..7a07fed1fae 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 09832c260d0..5a8aacb1a6d 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 65ef124a463..58da222e039 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 32141bf0fb8..87116e49245 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 f8464c7ce76..49651b20fb1 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 + --> $DIR/invalid-iterator-chain.rs:18:14 | -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 +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 + --> $DIR/invalid-iterator-chain.rs:28:14 | -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 +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 5a46027dd52..c66069c4d25 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 a4b4968b7d2..a92c3a6809e 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 36748fae13c..c2515c40b1d 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 f61ee661bb7..37d94cf0ebd 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 c99f06da7a4..70706541ad6 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 c64930db9be..f9d0d1f7875 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 925ae53e324..633b7cc255a 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 11db0c2b8f2..9e97d3f1137 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 c2c16921c2e..21ecddaffbb 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 b52eb2c0332..13fc719f28c 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 b52eb2c0332..13fc719f28c 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 684db23e135..a5e6f5b5ffc 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 146d38d076a..9062a0fab63 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 50060e53a49..d7b95f55769 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 ee40a67cd9283a9e8b0de87926581456252c6c9f Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Tue, 13 Dec 2022 02:06:24 +0900 Subject: [PATCH 13/20] remove unnecessary uses of `clone` --- compiler/rustc_ast/src/token.rs | 2 +- compiler/rustc_ast_passes/src/feature_gate.rs | 2 +- compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs | 2 +- compiler/rustc_builtin_macros/src/alloc_error_handler.rs | 2 +- compiler/rustc_builtin_macros/src/concat_bytes.rs | 2 +- compiler/rustc_codegen_llvm/src/back/lto.rs | 2 +- .../error_reporting/nice_region_error/static_impl_trait.rs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index c0cc4e79a3d..7b8c0d79a17 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -114,7 +114,7 @@ impl Lit { if let NtExpr(expr) | NtLiteral(expr) = &**nt && let ast::ExprKind::Lit(token_lit) = expr.kind => { - Some(token_lit.clone()) + Some(token_lit) } _ => None, } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 32f45f8b59e..039338f543c 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -630,7 +630,7 @@ fn check_incompatible_features(sess: &Session) { { let spans = vec![f1_span, f2_span]; sess.struct_span_err( - spans.clone(), + spans, &format!( "features `{}` and `{}` are incompatible, using them at the same time \ is not allowed", diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 5e3745f1735..5fb4dcf09f5 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -745,7 +745,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_suggestion_verbose( span.shrink_to_hi(), "consider cloning the value if the performance cost is acceptable", - ".clone()".to_string(), + ".clone()", Applicability::MachineApplicable, ); } diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index 95e38e4b053..dcf500ddbd3 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -32,7 +32,7 @@ pub fn expand( (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span)) } else { ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "alloc_error_handler must be a function"); - return vec![orig_item.clone()]; + return vec![orig_item]; }; // Generate a bunch of new items using the AllocFnFactory diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index 70ce5a6c419..392bd93ff84 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -196,7 +196,7 @@ pub fn expand_concat_bytes( } } if !missing_literals.is_empty() { - let mut err = cx.struct_span_err(missing_literals.clone(), "expected a byte literal"); + let mut err = cx.struct_span_err(missing_literals, "expected a byte literal"); err.note("only byte literals (like `b\"foo\"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`"); err.emit(); return base::MacEager::expr(DummyResult::raw_expr(sp, true)); diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 3fa21355b7f..b5e0736774f 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -206,7 +206,7 @@ pub(crate) fn run_thin( } pub(crate) fn prepare_thin(module: ModuleCodegen) -> (String, ThinBuffer) { - let name = module.name.clone(); + let name = module.name; let buffer = ThinBuffer::new(module.module_llvm.llmod(), true); (name, buffer) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 09f9aa3c842..9bd2202d260 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -330,7 +330,7 @@ pub fn suggest_new_region_bound( Applicability::MaybeIncorrect, ); } - if let Some((param_span, param_ty)) = param.clone() { + if let Some((param_span, ref param_ty)) = param { err.span_suggestion_verbose( param_span, add_static_bound, 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 14/20] 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 00000000000..cb373d65772 --- /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 78364253adb..a0ed1fc751b 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 162e73faa2a..df470f62089 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 2ea368e53c755fb13d3ad5cd59370a3f7ad4e8c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 12 Dec 2022 19:49:53 +0100 Subject: [PATCH 15/20] minor code cleanups --- compiler/rustc_abi/src/lib.rs | 9 +++------ compiler/rustc_data_structures/src/base_n.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 2 +- compiler/rustc_errors/src/emitter.rs | 4 ++-- compiler/rustc_hir/src/hir.rs | 7 +------ compiler/rustc_index/src/bit_set.rs | 2 +- compiler/rustc_lexer/src/unescape.rs | 3 +-- compiler/rustc_span/src/source_map.rs | 2 +- 8 files changed, 11 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 4ca59144b29..8c71332bfab 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -802,12 +802,9 @@ impl Integer { pub fn for_align(cx: &C, wanted: Align) -> Option { let dl = cx.data_layout(); - for candidate in [I8, I16, I32, I64, I128] { - if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() { - return Some(candidate); - } - } - None + [I8, I16, I32, I64, I128].into_iter().find(|&candidate| { + wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() + }) } /// Find the largest integer with the given alignment or less. diff --git a/compiler/rustc_data_structures/src/base_n.rs b/compiler/rustc_data_structures/src/base_n.rs index 3c7bea27124..4567759c004 100644 --- a/compiler/rustc_data_structures/src/base_n.rs +++ b/compiler/rustc_data_structures/src/base_n.rs @@ -9,7 +9,7 @@ pub const MAX_BASE: usize = 64; pub const ALPHANUMERIC_ONLY: usize = 62; pub const CASE_INSENSITIVE: usize = 36; -const BASE_64: &[u8; MAX_BASE as usize] = +const BASE_64: &[u8; MAX_BASE] = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$"; #[inline] diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 06bb5edc090..0f79bc558bf 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -802,7 +802,7 @@ impl Diagnostic { debug_assert!( !(suggestions .iter() - .flat_map(|suggs| suggs) + .flatten() .any(|(sp, suggestion)| sp.is_empty() && suggestion.is_empty())), "Span must not be empty and have no suggestion" ); diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 4df2198fb0e..aaf0699f0dc 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1308,7 +1308,7 @@ impl EmitterWriter { // see how it *looks* with // very *weird* formats // see? - for &(ref text, ref style) in msg.iter() { + for (text, style) in msg.iter() { let text = self.translate_message(text, args); let lines = text.split('\n').collect::>(); if lines.len() > 1 { @@ -1370,7 +1370,7 @@ impl EmitterWriter { buffer.append(0, ": ", header_style); label_width += 2; } - for &(ref text, _) in msg.iter() { + for (text, _) in msg.iter() { let text = self.translate_message(text, args); // Account for newlines to align output to its label. for (line, text) in normalize_whitespace(&text).lines().enumerate() { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 8bc022e1e17..91825c29258 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -548,12 +548,7 @@ impl<'hir> Generics<'hir> { } pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'hir>> { - for param in self.params { - if name == param.name.ident().name { - return Some(param); - } - } - None + self.params.iter().find(|¶m| name == param.name.ident().name) } pub fn spans(&self) -> MultiSpan { diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 777112442f0..686cb6dac49 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -209,7 +209,7 @@ impl BitSet { self.words[start_word_index] |= !(start_mask - 1); // And all trailing bits (i.e. from 0..=end) in the end word, // including the end. - self.words[end_word_index] |= end_mask | end_mask - 1; + self.words[end_word_index] |= end_mask | (end_mask - 1); } else { self.words[start_word_index] |= end_mask | (end_mask - start_mask); } diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index e405013dcab..87c44638a8d 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -204,14 +204,13 @@ fn scan_escape(chars: &mut Chars<'_>, is_byte: bool) -> Result { - let digit = + let digit: u32 = c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?; n_digits += 1; if n_digits > 6 { // Stop updating value since we're sure that it's incorrect already. continue; } - let digit = digit as u32; value = value * 16 + digit; } }; diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 43a31722707..a4e0f54d276 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -1150,7 +1150,7 @@ impl FilePathMapping { // NOTE: We are iterating over the mapping entries from last to first // because entries specified later on the command line should // take precedence. - for &(ref from, ref to) in mapping.iter().rev() { + for (from, to) in mapping.iter().rev() { debug!("Trying to apply {from:?} => {to:?}"); if let Ok(rest) = path.strip_prefix(from) { From 7e64cebf97df021b7ece9df435e748652e0b2e83 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 12 Dec 2022 12:46:11 -0700 Subject: [PATCH 16/20] rustdoc: stop treating everything in a trait item as a method This was added in 0b9b4b70683db6ef707755f520f139eb7b92a944 to fix the spacing on trait pages, but stopped being needed because 791f04e5a47ee78951552c7ed1545b2b01a44c74 stopped styling method-toggle. By only putting the method-toggle class on actual methods, the JS setting does the right thing. --- src/librustdoc/formats/item_type.rs | 3 +++ src/librustdoc/html/render/mod.rs | 3 +-- src/librustdoc/html/render/print_item.rs | 3 ++- src/test/rustdoc/toggle-trait-fn.rs | 7 +++++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index f21e60a64e0..2f1f4cbf359 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -177,6 +177,9 @@ impl ItemType { ItemType::TraitAlias => "traitalias", } } + pub(crate) fn is_method(&self) -> bool { + matches!(*self, ItemType::Method | ItemType::TyMethod) + } } impl fmt::Display for ItemType { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 36d15ec3b86..80fbe9c1f06 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1512,8 +1512,7 @@ fn render_impl( let toggled = !doc_buffer.is_empty(); if toggled { - let method_toggle_class = - if item_type == ItemType::Method { " method-toggle" } else { "" }; + let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; write!(w, "
", method_toggle_class); } match &*item.kind { diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index acbe3f22889..a7b57c373e3 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -732,7 +732,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: document(&mut content, cx, m, Some(t), HeadingOffset::H5); let toggled = !content.is_empty(); if toggled { - write!(w, "
"); + let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; + write!(w, "
"); } write!(w, "
", id); render_rightside(w, cx, m, t, RenderMode::Normal); diff --git a/src/test/rustdoc/toggle-trait-fn.rs b/src/test/rustdoc/toggle-trait-fn.rs index e41422ce7c5..0a1f088b9ab 100644 --- a/src/test/rustdoc/toggle-trait-fn.rs +++ b/src/test/rustdoc/toggle-trait-fn.rs @@ -4,6 +4,8 @@ // summary. Trait methods with no documentation should not be wrapped. // // @has foo/trait.Foo.html +// @has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item' +// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item2' // @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()' // @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()' // @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented' @@ -11,6 +13,11 @@ // @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()' // @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented' pub trait Foo { + /// is documented + type Item; + + type Item2; + fn not_documented(); /// is_documented is documented 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 17/20] 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 df470f62089..40c81025471 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; } } From 21a2b642090d96cb486a55748d18d6917f0e2d11 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Dec 2022 22:49:19 +0100 Subject: [PATCH 18/20] Add check for local-storage value when changing "display line numbers" settings --- src/test/rustdoc-gui/docblock-code-block-line-number.goml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml index fec21ad35c3..b094c483876 100644 --- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml +++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml @@ -33,7 +33,9 @@ assert-css: ("#settings", {"display": "block"}) click: "input#line-numbers" wait-for: 100 // wait-for-false does not exist assert-false: "pre.example-line-numbers" +assert-local-storage: {"rustdoc-line-numbers": "false" } // Finally, turn it on again. click: "input#line-numbers" wait-for: "pre.example-line-numbers" +assert-local-storage: {"rustdoc-line-numbers": "true" } From 46b4a3b83148192fa4dc50bf1a751357ec7393aa Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 12 Dec 2022 15:17:49 -0700 Subject: [PATCH 19/20] rustdoc: remove `type="text/css" from stylesheet links MDN directly recommends this in , since "CSS is the only stylesheet language used on the web." Like 07a243b2a46384235d7e2c08688978b7cf018973, but a few places that were missed the first time. --- src/librustdoc/html/render/context.rs | 2 +- src/librustdoc/html/static/js/main.js | 1 - src/librustdoc/markdown.rs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 73690c86f4f..d4d3e4f6ea7 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -637,7 +637,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { You need to enable Javascript be able to update your settings.\
\ \ - \ ", static_root_path = page.get_static_root_path(), diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 152116089c7..3f97e4e2e39 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -184,7 +184,6 @@ function browserSupportsHistoryApi() { function loadCss(cssUrl) { const link = document.createElement("link"); link.href = cssUrl; - link.type = "text/css"; link.rel = "stylesheet"; document.getElementsByTagName("head")[0].appendChild(link); } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 044e051440c..5f4ad6d2aea 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -53,7 +53,7 @@ pub(crate) fn render>( let mut css = String::new(); for name in &options.markdown_css { - write!(css, r#""#) + write!(css, r#""#) .expect("Writing to a String can't fail"); } From 4ac81902870aa1e37728fe7e1b0e7204ac718436 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 31 Oct 2022 20:52:55 -0400 Subject: [PATCH 20/20] Adjust miri to still be optional We don't distribute a miri build for beta/stable so it needs to be kept optional. In the future it likely makes sense to switch the miri *artifacts* to always be built, but the rustup component to not be included -- this will avoid some of this pain. --- src/bootstrap/dist.rs | 56 ++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 2fef7f65827..3cb0eccd324 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1470,7 +1470,7 @@ impl Step for Extended { let xform = |p: &Path| { let mut contents = t!(fs::read_to_string(p)); - for tool in &["rust-demangler"] { + for tool in &["rust-demangler", "miri"] { if !built_tools.contains(tool) { contents = filter(&contents, tool); } @@ -1510,9 +1510,8 @@ impl Step for Extended { prepare("rust-std"); prepare("rust-analysis"); prepare("clippy"); - prepare("miri"); prepare("rust-analyzer"); - for tool in &["rust-docs", "rust-demangler"] { + for tool in &["rust-docs", "rust-demangler", "miri"] { if built_tools.contains(tool) { prepare(tool); } @@ -1571,9 +1570,8 @@ impl Step for Extended { prepare("rust-docs"); prepare("rust-std"); prepare("clippy"); - prepare("miri"); prepare("rust-analyzer"); - for tool in &["rust-demangler"] { + for tool in &["rust-demangler", "miri"] { if built_tools.contains(tool) { prepare(tool); } @@ -1710,23 +1708,25 @@ impl Step for Extended { .arg(etc.join("msi/remove-duplicates.xsl")), ); } - builder.run( - Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("miri") - .args(&heat_flags) - .arg("-cg") - .arg("MiriGroup") - .arg("-dr") - .arg("Miri") - .arg("-var") - .arg("var.MiriDir") - .arg("-out") - .arg(exe.join("MiriGroup.wxs")) - .arg("-t") - .arg(etc.join("msi/remove-duplicates.xsl")), - ); + if built_tools.contains("miri") { + builder.run( + Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("miri") + .args(&heat_flags) + .arg("-cg") + .arg("MiriGroup") + .arg("-dr") + .arg("Miri") + .arg("-var") + .arg("var.MiriDir") + .arg("-out") + .arg(exe.join("MiriGroup.wxs")) + .arg("-t") + .arg(etc.join("msi/remove-duplicates.xsl")), + ); + } builder.run( Command::new(&heat) .current_dir(&exe) @@ -1774,7 +1774,6 @@ impl Step for Extended { .arg("-dStdDir=rust-std") .arg("-dAnalysisDir=rust-analysis") .arg("-dClippyDir=clippy") - .arg("-dMiriDir=miri") .arg("-arch") .arg(&arch) .arg("-out") @@ -1788,6 +1787,9 @@ impl Step for Extended { if built_tools.contains("rust-analyzer") { cmd.arg("-dRustAnalyzerDir=rust-analyzer"); } + if built_tools.contains("miri") { + cmd.arg("-dMiriDir=miri"); + } if target.ends_with("windows-gnu") { cmd.arg("-dGccDir=rust-mingw"); } @@ -1801,7 +1803,9 @@ impl Step for Extended { candle("CargoGroup.wxs".as_ref()); candle("StdGroup.wxs".as_ref()); candle("ClippyGroup.wxs".as_ref()); - candle("MiriGroup.wxs".as_ref()); + if built_tools.contains("miri") { + candle("MiriGroup.wxs".as_ref()); + } if built_tools.contains("rust-demangler") { candle("RustDemanglerGroup.wxs".as_ref()); } @@ -1837,9 +1841,11 @@ impl Step for Extended { .arg("StdGroup.wixobj") .arg("AnalysisGroup.wixobj") .arg("ClippyGroup.wixobj") - .arg("MiriGroup.wixobj") .current_dir(&exe); + if built_tools.contains("miri") { + cmd.arg("MiriGroup.wixobj"); + } if built_tools.contains("rust-analyzer") { cmd.arg("RustAnalyzerGroup.wixobj"); }