Skip to content

Commit 45eceb2

Browse files
committed
Avoid crashing on variadic functions when producing arg-mismatch errors
1 parent 3a22be3 commit 45eceb2

File tree

6 files changed

+44
-31
lines changed

6 files changed

+44
-31
lines changed

Diff for: compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -2619,9 +2619,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26192619
is_method: bool,
26202620
) -> Option<Vec<(Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
26212621
let fn_node = self.tcx.hir().get_if_local(def_id)?;
2622+
let fn_decl = fn_node.fn_decl()?;
26222623

2623-
let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_node
2624-
.fn_decl()?
2624+
let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_decl
26252625
.inputs
26262626
.into_iter()
26272627
.skip(if is_method { 1 } else { 0 })
@@ -2642,7 +2642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26422642
})
26432643
.collect();
26442644

2645-
let params: Vec<&hir::Param<'_>> = self
2645+
let mut params: Vec<&hir::Param<'_>> = self
26462646
.tcx
26472647
.hir()
26482648
.body(fn_node.body_id()?)
@@ -2651,7 +2651,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26512651
.skip(if is_method { 1 } else { 0 })
26522652
.collect();
26532653

2654-
Some(generic_params.into_iter().zip_eq(params).collect())
2654+
// The surrounding code expects variadic functions to not have a parameter representing
2655+
// the "..." parameter. This is already true of the FnDecl but not of the body params, so
2656+
// we drop it if it exists.
2657+
2658+
if fn_decl.c_variadic {
2659+
params.pop();
2660+
}
2661+
2662+
debug_assert_eq!(params.len(), generic_params.len());
2663+
Some(generic_params.into_iter().zip(params).collect())
26552664
}
26562665
}
26572666

Diff for: tests/crashes/130372-1.rs

-9
This file was deleted.

Diff for: tests/crashes/130372-2.rs

-11
This file was deleted.

Diff for: tests/crashes/130372-3.rs

-7
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![feature(c_variadic)]
2+
3+
// Regression test that covers all 3 cases of https://github.com/rust-lang/rust/issues/130372
4+
5+
unsafe extern "C" fn test_va_copy(_: u64, mut ap: ...) {}
6+
7+
pub fn main() {
8+
unsafe {
9+
test_va_copy();
10+
//~^ ERROR this function takes at least 1 argument but 0 arguments were supplied
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0060]: this function takes at least 1 argument but 0 arguments were supplied
2+
--> $DIR/mismatch-args-vargs-issue-130372.rs:9:9
3+
|
4+
LL | test_va_copy();
5+
| ^^^^^^^^^^^^-- argument #1 of type `u64` is missing
6+
|
7+
note: function defined here
8+
--> $DIR/mismatch-args-vargs-issue-130372.rs:5:22
9+
|
10+
LL | unsafe extern "C" fn test_va_copy(_: u64, mut ap: ...) {}
11+
| ^^^^^^^^^^^^ ------
12+
help: provide the argument
13+
|
14+
LL | test_va_copy(/* u64 */);
15+
| ~~~~~~~~~~~
16+
17+
error: aborting due to 1 previous error
18+
19+
For more information about this error, try `rustc --explain E0060`.

0 commit comments

Comments
 (0)