about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBryanskiy <ivakin.kir@gmail.com>2025-03-12 16:57:12 +0300
committerBryanskiy <ivakin.kir@gmail.com>2025-03-12 17:14:51 +0300
commitccdba16f42c951163d00c7e6cd7051be64d2f847 (patch)
tree0fc509e8f47624be4ef4b83b71d2b96ecafb0c67
parent57a4736e9f4b7e8089b2db60583607f3b550c862 (diff)
downloadrust-ccdba16f42c951163d00c7e6cd7051be64d2f847.tar.gz
rust-ccdba16f42c951163d00c7e6cd7051be64d2f847.zip
Delegation: reject C-variadics
-rw-r--r--compiler/rustc_hir_analysis/src/delegation.rs5
-rw-r--r--tests/ui/delegation/fn-header-variadic.rs25
-rw-r--r--tests/ui/delegation/fn-header-variadic.stderr22
-rw-r--r--tests/ui/delegation/fn-header.rs11
4 files changed, 52 insertions, 11 deletions
diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs
index 4dbdfa3d85a..b0b3590d68c 100644
--- a/compiler/rustc_hir_analysis/src/delegation.rs
+++ b/compiler/rustc_hir_analysis/src/delegation.rs
@@ -409,6 +409,11 @@ fn check_constraints<'tcx>(
         emit("recursive delegation is not supported yet");
     }
 
+    if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic {
+        // See issue #127443 for explanation.
+        emit("delegation to C-variadic functions is not allowed");
+    }
+
     ret
 }
 
diff --git a/tests/ui/delegation/fn-header-variadic.rs b/tests/ui/delegation/fn-header-variadic.rs
new file mode 100644
index 00000000000..2c83d64d0b3
--- /dev/null
+++ b/tests/ui/delegation/fn-header-variadic.rs
@@ -0,0 +1,25 @@
+//@ aux-crate:fn_header_aux=fn-header-aux.rs
+
+#![feature(c_variadic)]
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+    pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
+}
+
+reuse to_reuse::variadic_fn;
+//~^ ERROR delegation to C-variadic functions is not allowed
+reuse fn_header_aux::variadic_fn_extern;
+//~^ ERROR delegation to C-variadic functions is not allowed
+
+fn main() {
+    unsafe {
+        variadic_fn(0);
+        variadic_fn(0, 1);
+        variadic_fn_extern(0);
+        variadic_fn_extern(0, 1);
+    }
+    let _: unsafe extern "C" fn(usize, ...) = variadic_fn;
+    let _: unsafe extern "C" fn(usize, ...) = variadic_fn_extern;
+}
diff --git a/tests/ui/delegation/fn-header-variadic.stderr b/tests/ui/delegation/fn-header-variadic.stderr
new file mode 100644
index 00000000000..688a965fb4d
--- /dev/null
+++ b/tests/ui/delegation/fn-header-variadic.stderr
@@ -0,0 +1,22 @@
+error: delegation to C-variadic functions is not allowed
+  --> $DIR/fn-header-variadic.rs:11:17
+   |
+LL |     pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
+   |     ------------------------------------------------------------- callee defined here
+...
+LL | reuse to_reuse::variadic_fn;
+   |                 ^^^^^^^^^^^
+
+error: delegation to C-variadic functions is not allowed
+  --> $DIR/fn-header-variadic.rs:13:22
+   |
+LL | reuse fn_header_aux::variadic_fn_extern;
+   |                      ^^^^^^^^^^^^^^^^^^
+   |
+  ::: $DIR/auxiliary/fn-header-aux.rs:7:1
+   |
+LL | pub unsafe extern "C" fn variadic_fn_extern(n: usize, mut args: ...) {}
+   | -------------------------------------------------------------------- callee defined here
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/delegation/fn-header.rs b/tests/ui/delegation/fn-header.rs
index db20e1058e0..9de0d549f20 100644
--- a/tests/ui/delegation/fn-header.rs
+++ b/tests/ui/delegation/fn-header.rs
@@ -10,20 +10,17 @@
 mod to_reuse {
     pub unsafe fn unsafe_fn() {}
     pub extern "C" fn extern_fn() {}
-    pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
     pub const fn const_fn() {}
     pub async fn async_fn() {}
 }
 
 reuse to_reuse::unsafe_fn;
 reuse to_reuse::extern_fn;
-reuse to_reuse::variadic_fn;
 reuse to_reuse::const_fn;
 reuse to_reuse::async_fn;
 
 reuse fn_header_aux::unsafe_fn_extern;
 reuse fn_header_aux::extern_fn_extern;
-reuse fn_header_aux::variadic_fn_extern;
 reuse fn_header_aux::const_fn_extern;
 reuse fn_header_aux::async_fn_extern;
 
@@ -46,12 +43,4 @@ fn main() {
     extern_fn_extern();
     let _: extern "C" fn() = extern_fn;
     let _: extern "C" fn() = extern_fn_extern;
-    unsafe {
-        variadic_fn(0);
-        variadic_fn(0, 1);
-        variadic_fn_extern(0);
-        variadic_fn_extern(0, 1);
-    }
-    let _: unsafe extern "C" fn(usize, ...) = variadic_fn;
-    let _: unsafe extern "C" fn(usize, ...) = variadic_fn_extern;
 }