Skip to content

Commit 64bc975

Browse files
committed
Mention only assoc types changes
1 parent 49d5bef commit 64bc975

File tree

4 files changed

+92
-52
lines changed

4 files changed

+92
-52
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2865,11 +2865,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
28652865
}
28662866
}
28672867

2868-
let span = expr.span;
2869-
let mut multi_span: MultiSpan = match expr.kind {
2870-
hir::ExprKind::MethodCall(_, _, _, span) => span.into(),
2871-
_ => span.into(),
2872-
};
2868+
let mut primary_spans = vec![];
2869+
let mut span_labels = vec![];
28732870

28742871
// FIXME: visit the ty to see if there's any closure involved, and if there is,
28752872
// check whether its evaluated return type is the same as the one corresponding
@@ -2897,25 +2894,28 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
28972894
}
28982895
}
28992896
let point_at_chain = |expr: &hir::Expr<'_>| {
2897+
let mut assocs = vec![];
2898+
// We still want to point at the different methods even if there hasn't
2899+
// been a change of assoc type.
2900+
let mut call_spans = vec![];
29002901
let mut expr = expr;
29012902
let mut prev_ty = self.resolve_vars_if_possible(
29022903
typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
29032904
);
2904-
let outer_ty = prev_ty;
2905-
let mut assoc_seen = 0;
29062905
while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) =
29072906
expr.kind
29082907
{
29092908
// Point at every method call in the chain with the resulting type.
29102909
// vec![1, 2, 3].iter().map(mapper).sum<i32>()
29112910
// ^^^^^^ ^^^^^^^^^^^
29122911
expr = rcvr_expr;
2912+
let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
2913+
call_spans.push(span);
29132914

29142915
let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
29152916
for diff in &type_diffs {
29162917
let Sorts(expected_found) = diff else { continue; };
29172918
let ty::Projection(proj) = expected_found.expected.kind() else { continue; };
2918-
assoc_seen += 1;
29192919

29202920
let origin = TypeVariableOrigin {
29212921
kind: TypeVariableOriginKind::TypeInference,
@@ -2963,23 +2963,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
29632963
if ocx.select_where_possible().is_empty() {
29642964
// `ty_var` now holds the type that `Item` is for `ExprTy`.
29652965
let assoc = self.tcx.def_path_str(proj.item_def_id);
2966-
multi_span.push_span_label(
2967-
span,
2968-
&format!(
2969-
"associated type `{assoc}` is `{}` here",
2970-
self.resolve_vars_if_possible(ty_var),
2971-
),
2972-
);
2966+
let ty_var = self.resolve_vars_if_possible(ty_var);
2967+
assocs_in_this_method.push(Some((span, (assoc, ty_var))));
29732968
} else {
29742969
// `<ExprTy as Iterator>` didn't select, so likely we've
29752970
// reached the end of the iterator chain, like the originating
29762971
// `Vec<_>`.
2977-
multi_span.push_span_label(
2978-
span,
2979-
format!("this call has type `{prev_ty}`"),
2980-
);
2972+
// Keep the space consistent for later zipping.
2973+
assocs_in_this_method.push(None);
29812974
}
29822975
}
2976+
assocs.push(assocs_in_this_method);
29832977
prev_ty = self.resolve_vars_if_possible(
29842978
typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
29852979
);
@@ -2992,17 +2986,65 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
29922986
// Point at the root expression
29932987
// vec![1, 2, 3].iter().map(mapper).sum<i32>()
29942988
// ^^^^^^^^^^^^^
2995-
multi_span.push_span_label(
2996-
expr.span,
2997-
format!("this expression has type `{ty}`"),
2998-
);
2989+
span_labels
2990+
.push((expr.span, format!("this expression has type `{ty}`")));
29992991
};
3000-
if assoc_seen > 0 {
3001-
// Only show this if it is not a "trivial" expression (not a method
3002-
// chain) and there are associated types to talk about.
2992+
// Only show this if it is not a "trivial" expression (not a method
2993+
// chain) and there are associated types to talk about.
2994+
let mut assocs = assocs.into_iter().peekable();
2995+
while let Some(assocs_in_method) = assocs.next() {
2996+
let Some(prev_assoc_in_method) = assocs.peek() else {
2997+
for entry in assocs_in_method {
2998+
let Some((span, (assoc, ty))) = entry else { continue; };
2999+
primary_spans.push(span);
3000+
span_labels.push((
3001+
span,
3002+
format!("associated type `{assoc}` is `{ty}` here"),
3003+
));
3004+
}
3005+
break;
3006+
};
3007+
for (entry, prev_entry) in
3008+
assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter())
3009+
{
3010+
match (entry, prev_entry) {
3011+
(Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => {
3012+
if ty != *prev_ty {
3013+
primary_spans.push(span);
3014+
span_labels.push((
3015+
span,
3016+
format!("associated type `{assoc}` changed to `{ty}` here"),
3017+
));
3018+
}
3019+
}
3020+
(Some((span, (assoc, ty))), None) => {
3021+
span_labels.push((
3022+
span,
3023+
format!("associated type `{assoc}` is `{ty}` here"),
3024+
));
3025+
}
3026+
(None, Some(_)) | (None, None) => {}
3027+
}
3028+
}
3029+
}
3030+
for span in call_spans {
3031+
if span_labels.iter().find(|(s, _)| *s == span).is_none() {
3032+
// Ensure we are showing the entire chain, even if the assoc types
3033+
// haven't changed.
3034+
span_labels.push((span, String::new()));
3035+
}
3036+
}
3037+
if !primary_spans.is_empty() {
3038+
let mut multi_span: MultiSpan = primary_spans.into();
3039+
for (span, label) in span_labels {
3040+
multi_span.push_span_label(span, label);
3041+
}
30033042
err.span_note(
30043043
multi_span,
3005-
format!("the expression is of type `{outer_ty}`"),
3044+
format!(
3045+
"the method call chain might not have had the expected \
3046+
associated types",
3047+
),
30063048
);
30073049
}
30083050
};

src/test/ui/issues/issue-34334.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece
2222
|
2323
= help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
2424
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
25-
note: the expression is of type `Map<std::slice::Iter<'_, (_, _, _)>, [closure@$DIR/issue-34334.rs:5:47: 5:82]>`
26-
--> $DIR/issue-34334.rs:5:43
25+
note: the method call chain might not have had the expected associated types
26+
--> $DIR/issue-34334.rs:5:36
2727
|
2828
LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
29-
| -- ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here
29+
| -- ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here
3030
| | |
3131
| | associated type `std::iter::Iterator::Item` is `&(_, _, _)` here
3232
| this expression has type `Vec<(_, _, _)>`

src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | let x2: Vec<f64> = x1.into_iter().collect();
88
|
99
= help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
1010
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
11-
note: the expression is of type `std::slice::Iter<'_, f64>`
11+
note: the method call chain might not have had the expected associated types
1212
--> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
1313
|
1414
LL | let x2: Vec<f64> = x1.into_iter().collect();
@@ -31,7 +31,7 @@ LL | let x3 = x1.into_iter().collect::<Vec<f64>>();
3131
|
3232
= help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
3333
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
34-
note: the expression is of type `std::slice::Iter<'_, f64>`
34+
note: the method call chain might not have had the expected associated types
3535
--> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
3636
|
3737
LL | let x3 = x1.into_iter().collect::<Vec<f64>>();

src/test/ui/iterators/invalid-iterator-chain.stderr

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,18 @@ LL | println!("{}", scores.sum::<i32>());
99
= help: the following other types implement trait `Sum<A>`:
1010
<i32 as Sum<&'a i32>>
1111
<i32 as Sum>
12-
note: the expression is of type `Map<std::slice::Iter<'_, ({integer}, {integer})>, [closure@$DIR/invalid-iterator-chain.rs:4:14: 4:22]>`
13-
--> $DIR/invalid-iterator-chain.rs:7:20
12+
note: the method call chain might not have had the expected associated types
13+
--> $DIR/invalid-iterator-chain.rs:3:10
1414
|
1515
LL | let scores = vec![(0, 0)]
1616
| ------------ this expression has type `Vec<({integer}, {integer})>`
1717
LL | .iter()
18-
| ------ associated type `std::iter::Iterator::Item` is `&({integer}, {integer})` here
18+
| ^^^^^^ associated type `std::iter::Iterator::Item` is `&({integer}, {integer})` here
1919
LL | .map(|(a, b)| {
20-
| __________-
20+
| __________^
2121
LL | | a + b;
2222
LL | | });
23-
| |__________- associated type `std::iter::Iterator::Item` is `()` here
24-
LL | println!("{}", scores.sum::<i32>());
25-
| ^^^^^^
23+
| |__________^ associated type `std::iter::Iterator::Item` changed to `()` here
2624
note: required by a bound in `std::iter::Iterator::sum`
2725
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
2826
|
@@ -46,25 +44,25 @@ LL | .sum::<i32>(),
4644
= help: the following other types implement trait `Sum<A>`:
4745
<i32 as Sum<&'a i32>>
4846
<i32 as Sum>
49-
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]>`
50-
--> $DIR/invalid-iterator-chain.rs:17:14
47+
note: the method call chain might not have had the expected associated types
48+
--> $DIR/invalid-iterator-chain.rs:11:14
5149
|
5250
LL | vec![0, 1]
5351
| ---------- this expression has type `Vec<{integer}>`
5452
LL | .iter()
55-
| ------ associated type `std::iter::Iterator::Item` is `&{integer}` here
53+
| ^^^^^^ associated type `std::iter::Iterator::Item` is `&{integer}` here
5654
LL | .map(|x| x * 2)
57-
| -------------- associated type `std::iter::Iterator::Item` is `{integer}` here
55+
| ^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `{integer}` here
5856
LL | .map(|x| x as f64)
59-
| ----------------- associated type `std::iter::Iterator::Item` is `f64` here
57+
| ^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `f64` here
6058
LL | .map(|x| x as i64)
61-
| ----------------- associated type `std::iter::Iterator::Item` is `i64` here
59+
| ^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `i64` here
6260
LL | .filter(|x| *x > 0)
63-
| ------------------ associated type `std::iter::Iterator::Item` is `i64` here
61+
| ------------------
6462
LL | .map(|x| { x + 1 })
65-
| ------------------ associated type `std::iter::Iterator::Item` is `i64` here
63+
| ------------------
6664
LL | .map(|x| { x; })
67-
| ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here
65+
| ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here
6866
note: required by a bound in `std::iter::Iterator::sum`
6967
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
7068
|
@@ -82,11 +80,11 @@ LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
8280
= help: the following other types implement trait `Sum<A>`:
8381
<i32 as Sum<&'a i32>>
8482
<i32 as Sum>
85-
note: the expression is of type `Map<std::slice::Iter<'_, {integer}>, [closure@$DIR/invalid-iterator-chain.rs:20:42: 20:45]>`
86-
--> $DIR/invalid-iterator-chain.rs:20:38
83+
note: the method call chain might not have had the expected associated types
84+
--> $DIR/invalid-iterator-chain.rs:20:31
8785
|
8886
LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
89-
| ---------- ------ ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here
87+
| ---------- ^^^^^^ ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here
9088
| | |
9189
| | associated type `std::iter::Iterator::Item` is `&{integer}` here
9290
| this expression has type `Vec<{integer}>`
@@ -107,7 +105,7 @@ LL | println!("{}", vec![(), ()].iter().sum::<i32>());
107105
= help: the following other types implement trait `Sum<A>`:
108106
<i32 as Sum<&'a i32>>
109107
<i32 as Sum>
110-
note: the expression is of type `std::slice::Iter<'_, ()>`
108+
note: the method call chain might not have had the expected associated types
111109
--> $DIR/invalid-iterator-chain.rs:21:33
112110
|
113111
LL | println!("{}", vec![(), ()].iter().sum::<i32>());

0 commit comments

Comments
 (0)