Skip to content

Commit f2e4a2f

Browse files
committed
feature-gate c-variadic definitions and calls in const contexts
1 parent f5bf335 commit f2e4a2f

11 files changed

Lines changed: 93 additions & 5 deletions

File tree

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,13 @@ impl<'a> AstValidator<'a> {
698698
unreachable!("C variable argument list cannot be used in closures")
699699
};
700700

701+
if let Const::Yes(_) = sig.header.constness
702+
&& !self.features.enabled(sym::const_c_variadic)
703+
{
704+
let msg = format!("c-variadic const function definitions are unstable");
705+
feature_err(&self.sess, sym::const_c_variadic, sig.span, msg).emit();
706+
}
707+
701708
if let Some(coroutine_kind) = sig.header.coroutine_kind {
702709
self.dcx().emit_err(errors::CoroutineAndCVariadic {
703710
spans: vec![coroutine_kind.span(), variadic_param.span],

compiler/rustc_const_eval/src/check_consts/check.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
815815
});
816816
}
817817

818+
if self.tcx.fn_sig(callee).skip_binder().c_variadic() {
819+
self.check_op(ops::FnCallCVariadic)
820+
}
821+
818822
// At this point, we are calling a function, `callee`, whose `DefId` is known...
819823

820824
// `begin_panic` and `panic_display` functions accept generic

compiler/rustc_const_eval/src/check_consts/ops.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,31 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
7575
}
7676
}
7777

78+
/// A c-variadic function call.
79+
#[derive(Debug)]
80+
pub(crate) struct FnCallCVariadic;
81+
impl<'tcx> NonConstOp<'tcx> for FnCallCVariadic {
82+
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
83+
Status::Unstable {
84+
gate: sym::const_c_variadic,
85+
gate_already_checked: false,
86+
safe_to_expose_on_stable: false,
87+
is_function_call: true,
88+
}
89+
}
90+
91+
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
92+
ccx.tcx.sess.create_feature_err(
93+
errors::NonConstCVariadicCall {
94+
span,
95+
kind: ccx.const_kind(),
96+
non_or_conditionally: "non",
97+
},
98+
sym::const_c_variadic,
99+
)
100+
}
101+
}
102+
78103
/// A call to a function that is in a trait, or has trait bounds that make it conditionally-const.
79104
#[derive(Debug)]
80105
pub(crate) struct ConditionallyConstCall<'tcx> {

compiler/rustc_const_eval/src/errors.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,20 @@ pub struct NonConstClosure {
531531
pub non_or_conditionally: &'static str,
532532
}
533533

534+
#[derive(Diagnostic)]
535+
#[diag(r#"calling const c-variadic functions is unstable in {$kind ->
536+
[const] constant
537+
[static] static
538+
[const_fn] constant function
539+
*[other] {""}
540+
}s"#, code = E0015)]
541+
pub struct NonConstCVariadicCall {
542+
#[primary_span]
543+
pub span: Span,
544+
pub kind: ConstContext,
545+
pub non_or_conditionally: &'static str,
546+
}
547+
534548
#[derive(Subdiagnostic)]
535549
pub enum NonConstClosureNote {
536550
#[note("function defined here, but it is not `const`")]

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@ declare_features! (
420420
(unstable, const_async_blocks, "1.53.0", Some(85368)),
421421
/// Allows `const { ... }` as a shorthand for `const _: () = const { ... };` for module items.
422422
(unstable, const_block_items, "CURRENT_RUSTC_VERSION", Some(149226)),
423+
/// Allows defining and calling c-variadic functions in const contexts.
424+
(unstable, const_c_variadic, "CURRENT_RUSTC_VERSION", Some(151787)),
423425
/// Allows `const || {}` closures in const contexts.
424426
(incomplete, const_closures, "1.68.0", Some(106003)),
425427
/// Allows using `[const] Destruct` bounds and calling drop impls in const contexts.

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,7 @@ symbols! {
740740
const_allocate,
741741
const_async_blocks,
742742
const_block_items,
743+
const_c_variadic,
743744
const_closures,
744745
const_compare_raw_pointers,
745746
const_constructor,

library/core/src/ffi/va_list.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ impl VaList<'_> {
205205
}
206206
}
207207

208-
#[rustc_const_unstable(feature = "c_variadic_const", issue = "none")]
208+
#[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
209209
impl<'f> const Clone for VaList<'f> {
210210
#[inline]
211211
fn clone(&self) -> Self {
@@ -217,7 +217,7 @@ impl<'f> const Clone for VaList<'f> {
217217
}
218218
}
219219

220-
#[rustc_const_unstable(feature = "c_variadic_const", issue = "none")]
220+
#[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
221221
impl<'f> const Drop for VaList<'f> {
222222
fn drop(&mut self) {
223223
// SAFETY: this variable argument list is being dropped, so won't be read from again.
@@ -293,7 +293,7 @@ impl<'f> VaList<'f> {
293293
///
294294
/// [valid]: https://doc.rust-lang.org/nightly/nomicon/what-unsafe-does.html
295295
#[inline]
296-
#[rustc_const_unstable(feature = "c_variadic_const", issue = "none")]
296+
#[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
297297
pub const unsafe fn arg<T: VaArgSafe>(&mut self) -> T {
298298
// SAFETY: the caller must uphold the safety contract for `va_arg`.
299299
unsafe { va_arg(self) }

tests/ui/consts/const-eval/c-variadic-fail.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//@ build-fail
22

33
#![feature(c_variadic)]
4-
#![feature(c_variadic_const)]
4+
#![feature(const_c_variadic)]
55
#![feature(const_trait_impl)]
66
#![feature(const_destruct)]
77
#![feature(const_clone)]

tests/ui/consts/const-eval/c-variadic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
//@ ignore-backends: gcc
44

55
#![feature(c_variadic)]
6+
#![feature(const_c_variadic)]
67
#![feature(const_destruct)]
7-
#![feature(c_variadic_const)]
88
#![feature(const_cmp)]
99
#![feature(const_trait_impl)]
1010

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(c_variadic)]
2+
3+
fn main() {
4+
const unsafe extern "C" fn foo(ap: ...) {
5+
//~^ ERROR c-variadic const function definitions are unstable
6+
core::mem::forget(ap);
7+
}
8+
9+
const { unsafe { foo() } }
10+
//~^ ERROR calling const c-variadic functions is unstable in constants
11+
}

0 commit comments

Comments
 (0)