Skip to content

Commit 784f04b

Browse files
Rollup merge of #117370 - nicholasbishop:bishop-better-c-variadic-errors, r=oli-obk
C-variadic error improvements A couple improvements for c-variadic errors: 1. Fix the bad-c-variadic error being emitted multiple times. If a function incorrectly contains multiple `...` args, and is also not foreign or `unsafe extern "C"`, only emit the latter error once rather than once per `...`. 2. 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". This also addresses one of the concerns in #44930: "Ensure that even when this gets stabilized for regular functions, it is still rejected on const fn."
2 parents 5ac999f + f91b5ce commit 784f04b

File tree

6 files changed

+135
-49
lines changed

6 files changed

+135
-49
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

+30-7
Original file line numberDiff line numberDiff line change
@@ -482,9 +482,36 @@ 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>) {
491+
let variadic_spans: Vec<_> = fk
492+
.decl()
493+
.inputs
494+
.iter()
495+
.filter(|arg| matches!(arg.ty.kind, TyKind::CVarArgs))
496+
.map(|arg| arg.span)
497+
.collect();
498+
499+
if variadic_spans.is_empty() {
500+
return;
501+
}
502+
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+
488515
match (fk.ctxt(), fk.header()) {
489516
(Some(FnCtxt::Foreign), _) => return,
490517
(Some(FnCtxt::Free), Some(header)) => match header.ext {
@@ -499,11 +526,7 @@ impl<'a> AstValidator<'a> {
499526
_ => {}
500527
};
501528

502-
for Param { ty, span, .. } in &fk.decl().inputs {
503-
if let TyKind::CVarArgs = ty.kind {
504-
self.err_handler().emit_err(errors::BadCVariadic { span: *span });
505-
}
506-
}
529+
self.err_handler().emit_err(errors::BadCVariadic { span: variadic_spans });
507530
}
508531

509532
fn check_item_named(&self, ident: Ident, kind: &str) {

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

+12-1
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ pub struct ExternItemAscii {
271271
#[diag(ast_passes_bad_c_variadic)]
272272
pub struct BadCVariadic {
273273
#[primary_span]
274-
pub span: Span,
274+
pub span: Vec<Span>,
275275
}
276276

277277
#[derive(Diagnostic)]
@@ -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 {

Diff for: tests/ui/c-variadic/issue-86053-1.stderr

+2-8
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,7 @@ error: only foreign or `unsafe extern "C"` functions may be C-variadic
5050
--> $DIR/issue-86053-1.rs:11:12
5151
|
5252
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
53-
| ^^^
54-
55-
error: only foreign or `unsafe extern "C"` functions may be C-variadic
56-
--> $DIR/issue-86053-1.rs:11:36
57-
|
58-
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
59-
| ^^^
53+
| ^^^ ^^^
6054

6155
error[E0412]: cannot find type `F` in this scope
6256
--> $DIR/issue-86053-1.rs:11:48
@@ -76,6 +70,6 @@ help: you might be missing a type parameter
7670
LL | fn ordering4 < 'a , 'b, F > ( a : , self , self , self ,
7771
| +++
7872

79-
error: aborting due to 11 previous errors
73+
error: aborting due to 10 previous errors
8074

8175
For more information about this error, try `rustc --explain E0412`.

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

+15-2
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
@@ -49,12 +61,13 @@ impl X {
4961
//~| ERROR C-variadic function must be declared with at least one named argument
5062
fn i_f3(..., x: isize, ...) {}
5163
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
52-
//~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
5364
//~| ERROR `...` must be the last argument of a C-variadic function
5465
fn i_f4(..., x: isize, ...) {}
5566
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
56-
//~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
5767
//~| 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
5871
}
5972

6073
trait T {

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

+72-31
Original file line numberDiff line numberDiff line change
@@ -76,131 +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
111-
|
112-
LL | fn i_f3(..., x: isize, ...) {}
113-
| ^^^
114-
115-
error: only foreign or `unsafe extern "C"` functions may be C-variadic
116-
--> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
149+
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
117150
|
118151
LL | fn i_f3(..., x: isize, ...) {}
119152
| ^^^
120153

121154
error: only foreign or `unsafe extern "C"` functions may be C-variadic
122-
--> $DIR/variadic-ffi-semantic-restrictions.rs:50:28
155+
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
123156
|
124157
LL | fn i_f3(..., x: isize, ...) {}
125-
| ^^^
158+
| ^^^ ^^^
126159

127160
error: `...` must be the last argument of a C-variadic function
128-
--> $DIR/variadic-ffi-semantic-restrictions.rs:54:13
161+
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
129162
|
130163
LL | fn i_f4(..., x: isize, ...) {}
131164
| ^^^
132165

133166
error: only foreign or `unsafe extern "C"` functions may be C-variadic
134-
--> $DIR/variadic-ffi-semantic-restrictions.rs:54:13
167+
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
135168
|
136169
LL | fn i_f4(..., x: isize, ...) {}
137-
| ^^^
170+
| ^^^ ^^^
171+
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
138179

139180
error: only foreign or `unsafe extern "C"` functions may be C-variadic
140-
--> $DIR/variadic-ffi-semantic-restrictions.rs:54:28
181+
--> $DIR/variadic-ffi-semantic-restrictions.rs:68:29
141182
|
142-
LL | fn i_f4(..., x: isize, ...) {}
143-
| ^^^
183+
LL | const fn i_f5(x: isize, ...) {}
184+
| ^^^
144185

145186
error: only foreign or `unsafe extern "C"` functions may be C-variadic
146-
--> $DIR/variadic-ffi-semantic-restrictions.rs:61:23
187+
--> $DIR/variadic-ffi-semantic-restrictions.rs:74:23
147188
|
148189
LL | fn t_f1(x: isize, ...) {}
149190
| ^^^
150191

151192
error: only foreign or `unsafe extern "C"` functions may be C-variadic
152-
--> $DIR/variadic-ffi-semantic-restrictions.rs:63:23
193+
--> $DIR/variadic-ffi-semantic-restrictions.rs:76:23
153194
|
154195
LL | fn t_f2(x: isize, ...);
155196
| ^^^
156197

157198
error: C-variadic function must be declared with at least one named argument
158-
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
199+
--> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
159200
|
160201
LL | fn t_f3(...) {}
161202
| ^^^
162203

163204
error: only foreign or `unsafe extern "C"` functions may be C-variadic
164-
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
205+
--> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
165206
|
166207
LL | fn t_f3(...) {}
167208
| ^^^
168209

169210
error: C-variadic function must be declared with at least one named argument
170-
--> $DIR/variadic-ffi-semantic-restrictions.rs:68:13
211+
--> $DIR/variadic-ffi-semantic-restrictions.rs:81:13
171212
|
172213
LL | fn t_f4(...);
173214
| ^^^
174215

175216
error: only foreign or `unsafe extern "C"` functions may be C-variadic
176-
--> $DIR/variadic-ffi-semantic-restrictions.rs:68:13
217+
--> $DIR/variadic-ffi-semantic-restrictions.rs:81:13
177218
|
178219
LL | fn t_f4(...);
179220
| ^^^
180221

181222
error: `...` must be the last argument of a C-variadic function
182-
--> $DIR/variadic-ffi-semantic-restrictions.rs:71:13
223+
--> $DIR/variadic-ffi-semantic-restrictions.rs:84:13
183224
|
184225
LL | fn t_f5(..., x: isize) {}
185226
| ^^^
186227

187228
error: only foreign or `unsafe extern "C"` functions may be C-variadic
188-
--> $DIR/variadic-ffi-semantic-restrictions.rs:71:13
229+
--> $DIR/variadic-ffi-semantic-restrictions.rs:84:13
189230
|
190231
LL | fn t_f5(..., x: isize) {}
191232
| ^^^
192233

193234
error: `...` must be the last argument of a C-variadic function
194-
--> $DIR/variadic-ffi-semantic-restrictions.rs:74:13
235+
--> $DIR/variadic-ffi-semantic-restrictions.rs:87:13
195236
|
196237
LL | fn t_f6(..., x: isize);
197238
| ^^^
198239

199240
error: only foreign or `unsafe extern "C"` functions may be C-variadic
200-
--> $DIR/variadic-ffi-semantic-restrictions.rs:74:13
241+
--> $DIR/variadic-ffi-semantic-restrictions.rs:87:13
201242
|
202243
LL | fn t_f6(..., x: isize);
203244
| ^^^
204245

205-
error: aborting due to 34 previous errors
246+
error: aborting due to 40 previous errors
206247

0 commit comments

Comments
 (0)