Skip to content

Commit a12ec2e

Browse files
Rollup merge of rust-lang#67354 - VirrageS:blame-wrong-line, r=estebank
Fix pointing at arg when cause is outside of call Follow up after: rust-lang#66933 Closes: rust-lang#66923 r? @estebank
2 parents ddd256b + e305bf8 commit a12ec2e

5 files changed

+86
-33
lines changed

src/librustc_typeck/check/mod.rs

+37-28
Original file line numberDiff line numberDiff line change
@@ -3880,36 +3880,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
38803880
call_sp: Span,
38813881
args: &'tcx [hir::Expr],
38823882
) {
3883-
if !call_sp.desugaring_kind().is_some() {
3884-
// We *do not* do this for desugared call spans to keep good diagnostics when involving
3885-
// the `?` operator.
3886-
for error in errors {
3887-
if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
3888-
// Collect the argument position for all arguments that could have caused this
3889-
// `FulfillmentError`.
3890-
let mut referenced_in = final_arg_types.iter()
3891-
.map(|(i, checked_ty, _)| (i, checked_ty))
3892-
.chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty)))
3893-
.flat_map(|(i, ty)| {
3894-
let ty = self.resolve_vars_if_possible(ty);
3895-
// We walk the argument type because the argument's type could have
3896-
// been `Option<T>`, but the `FulfillmentError` references `T`.
3897-
ty.walk()
3898-
.filter(|&ty| ty == predicate.skip_binder().self_ty())
3899-
.map(move |_| *i)
3900-
})
3901-
.collect::<Vec<_>>();
3883+
// We *do not* do this for desugared call spans to keep good diagnostics when involving
3884+
// the `?` operator.
3885+
if call_sp.desugaring_kind().is_some() {
3886+
return
3887+
}
3888+
3889+
for error in errors {
3890+
// Only if the cause is somewhere inside the expression we want try to point at arg.
3891+
// Otherwise, it means that the cause is somewhere else and we should not change
3892+
// anything because we can break the correct span.
3893+
if !call_sp.contains(error.obligation.cause.span) {
3894+
continue
3895+
}
3896+
3897+
if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
3898+
// Collect the argument position for all arguments that could have caused this
3899+
// `FulfillmentError`.
3900+
let mut referenced_in = final_arg_types.iter()
3901+
.map(|(i, checked_ty, _)| (i, checked_ty))
3902+
.chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty)))
3903+
.flat_map(|(i, ty)| {
3904+
let ty = self.resolve_vars_if_possible(ty);
3905+
// We walk the argument type because the argument's type could have
3906+
// been `Option<T>`, but the `FulfillmentError` references `T`.
3907+
ty.walk()
3908+
.filter(|&ty| ty == predicate.skip_binder().self_ty())
3909+
.map(move |_| *i)
3910+
})
3911+
.collect::<Vec<_>>();
39023912

3903-
// Both checked and coerced types could have matched, thus we need to remove
3904-
// duplicates.
3905-
referenced_in.dedup();
3913+
// Both checked and coerced types could have matched, thus we need to remove
3914+
// duplicates.
3915+
referenced_in.dedup();
39063916

3907-
if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
3908-
// We make sure that only *one* argument matches the obligation failure
3909-
// and we assign the obligation's span to its expression's.
3910-
error.obligation.cause.span = args[ref_in].span;
3911-
error.points_at_arg_span = true;
3912-
}
3917+
if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
3918+
// We make sure that only *one* argument matches the obligation failure
3919+
// and we assign the obligation's span to its expression's.
3920+
error.obligation.cause.span = args[ref_in].span;
3921+
error.points_at_arg_span = true;
39133922
}
39143923
}
39153924
}

src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub fn no_debug() {
66
pub fn no_hash() {
77
use std::collections::HashSet;
88
let mut set = HashSet::new();
9+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
910
set.insert([0_usize; 33]);
1011
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
1112
}

src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr

+14-5
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,24 @@ LL | println!("{:?}", [0_usize; 33]);
88
= note: required by `std::fmt::Debug::fmt`
99

1010
error[E0277]: arrays only have std trait implementations for lengths 0..=32
11-
--> $DIR/core-traits-no-impls-length-33.rs:9:16
11+
--> $DIR/core-traits-no-impls-length-33.rs:10:16
1212
|
1313
LL | set.insert([0_usize; 33]);
1414
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
1515
|
1616
= note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
1717

18+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
19+
--> $DIR/core-traits-no-impls-length-33.rs:8:19
20+
|
21+
LL | let mut set = HashSet::new();
22+
| ^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
23+
|
24+
= note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
25+
= note: required by `std::collections::HashSet::<T>::new`
26+
1827
error[E0369]: binary operation `==` cannot be applied to type `[usize; 33]`
19-
--> $DIR/core-traits-no-impls-length-33.rs:14:19
28+
--> $DIR/core-traits-no-impls-length-33.rs:15:19
2029
|
2130
LL | [0_usize; 33] == [1_usize; 33]
2231
| ------------- ^^ ------------- [usize; 33]
@@ -26,7 +35,7 @@ LL | [0_usize; 33] == [1_usize; 33]
2635
= note: an implementation of `std::cmp::PartialEq` might be missing for `[usize; 33]`
2736

2837
error[E0369]: binary operation `<` cannot be applied to type `[usize; 33]`
29-
--> $DIR/core-traits-no-impls-length-33.rs:19:19
38+
--> $DIR/core-traits-no-impls-length-33.rs:20:19
3039
|
3140
LL | [0_usize; 33] < [1_usize; 33]
3241
| ------------- ^ ------------- [usize; 33]
@@ -36,7 +45,7 @@ LL | [0_usize; 33] < [1_usize; 33]
3645
= note: an implementation of `std::cmp::PartialOrd` might be missing for `[usize; 33]`
3746

3847
error[E0277]: the trait bound `&[usize; 33]: std::iter::IntoIterator` is not satisfied
39-
--> $DIR/core-traits-no-impls-length-33.rs:24:14
48+
--> $DIR/core-traits-no-impls-length-33.rs:25:14
4049
|
4150
LL | for _ in &[0_usize; 33] {
4251
| ^^^^^^^^^^^^^^ the trait `std::iter::IntoIterator` is not implemented for `&[usize; 33]`
@@ -48,7 +57,7 @@ LL | for _ in &[0_usize; 33] {
4857
<&'a mut [T] as std::iter::IntoIterator>
4958
= note: required by `std::iter::IntoIterator::into_iter`
5059

51-
error: aborting due to 5 previous errors
60+
error: aborting due to 6 previous errors
5261

5362
Some errors have detailed explanations: E0277, E0369.
5463
For more information about an error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// This test checks that errors are showed for lines with `collect` rather than `push` method.
2+
3+
fn main() {
4+
let v = vec![1_f64, 2.2_f64];
5+
let mut fft: Vec<Vec<f64>> = vec![];
6+
7+
let x1: &[f64] = &v;
8+
let x2: Vec<f64> = x1.into_iter().collect();
9+
//~^ ERROR a value of type
10+
fft.push(x2);
11+
12+
let x3 = x1.into_iter().collect::<Vec<f64>>();
13+
//~^ ERROR a value of type
14+
fft.push(x3);
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0277]: a value of type `std::vec::Vec<f64>` cannot be built from an iterator over elements of type `&f64`
2+
--> $DIR/issue-66923-show-error-for-correct-call.rs:8:39
3+
|
4+
LL | let x2: Vec<f64> = x1.into_iter().collect();
5+
| ^^^^^^^ value of type `std::vec::Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
6+
|
7+
= help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec<f64>`
8+
9+
error[E0277]: a value of type `std::vec::Vec<f64>` cannot be built from an iterator over elements of type `&f64`
10+
--> $DIR/issue-66923-show-error-for-correct-call.rs:12:29
11+
|
12+
LL | let x3 = x1.into_iter().collect::<Vec<f64>>();
13+
| ^^^^^^^ value of type `std::vec::Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
14+
|
15+
= help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec<f64>`
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)