Skip to content

Commit f91b5ce

Browse files
Explicitly reject const C-variadic functions
Trying to use C-variadics in a const function would previously fail with an error like "destructor of `VaListImpl<'_>` cannot be evaluated at compile-time". Add an explicit check for const C-variadics to provide a clearer error: "functions cannot be both `const` and C-variadic".
1 parent 8508e65 commit f91b5ce

File tree

5 files changed

+120
-22
lines changed

5 files changed

+120
-22
lines changed

compiler/rustc_ast_passes/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ ast_passes_const_and_async = functions cannot be both `const` and `async`
4242
.async = `async` because of this
4343
.label = {""}
4444
45+
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
46+
.const = `const` because of this
47+
.variadic = C-variadic because of this
48+
4549
ast_passes_const_without_body =
4650
free constant item without body
4751
.suggestion = provide a definition for the constant

compiler/rustc_ast_passes/src/ast_validation.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -482,8 +482,11 @@ impl<'a> AstValidator<'a> {
482482
}
483483
}
484484

485-
/// Reject C-variadic type unless the function is foreign,
486-
/// or free and `unsafe extern "C"` semantically.
485+
/// Reject invalid C-variadic types.
486+
///
487+
/// C-variadics must be:
488+
/// - Non-const
489+
/// - Either foreign, or free and `unsafe extern "C"` semantically
487490
fn check_c_variadic_type(&self, fk: FnKind<'a>) {
488491
let variadic_spans: Vec<_> = fk
489492
.decl()
@@ -497,6 +500,18 @@ impl<'a> AstValidator<'a> {
497500
return;
498501
}
499502

503+
if let Some(header) = fk.header() {
504+
if let Const::Yes(const_span) = header.constness {
505+
let mut spans = variadic_spans.clone();
506+
spans.push(const_span);
507+
self.err_handler().emit_err(errors::ConstAndCVariadic {
508+
spans,
509+
const_span,
510+
variadic_spans: variadic_spans.clone(),
511+
});
512+
}
513+
}
514+
500515
match (fk.ctxt(), fk.header()) {
501516
(Some(FnCtxt::Foreign), _) => return,
502517
(Some(FnCtxt::Free), Some(header)) => match header.ext {

compiler/rustc_ast_passes/src/errors.rs

+11
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,17 @@ pub struct ConstAndAsync {
583583
pub span: Span,
584584
}
585585

586+
#[derive(Diagnostic)]
587+
#[diag(ast_passes_const_and_c_variadic)]
588+
pub struct ConstAndCVariadic {
589+
#[primary_span]
590+
pub spans: Vec<Span>,
591+
#[label(ast_passes_const)]
592+
pub const_span: Span,
593+
#[label(ast_passes_variadic)]
594+
pub variadic_spans: Vec<Span>,
595+
}
596+
586597
#[derive(Diagnostic)]
587598
#[diag(ast_passes_pattern_in_foreign, code = "E0130")]
588599
pub struct PatternInForeign {

tests/ui/parser/variadic-ffi-semantic-restrictions.rs

+15
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@ extern "C" fn f3_3(..., x: isize) {}
3232
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
3333
//~| ERROR `...` must be the last argument of a C-variadic function
3434

35+
const unsafe extern "C" fn f4_1(x: isize, ...) {}
36+
//~^ ERROR functions cannot be both `const` and C-variadic
37+
38+
const extern "C" fn f4_2(x: isize, ...) {}
39+
//~^ ERROR functions cannot be both `const` and C-variadic
40+
//~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
41+
42+
const extern "C" fn f4_3(..., x: isize, ...) {}
43+
//~^ ERROR functions cannot be both `const` and C-variadic
44+
//~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
45+
//~| ERROR `...` must be the last argument of a C-variadic function
46+
3547
extern "C" {
3648
fn e_f1(...);
3749
//~^ ERROR C-variadic function must be declared with at least one named argument
@@ -53,6 +65,9 @@ impl X {
5365
fn i_f4(..., x: isize, ...) {}
5466
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
5567
//~| ERROR `...` must be the last argument of a C-variadic function
68+
const fn i_f5(x: isize, ...) {}
69+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
70+
//~| ERROR functions cannot be both `const` and C-variadic
5671
}
5772

5873
trait T {

tests/ui/parser/variadic-ffi-semantic-restrictions.stderr

+73-20
Original file line numberDiff line numberDiff line change
@@ -76,119 +76,172 @@ error: only foreign or `unsafe extern "C"` functions may be C-variadic
7676
LL | extern "C" fn f3_3(..., x: isize) {}
7777
| ^^^
7878

79+
error: functions cannot be both `const` and C-variadic
80+
--> $DIR/variadic-ffi-semantic-restrictions.rs:35:1
81+
|
82+
LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
83+
| ^^^^^ `const` because of this ^^^ C-variadic because of this
84+
85+
error: functions cannot be both `const` and C-variadic
86+
--> $DIR/variadic-ffi-semantic-restrictions.rs:38:1
87+
|
88+
LL | const extern "C" fn f4_2(x: isize, ...) {}
89+
| ^^^^^ `const` because of this ^^^ C-variadic because of this
90+
91+
error: only foreign or `unsafe extern "C"` functions may be C-variadic
92+
--> $DIR/variadic-ffi-semantic-restrictions.rs:38:36
93+
|
94+
LL | const extern "C" fn f4_2(x: isize, ...) {}
95+
| ^^^
96+
97+
error: `...` must be the last argument of a C-variadic function
98+
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:26
99+
|
100+
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
101+
| ^^^
102+
103+
error: functions cannot be both `const` and C-variadic
104+
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:1
105+
|
106+
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
107+
| ^^^^^ ^^^ ^^^ C-variadic because of this
108+
| | |
109+
| | C-variadic because of this
110+
| `const` because of this
111+
112+
error: only foreign or `unsafe extern "C"` functions may be C-variadic
113+
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:26
114+
|
115+
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
116+
| ^^^ ^^^
117+
79118
error: C-variadic function must be declared with at least one named argument
80-
--> $DIR/variadic-ffi-semantic-restrictions.rs:36:13
119+
--> $DIR/variadic-ffi-semantic-restrictions.rs:48:13
81120
|
82121
LL | fn e_f1(...);
83122
| ^^^
84123

85124
error: `...` must be the last argument of a C-variadic function
86-
--> $DIR/variadic-ffi-semantic-restrictions.rs:38:13
125+
--> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
87126
|
88127
LL | fn e_f2(..., x: isize);
89128
| ^^^
90129

91130
error: only foreign or `unsafe extern "C"` functions may be C-variadic
92-
--> $DIR/variadic-ffi-semantic-restrictions.rs:45:23
131+
--> $DIR/variadic-ffi-semantic-restrictions.rs:57:23
93132
|
94133
LL | fn i_f1(x: isize, ...) {}
95134
| ^^^
96135

97136
error: C-variadic function must be declared with at least one named argument
98-
--> $DIR/variadic-ffi-semantic-restrictions.rs:47:13
137+
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
99138
|
100139
LL | fn i_f2(...) {}
101140
| ^^^
102141

103142
error: only foreign or `unsafe extern "C"` functions may be C-variadic
104-
--> $DIR/variadic-ffi-semantic-restrictions.rs:47:13
143+
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
105144
|
106145
LL | fn i_f2(...) {}
107146
| ^^^
108147

109148
error: `...` must be the last argument of a C-variadic function
110-
--> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
149+
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
111150
|
112151
LL | fn i_f3(..., x: isize, ...) {}
113152
| ^^^
114153

115154
error: only foreign or `unsafe extern "C"` functions may be C-variadic
116-
--> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
155+
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
117156
|
118157
LL | fn i_f3(..., x: isize, ...) {}
119158
| ^^^ ^^^
120159

121160
error: `...` must be the last argument of a C-variadic function
122-
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
161+
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
123162
|
124163
LL | fn i_f4(..., x: isize, ...) {}
125164
| ^^^
126165

127166
error: only foreign or `unsafe extern "C"` functions may be C-variadic
128-
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
167+
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
129168
|
130169
LL | fn i_f4(..., x: isize, ...) {}
131170
| ^^^ ^^^
132171

172+
error: functions cannot be both `const` and C-variadic
173+
--> $DIR/variadic-ffi-semantic-restrictions.rs:68:5
174+
|
175+
LL | const fn i_f5(x: isize, ...) {}
176+
| ^^^^^ ^^^ C-variadic because of this
177+
| |
178+
| `const` because of this
179+
180+
error: only foreign or `unsafe extern "C"` functions may be C-variadic
181+
--> $DIR/variadic-ffi-semantic-restrictions.rs:68:29
182+
|
183+
LL | const fn i_f5(x: isize, ...) {}
184+
| ^^^
185+
133186
error: only foreign or `unsafe extern "C"` functions may be C-variadic
134-
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:23
187+
--> $DIR/variadic-ffi-semantic-restrictions.rs:74:23
135188
|
136189
LL | fn t_f1(x: isize, ...) {}
137190
| ^^^
138191

139192
error: only foreign or `unsafe extern "C"` functions may be C-variadic
140-
--> $DIR/variadic-ffi-semantic-restrictions.rs:61:23
193+
--> $DIR/variadic-ffi-semantic-restrictions.rs:76:23
141194
|
142195
LL | fn t_f2(x: isize, ...);
143196
| ^^^
144197

145198
error: C-variadic function must be declared with at least one named argument
146-
--> $DIR/variadic-ffi-semantic-restrictions.rs:63:13
199+
--> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
147200
|
148201
LL | fn t_f3(...) {}
149202
| ^^^
150203

151204
error: only foreign or `unsafe extern "C"` functions may be C-variadic
152-
--> $DIR/variadic-ffi-semantic-restrictions.rs:63:13
205+
--> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
153206
|
154207
LL | fn t_f3(...) {}
155208
| ^^^
156209

157210
error: C-variadic function must be declared with at least one named argument
158-
--> $DIR/variadic-ffi-semantic-restrictions.rs:66:13
211+
--> $DIR/variadic-ffi-semantic-restrictions.rs:81:13
159212
|
160213
LL | fn t_f4(...);
161214
| ^^^
162215

163216
error: only foreign or `unsafe extern "C"` functions may be C-variadic
164-
--> $DIR/variadic-ffi-semantic-restrictions.rs:66:13
217+
--> $DIR/variadic-ffi-semantic-restrictions.rs:81:13
165218
|
166219
LL | fn t_f4(...);
167220
| ^^^
168221

169222
error: `...` must be the last argument of a C-variadic function
170-
--> $DIR/variadic-ffi-semantic-restrictions.rs:69:13
223+
--> $DIR/variadic-ffi-semantic-restrictions.rs:84:13
171224
|
172225
LL | fn t_f5(..., x: isize) {}
173226
| ^^^
174227

175228
error: only foreign or `unsafe extern "C"` functions may be C-variadic
176-
--> $DIR/variadic-ffi-semantic-restrictions.rs:69:13
229+
--> $DIR/variadic-ffi-semantic-restrictions.rs:84:13
177230
|
178231
LL | fn t_f5(..., x: isize) {}
179232
| ^^^
180233

181234
error: `...` must be the last argument of a C-variadic function
182-
--> $DIR/variadic-ffi-semantic-restrictions.rs:72:13
235+
--> $DIR/variadic-ffi-semantic-restrictions.rs:87:13
183236
|
184237
LL | fn t_f6(..., x: isize);
185238
| ^^^
186239

187240
error: only foreign or `unsafe extern "C"` functions may be C-variadic
188-
--> $DIR/variadic-ffi-semantic-restrictions.rs:72:13
241+
--> $DIR/variadic-ffi-semantic-restrictions.rs:87:13
189242
|
190243
LL | fn t_f6(..., x: isize);
191244
| ^^^
192245

193-
error: aborting due to 32 previous errors
246+
error: aborting due to 40 previous errors
194247

0 commit comments

Comments
 (0)