diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 43020a930788f..d22bae816ef41 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 78bf4339e2b6b..7b62832187a8a 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 Some(variadic_span) = fk .decl() @@ -495,6 +498,16 @@ impl<'a> AstValidator<'a> { return; }; + if let Some(header) = fk.header() { + if let Const::Yes(const_span) = header.constness { + self.err_handler().emit_err(errors::ConstAndCVariadic { + spans: vec![const_span, variadic_span], + const_span, + variadic_span, + }); + } + } + 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 e74d94e43474d..71358727aa84e 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, + #[label(ast_passes_const)] + pub const_span: Span, + #[label(ast_passes_variadic)] + pub variadic_span: 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 8e382314ca27e..b173e23e7a183 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 231cd06093f95..4d477f62df98f 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -76,119 +76,171 @@ 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 + | | + | `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: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:59:23 + --> $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