Fix pointing at arg when cause is outside of call
This commit is contained in:
parent
d0126e8ed3
commit
d419a5fdae
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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`.
|
Loading…
Reference in New Issue