diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-12-20 17:22:21 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-12-20 17:22:21 +0100 |
| commit | 5a8083c6652f55b5a902dc4c60070ec87a632c22 (patch) | |
| tree | 1ca2d88f9e906bb6851efd5d21b4df1c7075e7ac | |
| parent | ec82174fad385882798b6c223dc1b8ac44f58332 (diff) | |
| parent | e305bf8bc8cecaf93080f07962a4f763cd66f5ce (diff) | |
| download | rust-5a8083c6652f55b5a902dc4c60070ec87a632c22.tar.gz rust-5a8083c6652f55b5a902dc4c60070ec87a632c22.zip | |
Rollup merge of #67354 - VirrageS:blame-wrong-line, r=estebank
Fix pointing at arg when cause is outside of call Follow up after: #66933 Closes: #66923 r? @estebank
5 files changed, 86 insertions, 33 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 09771bb7625..7f1c6c99cf8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3880,36 +3880,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_sp: Span, args: &'tcx [hir::Expr], ) { - if !call_sp.desugaring_kind().is_some() { - // We *do not* do this for desugared call spans to keep good diagnostics when involving - // the `?` operator. - for error in errors { - if let ty::Predicate::Trait(predicate) = error.obligation.predicate { - // Collect the argument position for all arguments that could have caused this - // `FulfillmentError`. - let mut referenced_in = final_arg_types.iter() - .map(|(i, checked_ty, _)| (i, checked_ty)) - .chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty))) - .flat_map(|(i, ty)| { - let ty = self.resolve_vars_if_possible(ty); - // We walk the argument type because the argument's type could have - // been `Option<T>`, but the `FulfillmentError` references `T`. - ty.walk() - .filter(|&ty| ty == predicate.skip_binder().self_ty()) - .map(move |_| *i) - }) - .collect::<Vec<_>>(); + // We *do not* do this for desugared call spans to keep good diagnostics when involving + // the `?` operator. + if call_sp.desugaring_kind().is_some() { + return + } + + for error in errors { + // Only if the cause is somewhere inside the expression we want try to point at arg. + // Otherwise, it means that the cause is somewhere else and we should not change + // anything because we can break the correct span. + if !call_sp.contains(error.obligation.cause.span) { + continue + } + + if let ty::Predicate::Trait(predicate) = error.obligation.predicate { + // Collect the argument position for all arguments that could have caused this + // `FulfillmentError`. + let mut referenced_in = final_arg_types.iter() + .map(|(i, checked_ty, _)| (i, checked_ty)) + .chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty))) + .flat_map(|(i, ty)| { + let ty = self.resolve_vars_if_possible(ty); + // We walk the argument type because the argument's type could have + // been `Option<T>`, but the `FulfillmentError` references `T`. + ty.walk() + .filter(|&ty| ty == predicate.skip_binder().self_ty()) + .map(move |_| *i) + }) + .collect::<Vec<_>>(); - // Both checked and coerced types could have matched, thus we need to remove - // duplicates. - referenced_in.dedup(); + // Both checked and coerced types could have matched, thus we need to remove + // duplicates. + referenced_in.dedup(); - if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) { - // We make sure that only *one* argument matches the obligation failure - // and we assign the obligation's span to its expression's. - error.obligation.cause.span = args[ref_in].span; - error.points_at_arg_span = true; - } + if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) { + // We make sure that only *one* argument matches the obligation failure + // and we assign the obligation's span to its expression's. + error.obligation.cause.span = args[ref_in].span; + error.points_at_arg_span = true; } } } diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs index 8397d204f35..7fa059583f5 100644 --- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs +++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs @@ -6,6 +6,7 @@ pub fn no_debug() { pub fn no_hash() { use std::collections::HashSet; let mut set = HashSet::new(); + //~^ ERROR arrays only have std trait implementations for lengths 0..=32 set.insert([0_usize; 33]); //~^ ERROR arrays only have std trait implementations for lengths 0..=32 } diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr index 594a0d4b5d8..d885c98dcb2 100644 --- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr +++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr @@ -8,15 +8,24 @@ LL | println!("{:?}", [0_usize; 33]); = note: required by `std::fmt::Debug::fmt` error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/core-traits-no-impls-length-33.rs:9:16 + --> $DIR/core-traits-no-impls-length-33.rs:10:16 | LL | set.insert([0_usize; 33]); | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]` | = note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]` +error[E0277]: arrays only have std trait implementations for lengths 0..=32 + --> $DIR/core-traits-no-impls-length-33.rs:8:19 + | +LL | let mut set = HashSet::new(); + | ^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]` + | + = note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]` + = note: required by `std::collections::HashSet::<T>::new` + error[E0369]: binary operation `==` cannot be applied to type `[usize; 33]` - --> $DIR/core-traits-no-impls-length-33.rs:14:19 + --> $DIR/core-traits-no-impls-length-33.rs:15:19 | LL | [0_usize; 33] == [1_usize; 33] | ------------- ^^ ------------- [usize; 33] @@ -26,7 +35,7 @@ LL | [0_usize; 33] == [1_usize; 33] = note: an implementation of `std::cmp::PartialEq` might be missing for `[usize; 33]` error[E0369]: binary operation `<` cannot be applied to type `[usize; 33]` - --> $DIR/core-traits-no-impls-length-33.rs:19:19 + --> $DIR/core-traits-no-impls-length-33.rs:20:19 | LL | [0_usize; 33] < [1_usize; 33] | ------------- ^ ------------- [usize; 33] @@ -36,7 +45,7 @@ LL | [0_usize; 33] < [1_usize; 33] = note: an implementation of `std::cmp::PartialOrd` might be missing for `[usize; 33]` error[E0277]: the trait bound `&[usize; 33]: std::iter::IntoIterator` is not satisfied - --> $DIR/core-traits-no-impls-length-33.rs:24:14 + --> $DIR/core-traits-no-impls-length-33.rs:25:14 | LL | for _ in &[0_usize; 33] { | ^^^^^^^^^^^^^^ the trait `std::iter::IntoIterator` is not implemented for `&[usize; 33]` @@ -48,7 +57,7 @@ LL | for _ in &[0_usize; 33] { <&'a mut [T] as std::iter::IntoIterator> = note: required by `std::iter::IntoIterator::into_iter` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0277, E0369. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs b/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs new file mode 100644 index 00000000000..83328073972 --- /dev/null +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs @@ -0,0 +1,15 @@ +// This test checks that errors are showed for lines with `collect` rather than `push` method. + +fn main() { + let v = vec![1_f64, 2.2_f64]; + let mut fft: Vec<Vec<f64>> = vec![]; + + let x1: &[f64] = &v; + let x2: Vec<f64> = x1.into_iter().collect(); + //~^ ERROR a value of type + fft.push(x2); + + let x3 = x1.into_iter().collect::<Vec<f64>>(); + //~^ ERROR a value of type + fft.push(x3); +} 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 new file mode 100644 index 00000000000..8e7ee97e0b9 --- /dev/null +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -0,0 +1,19 @@ +error[E0277]: a value of type `std::vec::Vec<f64>` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39 + | +LL | let x2: Vec<f64> = x1.into_iter().collect(); + | ^^^^^^^ value of type `std::vec::Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>` + | + = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec<f64>` + +error[E0277]: a value of type `std::vec::Vec<f64>` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29 + | +LL | let x3 = x1.into_iter().collect::<Vec<f64>>(); + | ^^^^^^^ value of type `std::vec::Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>` + | + = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec<f64>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. |
