about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2022-12-06 12:08:17 -0800
committerEsteban Küber <esteban@kuber.com.ar>2022-12-11 09:46:01 -0800
commit64bc975d27f86aaa1d3d94921c9c042477b4e88b (patch)
tree4a42afa0108c4c4bbf804ec224f125fe382e352f
parent49d5bef5867012a3ec39a04c81694b64b22f0067 (diff)
downloadrust-64bc975d27f86aaa1d3d94921c9c042477b4e88b.tar.gz
rust-64bc975d27f86aaa1d3d94921c9c042477b4e88b.zip
Mention only assoc types changes
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs96
-rw-r--r--src/test/ui/issues/issue-34334.stderr6
-rw-r--r--src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr4
-rw-r--r--src/test/ui/iterators/invalid-iterator-chain.stderr38
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<i32>()
                             //               ^^^^^^ ^^^^^^^^^^^
                             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 {
                                     // `<ExprTy as Iterator>` 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<i32>()
                             // ^^^^^^^^^^^^^
-                            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<T>` is implemented for `Vec<T>`
-note: the expression is of type `Map<std::slice::Iter<'_, (_, _, _)>, [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<f64> = x1.into_iter().collect();
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
-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<f64> = x1.into_iter().collect();
@@ -31,7 +31,7 @@ LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
-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::<Vec<f64>>();
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::<i32>());
    = help: the following other types implement trait `Sum<A>`:
              <i32 as Sum<&'a i32>>
              <i32 as Sum>
-note: the expression is of type `Map<std::slice::Iter<'_, ({integer}, {integer})>, [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::<i32>());
-   |                      ^^^^^^
+   | |__________^ 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::<i32>(),
    = help: the following other types implement trait `Sum<A>`:
              <i32 as Sum<&'a i32>>
              <i32 as Sum>
-note: the expression is of type `Map<Map<Filter<Map<Map<Map<std::slice::Iter<'_, {integer}>, [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::<i32>());
    = help: the following other types implement trait `Sum<A>`:
              <i32 as Sum<&'a i32>>
              <i32 as Sum>
-note: the expression is of type `Map<std::slice::Iter<'_, {integer}>, [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::<i32>());
-   |                    ---------- ------ ^^^^^^^^^^^^^^^ 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::<i32>());
    = help: the following other types implement trait `Sum<A>`:
              <i32 as Sum<&'a i32>>
              <i32 as 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::<i32>());