Skip to content

Commit c04ec2c

Browse files
authored
Rollup merge of rust-lang#48047 - etaoins:fix-ice-for-mismatched-args-on-target-without-span, r=estebank
Fix ICE for mismatched args on target without span Commit 7ed00ca improved our error reporting by including the target function in our error messages when there is an argument count mismatch. A simple example from the UI tests is: ``` error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:32:53 | 32 | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo); | ^^^ expected function that takes a single 2-tuple as argument ... 44 | fn foo() {} | -------- takes 0 arguments ``` However, this assumed the target span was always available. This does not hold true if the target function is in `std` or another crate. A simple example from rust-lang#48046 is assigning `str::split` to a function type with a different number of arguments. Fix by omitting all of the labels and suggestions related to the target span when it's not found. Fixes rust-lang#48046 r? @estebank
2 parents 077979f + daaa9a4 commit c04ec2c

File tree

3 files changed

+61
-47
lines changed

3 files changed

+61
-47
lines changed

src/librustc/traits/error_reporting.rs

+49-44
Original file line numberDiff line numberDiff line change
@@ -764,8 +764,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
764764
} else {
765765
let (closure_span, found) = found_did
766766
.and_then(|did| self.tcx.hir.get_if_local(did))
767-
.map(|node| self.get_fn_like_arguments(node))
768-
.unwrap_or((found_span.unwrap(), found));
767+
.map(|node| {
768+
let (found_span, found) = self.get_fn_like_arguments(node);
769+
(Some(found_span), found)
770+
}).unwrap_or((found_span, found));
769771

770772
self.report_arg_count_mismatch(span,
771773
closure_span,
@@ -875,7 +877,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
875877
fn report_arg_count_mismatch(
876878
&self,
877879
span: Span,
878-
found_span: Span,
880+
found_span: Option<Span>,
879881
expected_args: Vec<ArgKind>,
880882
found_args: Vec<ArgKind>,
881883
is_closure: bool,
@@ -913,48 +915,51 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
913915
);
914916

915917
err.span_label(span, format!( "expected {} that takes {}", kind, expected_str));
916-
err.span_label(found_span, format!("takes {}", found_str));
917-
918-
if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
919-
if fields.len() == expected_args.len() {
920-
let sugg = fields.iter()
921-
.map(|(name, _)| name.to_owned())
922-
.collect::<Vec<String>>().join(", ");
923-
err.span_suggestion(found_span,
924-
"change the closure to take multiple arguments instead of \
925-
a single tuple",
926-
format!("|{}|", sugg));
918+
919+
if let Some(found_span) = found_span {
920+
err.span_label(found_span, format!("takes {}", found_str));
921+
922+
if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
923+
if fields.len() == expected_args.len() {
924+
let sugg = fields.iter()
925+
.map(|(name, _)| name.to_owned())
926+
.collect::<Vec<String>>().join(", ");
927+
err.span_suggestion(found_span,
928+
"change the closure to take multiple arguments instead of \
929+
a single tuple",
930+
format!("|{}|", sugg));
931+
}
927932
}
928-
}
929-
if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
930-
if fields.len() == found_args.len() && is_closure {
931-
let sugg = format!(
932-
"|({}){}|",
933-
found_args.iter()
934-
.map(|arg| match arg {
935-
ArgKind::Arg(name, _) => name.to_owned(),
936-
_ => "_".to_owned(),
937-
})
938-
.collect::<Vec<String>>()
939-
.join(", "),
940-
// add type annotations if available
941-
if found_args.iter().any(|arg| match arg {
942-
ArgKind::Arg(_, ty) => ty != "_",
943-
_ => false,
944-
}) {
945-
format!(": ({})",
946-
fields.iter()
947-
.map(|(_, ty)| ty.to_owned())
948-
.collect::<Vec<String>>()
949-
.join(", "))
950-
} else {
951-
"".to_owned()
952-
},
953-
);
954-
err.span_suggestion(found_span,
955-
"change the closure to accept a tuple instead of individual \
956-
arguments",
957-
sugg);
933+
if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
934+
if fields.len() == found_args.len() && is_closure {
935+
let sugg = format!(
936+
"|({}){}|",
937+
found_args.iter()
938+
.map(|arg| match arg {
939+
ArgKind::Arg(name, _) => name.to_owned(),
940+
_ => "_".to_owned(),
941+
})
942+
.collect::<Vec<String>>()
943+
.join(", "),
944+
// add type annotations if available
945+
if found_args.iter().any(|arg| match arg {
946+
ArgKind::Arg(_, ty) => ty != "_",
947+
_ => false,
948+
}) {
949+
format!(": ({})",
950+
fields.iter()
951+
.map(|(_, ty)| ty.to_owned())
952+
.collect::<Vec<String>>()
953+
.join(", "))
954+
} else {
955+
"".to_owned()
956+
},
957+
);
958+
err.span_suggestion(found_span,
959+
"change the closure to accept a tuple instead of \
960+
individual arguments",
961+
sugg);
962+
}
958963
}
959964
}
960965

src/test/ui/mismatched_types/closure-arg-count.rs

+3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ fn main() {
3636
//~^ ERROR closure is expected to take
3737
let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
3838
//~^ ERROR function is expected to take
39+
40+
let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
41+
//~^ ERROR function is expected to take
3942
}
4043

4144
fn foo() {}

src/test/ui/mismatched_types/closure-arg-count.stderr

+9-3
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ error[E0593]: function is expected to take a single 2-tuple as argument, but it
9090
32 | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
9191
| ^^^ expected function that takes a single 2-tuple as argument
9292
...
93-
41 | fn foo() {}
93+
44 | fn foo() {}
9494
| -------- takes 0 arguments
9595

9696
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
@@ -107,8 +107,14 @@ error[E0593]: function is expected to take a single 2-tuple as argument, but it
107107
37 | let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
108108
| ^^^ expected function that takes a single 2-tuple as argument
109109
...
110-
42 | fn qux(x: usize, y: usize) {}
110+
45 | fn qux(x: usize, y: usize) {}
111111
| -------------------------- takes 2 distinct arguments
112112

113-
error: aborting due to 11 previous errors
113+
error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
114+
--> $DIR/closure-arg-count.rs:40:41
115+
|
116+
40 | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
117+
| ^^^ expected function that takes 1 argument
118+
119+
error: aborting due to 12 previous errors
114120

0 commit comments

Comments
 (0)