Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ICE for mismatched args on target without span #48047

Merged
merged 1 commit into from
Feb 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 49 additions & 44 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,8 +744,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
} else {
let (closure_span, found) = found_did
.and_then(|did| self.tcx.hir.get_if_local(did))
.map(|node| self.get_fn_like_arguments(node))
.unwrap_or((found_span.unwrap(), found));
.map(|node| {
let (found_span, found) = self.get_fn_like_arguments(node);
(Some(found_span), found)
}).unwrap_or((found_span, found));

self.report_arg_count_mismatch(span,
closure_span,
Expand Down Expand Up @@ -855,7 +857,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
fn report_arg_count_mismatch(
&self,
span: Span,
found_span: Span,
found_span: Option<Span>,
expected_args: Vec<ArgKind>,
found_args: Vec<ArgKind>,
is_closure: bool,
Expand Down Expand Up @@ -893,48 +895,51 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
);

err.span_label(span, format!( "expected {} that takes {}", kind, expected_str));
err.span_label(found_span, format!("takes {}", found_str));

if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
if fields.len() == expected_args.len() {
let sugg = fields.iter()
.map(|(name, _)| name.to_owned())
.collect::<Vec<String>>().join(", ");
err.span_suggestion(found_span,
"change the closure to take multiple arguments instead of \
a single tuple",
format!("|{}|", sugg));

if let Some(found_span) = found_span {
err.span_label(found_span, format!("takes {}", found_str));

if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
if fields.len() == expected_args.len() {
let sugg = fields.iter()
.map(|(name, _)| name.to_owned())
.collect::<Vec<String>>().join(", ");
err.span_suggestion(found_span,
"change the closure to take multiple arguments instead of \
a single tuple",
format!("|{}|", sugg));
}
}
}
if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
if fields.len() == found_args.len() && is_closure {
let sugg = format!(
"|({}){}|",
found_args.iter()
.map(|arg| match arg {
ArgKind::Arg(name, _) => name.to_owned(),
_ => "_".to_owned(),
})
.collect::<Vec<String>>()
.join(", "),
// add type annotations if available
if found_args.iter().any(|arg| match arg {
ArgKind::Arg(_, ty) => ty != "_",
_ => false,
}) {
format!(": ({})",
fields.iter()
.map(|(_, ty)| ty.to_owned())
.collect::<Vec<String>>()
.join(", "))
} else {
"".to_owned()
},
);
err.span_suggestion(found_span,
"change the closure to accept a tuple instead of individual \
arguments",
sugg);
if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
if fields.len() == found_args.len() && is_closure {
let sugg = format!(
"|({}){}|",
found_args.iter()
.map(|arg| match arg {
ArgKind::Arg(name, _) => name.to_owned(),
_ => "_".to_owned(),
})
.collect::<Vec<String>>()
.join(", "),
// add type annotations if available
if found_args.iter().any(|arg| match arg {
ArgKind::Arg(_, ty) => ty != "_",
_ => false,
}) {
format!(": ({})",
fields.iter()
.map(|(_, ty)| ty.to_owned())
.collect::<Vec<String>>()
.join(", "))
} else {
"".to_owned()
},
);
err.span_suggestion(found_span,
"change the closure to accept a tuple instead of \
individual arguments",
sugg);
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/test/ui/mismatched_types/closure-arg-count.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ fn main() {
//~^ ERROR closure is expected to take
let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
//~^ ERROR function is expected to take

let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
//~^ ERROR function is expected to take
}

fn foo() {}
Expand Down
12 changes: 9 additions & 3 deletions src/test/ui/mismatched_types/closure-arg-count.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ error[E0593]: function is expected to take a single 2-tuple as argument, but it
32 | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
| ^^^ expected function that takes a single 2-tuple as argument
...
41 | fn foo() {}
44 | fn foo() {}
| -------- takes 0 arguments

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

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

error: aborting due to 12 previous errors