Skip to content

Commit

Permalink
Fix pointing at arg when cause is outside of call
Browse files Browse the repository at this point in the history
  • Loading branch information
VirrageS committed Dec 6, 2019
1 parent d0126e8 commit d419a5f
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 28 deletions.
65 changes: 37 additions & 28 deletions src/librustc_typeck/check/mod.rs
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
13 changes: 13 additions & 0 deletions src/test/ui/issues/issue-66923.rs
@@ -0,0 +1,13 @@
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 collection of type
fft.push(x2);

let x3 = x1.into_iter().collect::<Vec<f64>>();
//~^ ERROR a collection of type
fft.push(x3);
}
19 changes: 19 additions & 0 deletions src/test/ui/issues/issue-66923.stderr
@@ -0,0 +1,19 @@
error[E0277]: a collection of type `std::vec::Vec<f64>` cannot be built from an iterator over elements of type `&f64`
--> $DIR/issue-66923.rs:6:39
|
LL | let x2: Vec<f64> = x1.into_iter().collect();
| ^^^^^^^ a collection 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 collection of type `std::vec::Vec<f64>` cannot be built from an iterator over elements of type `&f64`
--> $DIR/issue-66923.rs:10:29
|
LL | let x3 = x1.into_iter().collect::<Vec<f64>>();
| ^^^^^^^ a collection 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`.

0 comments on commit d419a5f

Please sign in to comment.