about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJesse Rusak <me@jesserusak.com>2024-09-16 11:26:26 -0400
committerJesse Rusak <me@jesserusak.com>2024-09-16 14:51:56 -0400
commit45eceb2c576d20dd43c22ae4b591a4f1e9d1db56 (patch)
tree7063ac917b4d9a57426150e88c8c4097e240645c
parent3a22be33db27e4f90e95dfaad301af400386efc1 (diff)
downloadrust-45eceb2c576d20dd43c22ae4b591a4f1e9d1db56.tar.gz
rust-45eceb2c576d20dd43c22ae4b591a4f1e9d1db56.zip
Avoid crashing on variadic functions when producing arg-mismatch errors
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs17
-rw-r--r--tests/crashes/130372-1.rs9
-rw-r--r--tests/crashes/130372-2.rs11
-rw-r--r--tests/crashes/130372-3.rs7
-rw-r--r--tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.rs12
-rw-r--r--tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.stderr19
6 files changed, 44 insertions, 31 deletions
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<Vec<(Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
         let fn_node = self.tcx.hir().get_if_local(def_id)?;
+        let fn_decl = fn_node.fn_decl()?;
 
-        let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_node
-            .fn_decl()?
+        let generic_params: Vec<Option<&hir::GenericParam<'_>>> = 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`.