Skip to content

Commit 4cc7ef5

Browse files
committed
Fix pointing at arg when cause is outside of call
1 parent d8bdb3f commit 4cc7ef5

File tree

3 files changed

+69
-28
lines changed

3 files changed

+69
-28
lines changed

src/librustc_typeck/check/mod.rs

+37-28
Original file line numberDiff line numberDiff line change
@@ -3876,36 +3876,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
38763876
call_sp: Span,
38773877
args: &'tcx [hir::Expr],
38783878
) {
3879-
if !call_sp.desugaring_kind().is_some() {
3880-
// We *do not* do this for desugared call spans to keep good diagnostics when involving
3881-
// the `?` operator.
3882-
for error in errors {
3883-
if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
3884-
// Collect the argument position for all arguments that could have caused this
3885-
// `FulfillmentError`.
3886-
let mut referenced_in = final_arg_types.iter()
3887-
.map(|(i, checked_ty, _)| (i, checked_ty))
3888-
.chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty)))
3889-
.flat_map(|(i, ty)| {
3890-
let ty = self.resolve_vars_if_possible(ty);
3891-
// We walk the argument type because the argument's type could have
3892-
// been `Option<T>`, but the `FulfillmentError` references `T`.
3893-
ty.walk()
3894-
.filter(|&ty| ty == predicate.skip_binder().self_ty())
3895-
.map(move |_| *i)
3896-
})
3897-
.collect::<Vec<_>>();
3879+
// We *do not* do this for desugared call spans to keep good diagnostics when involving
3880+
// the `?` operator.
3881+
if call_sp.desugaring_kind().is_some() {
3882+
return
3883+
}
3884+
3885+
for error in errors {
3886+
// Only if the cause is somewhere inside the expression we want try to point at arg.
3887+
// Otherwise, it means that the cause is somewhere else and we should not change
3888+
// anything because we can break the correct span.
3889+
if !call_sp.contains(error.obligation.cause.span) {
3890+
continue
3891+
}
3892+
3893+
if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
3894+
// Collect the argument position for all arguments that could have caused this
3895+
// `FulfillmentError`.
3896+
let mut referenced_in = final_arg_types.iter()
3897+
.map(|(i, checked_ty, _)| (i, checked_ty))
3898+
.chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty)))
3899+
.flat_map(|(i, ty)| {
3900+
let ty = self.resolve_vars_if_possible(ty);
3901+
// We walk the argument type because the argument's type could have
3902+
// been `Option<T>`, but the `FulfillmentError` references `T`.
3903+
ty.walk()
3904+
.filter(|&ty| ty == predicate.skip_binder().self_ty())
3905+
.map(move |_| *i)
3906+
})
3907+
.collect::<Vec<_>>();
38983908

3899-
// Both checked and coerced types could have matched, thus we need to remove
3900-
// duplicates.
3901-
referenced_in.dedup();
3909+
// Both checked and coerced types could have matched, thus we need to remove
3910+
// duplicates.
3911+
referenced_in.dedup();
39023912

3903-
if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
3904-
// We make sure that only *one* argument matches the obligation failure
3905-
// and we assign the obligation's span to its expression's.
3906-
error.obligation.cause.span = args[ref_in].span;
3907-
error.points_at_arg_span = true;
3908-
}
3913+
if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
3914+
// We make sure that only *one* argument matches the obligation failure
3915+
// and we assign the obligation's span to its expression's.
3916+
error.obligation.cause.span = args[ref_in].span;
3917+
error.points_at_arg_span = true;
39093918
}
39103919
}
39113920
}

src/test/ui/issues/issue-66923.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fn main() {
2+
let v = vec![1_f64, 2.2_f64];
3+
let mut fft: Vec<Vec<f64>> = vec![];
4+
5+
let x1: &[f64] = &v;
6+
let x2: Vec<f64> = x1.into_iter().collect();
7+
//~^ ERROR a collection of type
8+
fft.push(x2);
9+
10+
let x3 = x1.into_iter().collect::<Vec<f64>>();
11+
//~^ ERROR a collection of type
12+
fft.push(x3);
13+
}

src/test/ui/issues/issue-66923.stderr

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0277]: a collection of type `std::vec::Vec<f64>` cannot be built from an iterator over elements of type `&f64`
2+
--> $DIR/issue-66923.rs:6:39
3+
|
4+
LL | let x2: Vec<f64> = x1.into_iter().collect();
5+
| ^^^^^^^ a collection of type `std::vec::Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
6+
|
7+
= help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec<f64>`
8+
9+
error[E0277]: a collection of type `std::vec::Vec<f64>` cannot be built from an iterator over elements of type `&f64`
10+
--> $DIR/issue-66923.rs:10:29
11+
|
12+
LL | let x3 = x1.into_iter().collect::<Vec<f64>>();
13+
| ^^^^^^^ a collection of type `std::vec::Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
14+
|
15+
= help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec<f64>`
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)