Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix pointing at arg when cause is outside of call #67354

Merged
merged 2 commits into from
Dec 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 37 additions & 28 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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]
Expand All @@ -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]`
Expand All @@ -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`.
15 changes: 15 additions & 0 deletions src/test/ui/issues/issue-66923-show-error-for-correct-call.rs
Original file line number Diff line number Diff line change
@@ -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);
}
19 changes: 19 additions & 0 deletions src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
Original file line number Diff line number Diff line change
@@ -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`.