Skip to content

Commit bca1492

Browse files
Explicitly reject const C-variadic functions
Trying to use C-variadics in a const function would previously 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 690b017 commit bca1492

File tree

5 files changed

+117
-22
lines changed

5 files changed

+117
-22
lines changed

Diff for: 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

Diff for: compiler/rustc_ast_passes/src/ast_validation.rs

+15-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 Some(variadic_span) = fk
489492
.decl()
@@ -495,6 +498,16 @@ impl<'a> AstValidator<'a> {
495498
return;
496499
};
497500

501+
if let Some(header) = fk.header() {
502+
if let Const::Yes(const_span) = header.constness {
503+
self.err_handler().emit_err(errors::ConstAndCVariadic {
504+
spans: vec![const_span, variadic_span],
505+
const_span,
506+
variadic_span,
507+
});
508+
}
509+
}
510+
498511
match (fk.ctxt(), fk.header()) {
499512
(Some(FnCtxt::Foreign), _) => return,
500513
(Some(FnCtxt::Free), Some(header)) => match header.ext {

Diff for: 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_span: Span,
595+
}
596+
586597
#[derive(Diagnostic)]
587598
#[diag(ast_passes_pattern_in_foreign, code = "E0130")]
588599
pub struct PatternInForeign {

Diff for: 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 {

Diff for: tests/ui/parser/variadic-ffi-semantic-restrictions.stderr

+72-20
Original file line numberDiff line numberDiff line change
@@ -76,119 +76,171 @@ 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+
| `const` because of this
110+
111+
error: only foreign or `unsafe extern "C"` functions may be C-variadic
112+
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:26
113+
|
114+
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
115+
| ^^^
116+
79117
error: C-variadic function must be declared with at least one named argument
80-
--> $DIR/variadic-ffi-semantic-restrictions.rs:36:13
118+
--> $DIR/variadic-ffi-semantic-restrictions.rs:48:13
81119
|
82120
LL | fn e_f1(...);
83121
| ^^^
84122

85123
error: `...` must be the last argument of a C-variadic function
86-
--> $DIR/variadic-ffi-semantic-restrictions.rs:38:13
124+
--> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
87125
|
88126
LL | fn e_f2(..., x: isize);
89127
| ^^^
90128

91129
error: only foreign or `unsafe extern "C"` functions may be C-variadic
92-
--> $DIR/variadic-ffi-semantic-restrictions.rs:45:23
130+
--> $DIR/variadic-ffi-semantic-restrictions.rs:57:23
93131
|
94132
LL | fn i_f1(x: isize, ...) {}
95133
| ^^^
96134

97135
error: C-variadic function must be declared with at least one named argument
98-
--> $DIR/variadic-ffi-semantic-restrictions.rs:47:13
136+
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
99137
|
100138
LL | fn i_f2(...) {}
101139
| ^^^
102140

103141
error: only foreign or `unsafe extern "C"` functions may be C-variadic
104-
--> $DIR/variadic-ffi-semantic-restrictions.rs:47:13
142+
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
105143
|
106144
LL | fn i_f2(...) {}
107145
| ^^^
108146

109147
error: `...` must be the last argument of a C-variadic function
110-
--> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
148+
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
111149
|
112150
LL | fn i_f3(..., x: isize, ...) {}
113151
| ^^^
114152

115153
error: only foreign or `unsafe extern "C"` functions may be C-variadic
116-
--> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
154+
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
117155
|
118156
LL | fn i_f3(..., x: isize, ...) {}
119157
| ^^^
120158

121159
error: `...` must be the last argument of a C-variadic function
122-
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
160+
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
123161
|
124162
LL | fn i_f4(..., x: isize, ...) {}
125163
| ^^^
126164

127165
error: only foreign or `unsafe extern "C"` functions may be C-variadic
128-
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
166+
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
129167
|
130168
LL | fn i_f4(..., x: isize, ...) {}
131169
| ^^^
132170

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

139191
error: only foreign or `unsafe extern "C"` functions may be C-variadic
140-
--> $DIR/variadic-ffi-semantic-restrictions.rs:61:23
192+
--> $DIR/variadic-ffi-semantic-restrictions.rs:76:23
141193
|
142194
LL | fn t_f2(x: isize, ...);
143195
| ^^^
144196

145197
error: C-variadic function must be declared with at least one named argument
146-
--> $DIR/variadic-ffi-semantic-restrictions.rs:63:13
198+
--> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
147199
|
148200
LL | fn t_f3(...) {}
149201
| ^^^
150202

151203
error: only foreign or `unsafe extern "C"` functions may be C-variadic
152-
--> $DIR/variadic-ffi-semantic-restrictions.rs:63:13
204+
--> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
153205
|
154206
LL | fn t_f3(...) {}
155207
| ^^^
156208

157209
error: C-variadic function must be declared with at least one named argument
158-
--> $DIR/variadic-ffi-semantic-restrictions.rs:66:13
210+
--> $DIR/variadic-ffi-semantic-restrictions.rs:81:13
159211
|
160212
LL | fn t_f4(...);
161213
| ^^^
162214

163215
error: only foreign or `unsafe extern "C"` functions may be C-variadic
164-
--> $DIR/variadic-ffi-semantic-restrictions.rs:66:13
216+
--> $DIR/variadic-ffi-semantic-restrictions.rs:81:13
165217
|
166218
LL | fn t_f4(...);
167219
| ^^^
168220

169221
error: `...` must be the last argument of a C-variadic function
170-
--> $DIR/variadic-ffi-semantic-restrictions.rs:69:13
222+
--> $DIR/variadic-ffi-semantic-restrictions.rs:84:13
171223
|
172224
LL | fn t_f5(..., x: isize) {}
173225
| ^^^
174226

175227
error: only foreign or `unsafe extern "C"` functions may be C-variadic
176-
--> $DIR/variadic-ffi-semantic-restrictions.rs:69:13
228+
--> $DIR/variadic-ffi-semantic-restrictions.rs:84:13
177229
|
178230
LL | fn t_f5(..., x: isize) {}
179231
| ^^^
180232

181233
error: `...` must be the last argument of a C-variadic function
182-
--> $DIR/variadic-ffi-semantic-restrictions.rs:72:13
234+
--> $DIR/variadic-ffi-semantic-restrictions.rs:87:13
183235
|
184236
LL | fn t_f6(..., x: isize);
185237
| ^^^
186238

187239
error: only foreign or `unsafe extern "C"` functions may be C-variadic
188-
--> $DIR/variadic-ffi-semantic-restrictions.rs:72:13
240+
--> $DIR/variadic-ffi-semantic-restrictions.rs:87:13
189241
|
190242
LL | fn t_f6(..., x: isize);
191243
| ^^^
192244

193-
error: aborting due to 32 previous errors
245+
error: aborting due to 40 previous errors
194246

0 commit comments

Comments
 (0)