Fix pointing at arg when cause is outside of call

This commit is contained in:
Janusz Marcinkiewicz 2019-12-01 13:39:01 +01:00
parent d0126e8ed3
commit d419a5fdae
3 changed files with 69 additions and 28 deletions

View File

@ -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
}
// Both checked and coerced types could have matched, thus we need to remove
// duplicates.
referenced_in.dedup();
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 (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 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();
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;
}
}
}

View File

@ -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);
}

View File

@ -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`.