diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 43020a93078..d22bae816ef 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -42,6 +42,10 @@ ast_passes_const_and_async = functions cannot be both `const` and `async`
     .async = `async` because of this
     .label = {""}
 
+ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
+    .const = `const` because of this
+    .variadic = C-variadic because of this
+
 ast_passes_const_without_body =
     free constant item without body
     .suggestion = provide a definition for the constant
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index f59f7d389cd..477d3732d46 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -482,8 +482,11 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    /// Reject C-variadic type unless the function is foreign,
-    /// or free and `unsafe extern "C"` semantically.
+    /// Reject invalid C-variadic types.
+    ///
+    /// C-variadics must be:
+    /// - Non-const
+    /// - Either foreign, or free and `unsafe extern "C"` semantically
     fn check_c_variadic_type(&self, fk: FnKind<'a>) {
         let variadic_spans: Vec<_> = fk
             .decl()
@@ -497,6 +500,18 @@ impl<'a> AstValidator<'a> {
             return;
         }
 
+        if let Some(header) = fk.header() {
+            if let Const::Yes(const_span) = header.constness {
+                let mut spans = variadic_spans.clone();
+                spans.push(const_span);
+                self.err_handler().emit_err(errors::ConstAndCVariadic {
+                    spans,
+                    const_span,
+                    variadic_spans: variadic_spans.clone(),
+                });
+            }
+        }
+
         match (fk.ctxt(), fk.header()) {
             (Some(FnCtxt::Foreign), _) => return,
             (Some(FnCtxt::Free), Some(header)) => match header.ext {
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 579f528e20f..d14b62d6bdc 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -583,6 +583,17 @@ pub struct ConstAndAsync {
     pub span: Span,
 }
 
+#[derive(Diagnostic)]
+#[diag(ast_passes_const_and_c_variadic)]
+pub struct ConstAndCVariadic {
+    #[primary_span]
+    pub spans: Vec<Span>,
+    #[label(ast_passes_const)]
+    pub const_span: Span,
+    #[label(ast_passes_variadic)]
+    pub variadic_spans: Vec<Span>,
+}
+
 #[derive(Diagnostic)]
 #[diag(ast_passes_pattern_in_foreign, code = "E0130")]
 pub struct PatternInForeign {
diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs
index 8e382314ca2..b173e23e7a1 100644
--- a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs
+++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs
@@ -32,6 +32,18 @@ extern "C" fn f3_3(..., x: isize) {}
 //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
 //~| ERROR `...` must be the last argument of a C-variadic function
 
+const unsafe extern "C" fn f4_1(x: isize, ...) {}
+//~^ ERROR functions cannot be both `const` and C-variadic
+
+const extern "C" fn f4_2(x: isize, ...) {}
+//~^ ERROR functions cannot be both `const` and C-variadic
+//~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
+
+const extern "C" fn f4_3(..., x: isize, ...) {}
+//~^ ERROR functions cannot be both `const` and C-variadic
+//~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
+//~| ERROR `...` must be the last argument of a C-variadic function
+
 extern "C" {
     fn e_f1(...);
     //~^ ERROR C-variadic function must be declared with at least one named argument
@@ -53,6 +65,9 @@ impl X {
     fn i_f4(..., x: isize, ...) {}
     //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     //~| ERROR `...` must be the last argument of a C-variadic function
+    const fn i_f5(x: isize, ...) {}
+    //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
+    //~| ERROR functions cannot be both `const` and C-variadic
 }
 
 trait T {
diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr
index 95e381f06fc..18526080e4c 100644
--- a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr
+++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr
@@ -76,119 +76,172 @@ error: only foreign or `unsafe extern "C"` functions may be C-variadic
 LL | extern "C" fn f3_3(..., x: isize) {}
    |                    ^^^
 
+error: functions cannot be both `const` and C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:35:1
+   |
+LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
+   | ^^^^^ `const` because of this             ^^^ C-variadic because of this
+
+error: functions cannot be both `const` and C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:38:1
+   |
+LL | const extern "C" fn f4_2(x: isize, ...) {}
+   | ^^^^^ `const` because of this      ^^^ C-variadic because of this
+
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:38:36
+   |
+LL | const extern "C" fn f4_2(x: isize, ...) {}
+   |                                    ^^^
+
+error: `...` must be the last argument of a C-variadic function
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:42:26
+   |
+LL | const extern "C" fn f4_3(..., x: isize, ...) {}
+   |                          ^^^
+
+error: functions cannot be both `const` and C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:42:1
+   |
+LL | const extern "C" fn f4_3(..., x: isize, ...) {}
+   | ^^^^^                    ^^^            ^^^ C-variadic because of this
+   | |                        |
+   | |                        C-variadic because of this
+   | `const` because of this
+
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:42:26
+   |
+LL | const extern "C" fn f4_3(..., x: isize, ...) {}
+   |                          ^^^            ^^^
+
 error: C-variadic function must be declared with at least one named argument
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:36:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:48:13
    |
 LL |     fn e_f1(...);
    |             ^^^
 
 error: `...` must be the last argument of a C-variadic function
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:38:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
    |
 LL |     fn e_f2(..., x: isize);
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:45:23
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:57:23
    |
 LL |     fn i_f1(x: isize, ...) {}
    |                       ^^^
 
 error: C-variadic function must be declared with at least one named argument
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:47:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
    |
 LL |     fn i_f2(...) {}
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:47:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
    |
 LL |     fn i_f2(...) {}
    |             ^^^
 
 error: `...` must be the last argument of a C-variadic function
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
    |
 LL |     fn i_f3(..., x: isize, ...) {}
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
    |
 LL |     fn i_f3(..., x: isize, ...) {}
    |             ^^^            ^^^
 
 error: `...` must be the last argument of a C-variadic function
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
    |
 LL |     fn i_f4(..., x: isize, ...) {}
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
    |
 LL |     fn i_f4(..., x: isize, ...) {}
    |             ^^^            ^^^
 
+error: functions cannot be both `const` and C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:68:5
+   |
+LL |     const fn i_f5(x: isize, ...) {}
+   |     ^^^^^                   ^^^ C-variadic because of this
+   |     |
+   |     `const` because of this
+
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:59:23
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:68:29
+   |
+LL |     const fn i_f5(x: isize, ...) {}
+   |                             ^^^
+
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:74:23
    |
 LL |     fn t_f1(x: isize, ...) {}
    |                       ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:61:23
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:76:23
    |
 LL |     fn t_f2(x: isize, ...);
    |                       ^^^
 
 error: C-variadic function must be declared with at least one named argument
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:63:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
    |
 LL |     fn t_f3(...) {}
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:63:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
    |
 LL |     fn t_f3(...) {}
    |             ^^^
 
 error: C-variadic function must be declared with at least one named argument
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:66:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13
    |
 LL |     fn t_f4(...);
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:66:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13
    |
 LL |     fn t_f4(...);
    |             ^^^
 
 error: `...` must be the last argument of a C-variadic function
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:69:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13
    |
 LL |     fn t_f5(..., x: isize) {}
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:69:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13
    |
 LL |     fn t_f5(..., x: isize) {}
    |             ^^^
 
 error: `...` must be the last argument of a C-variadic function
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:72:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13
    |
 LL |     fn t_f6(..., x: isize);
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:72:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13
    |
 LL |     fn t_f6(..., x: isize);
    |             ^^^
 
-error: aborting due to 32 previous errors
+error: aborting due to 40 previous errors