From 45eceb2c576d20dd43c22ae4b591a4f1e9d1db56 Mon Sep 17 00:00:00 2001 From: Jesse Rusak Date: Mon, 16 Sep 2024 11:26:26 -0400 Subject: [PATCH] Avoid crashing on variadic functions when producing arg-mismatch errors --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 17 +++++++++++++---- tests/crashes/130372-1.rs | 9 --------- tests/crashes/130372-2.rs | 11 ----------- tests/crashes/130372-3.rs | 7 ------- .../mismatch-args-vargs-issue-130372.rs | 12 ++++++++++++ .../mismatch-args-vargs-issue-130372.stderr | 19 +++++++++++++++++++ 6 files changed, 44 insertions(+), 31 deletions(-) delete mode 100644 tests/crashes/130372-1.rs delete mode 100644 tests/crashes/130372-2.rs delete mode 100644 tests/crashes/130372-3.rs create mode 100644 tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.rs create mode 100644 tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 8348c6e9a16..8810f14aaa9 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2619,9 +2619,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_method: bool, ) -> Option>, &hir::Param<'_>)>> { let fn_node = self.tcx.hir().get_if_local(def_id)?; + let fn_decl = fn_node.fn_decl()?; - let generic_params: Vec>> = fn_node - .fn_decl()? + let generic_params: Vec>> = fn_decl .inputs .into_iter() .skip(if is_method { 1 } else { 0 }) @@ -2642,7 +2642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .collect(); - let params: Vec<&hir::Param<'_>> = self + let mut params: Vec<&hir::Param<'_>> = self .tcx .hir() .body(fn_node.body_id()?) @@ -2651,7 +2651,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .skip(if is_method { 1 } else { 0 }) .collect(); - Some(generic_params.into_iter().zip_eq(params).collect()) + // The surrounding code expects variadic functions to not have a parameter representing + // the "..." parameter. This is already true of the FnDecl but not of the body params, so + // we drop it if it exists. + + if fn_decl.c_variadic { + params.pop(); + } + + debug_assert_eq!(params.len(), generic_params.len()); + Some(generic_params.into_iter().zip(params).collect()) } } diff --git a/tests/crashes/130372-1.rs b/tests/crashes/130372-1.rs deleted file mode 100644 index 5d58c14e7ab..00000000000 --- a/tests/crashes/130372-1.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: rust-lang/rust#130372 - -pub fn variadic_fn(n: usize, mut args: ...) {} - -reuse variadic_fn; - -fn main() { - variadic_fn(); -} diff --git a/tests/crashes/130372-2.rs b/tests/crashes/130372-2.rs deleted file mode 100644 index 46404191e32..00000000000 --- a/tests/crashes/130372-2.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: rust-lang/rust#130372 - -pub fn test_va_copy(_: u64, mut ap: ...) {} - -pub fn main() { - unsafe { - test_va_copy(); - - call(x); - } -} diff --git a/tests/crashes/130372-3.rs b/tests/crashes/130372-3.rs deleted file mode 100644 index 6e1c57437c8..00000000000 --- a/tests/crashes/130372-3.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: rust-lang/rust#130372 - -fn bar() -> impl Fn() { - wrap() -} - -fn wrap(...: impl ...) -> impl Fn() {} diff --git a/tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.rs b/tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.rs new file mode 100644 index 00000000000..60a3b47010e --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.rs @@ -0,0 +1,12 @@ +#![feature(c_variadic)] + +// Regression test that covers all 3 cases of https://github.com/rust-lang/rust/issues/130372 + +unsafe extern "C" fn test_va_copy(_: u64, mut ap: ...) {} + +pub fn main() { + unsafe { + test_va_copy(); + //~^ ERROR this function takes at least 1 argument but 0 arguments were supplied + } +} diff --git a/tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.stderr b/tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.stderr new file mode 100644 index 00000000000..38f76970358 --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.stderr @@ -0,0 +1,19 @@ +error[E0060]: this function takes at least 1 argument but 0 arguments were supplied + --> $DIR/mismatch-args-vargs-issue-130372.rs:9:9 + | +LL | test_va_copy(); + | ^^^^^^^^^^^^-- argument #1 of type `u64` is missing + | +note: function defined here + --> $DIR/mismatch-args-vargs-issue-130372.rs:5:22 + | +LL | unsafe extern "C" fn test_va_copy(_: u64, mut ap: ...) {} + | ^^^^^^^^^^^^ ------ +help: provide the argument + | +LL | test_va_copy(/* u64 */); + | ~~~~~~~~~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0060`.