Skip to content

Commit e05f537

Browse files
committed
simplify check_c_variadic_type
1 parent 94722ca commit e05f537

File tree

6 files changed

+82
-37
lines changed

6 files changed

+82
-37
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -665,46 +665,42 @@ impl<'a> AstValidator<'a> {
665665
/// - Non-const
666666
/// - Either foreign, or free and `unsafe extern "C"` semantically
667667
fn check_c_variadic_type(&self, fk: FnKind<'a>) {
668-
let variadic_spans: Vec<_> = fk
669-
.decl()
670-
.inputs
671-
.iter()
672-
.filter(|arg| matches!(arg.ty.kind, TyKind::CVarArgs))
673-
.map(|arg| arg.span)
674-
.collect();
668+
// The parser already rejects `...` when it is not the final parameter.
669+
let variadic_param = match fk.decl().inputs.last() {
670+
Some(param) if matches!(param.ty.kind, TyKind::CVarArgs) => param,
671+
_ => return,
672+
};
675673

676-
if variadic_spans.is_empty() {
677-
return;
678-
}
674+
let FnKind::Fn(fn_ctxt, _, Fn { sig, .. }) = fk else {
675+
// Unreachable because the parser already rejects `...` in closures.
676+
unreachable!("C variable argument list cannot be used in closures")
677+
};
679678

680-
if let Some(header) = fk.header()
681-
&& let Const::Yes(const_span) = header.constness
682-
{
683-
let mut spans = variadic_spans.clone();
684-
spans.push(const_span);
679+
// C-variadics are not yet implemented in const evaluation.
680+
if let Const::Yes(const_span) = sig.header.constness {
685681
self.dcx().emit_err(errors::ConstAndCVariadic {
686-
spans,
682+
spans: vec![const_span, variadic_param.span],
687683
const_span,
688-
variadic_spans: variadic_spans.clone(),
684+
variadic_span: variadic_param.span,
689685
});
690686
}
691687

692-
match (fk.ctxt(), fk.header()) {
693-
(Some(FnCtxt::Foreign), _) => return,
694-
(Some(FnCtxt::Free), Some(header)) => match header.ext {
688+
match fn_ctxt {
689+
FnCtxt::Foreign => return,
690+
FnCtxt::Free => match sig.header.ext {
695691
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _)
696692
| Extern::Explicit(StrLit { symbol_unescaped: sym::C_dash_unwind, .. }, _)
697693
| Extern::Implicit(_)
698-
if matches!(header.safety, Safety::Unsafe(_)) =>
694+
if matches!(sig.header.safety, Safety::Unsafe(_)) =>
699695
{
700696
return;
701697
}
702698
_ => {}
703699
},
704-
_ => {}
700+
FnCtxt::Assoc(_) => {}
705701
};
706702

707-
self.dcx().emit_err(errors::BadCVariadic { span: variadic_spans });
703+
self.dcx().emit_err(errors::BadCVariadic { span: variadic_param.span });
708704
}
709705

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

compiler/rustc_ast_passes/src/errors.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ pub(crate) struct ExternItemAscii {
322322
#[diag(ast_passes_bad_c_variadic)]
323323
pub(crate) struct BadCVariadic {
324324
#[primary_span]
325-
pub span: Vec<Span>,
325+
pub span: Span,
326326
}
327327

328328
#[derive(Diagnostic)]
@@ -656,7 +656,7 @@ pub(crate) struct ConstAndCVariadic {
656656
#[label(ast_passes_const)]
657657
pub const_span: Span,
658658
#[label(ast_passes_variadic)]
659-
pub variadic_spans: Vec<Span>,
659+
pub variadic_span: Span,
660660
}
661661

662662
#[derive(Diagnostic)]

tests/ui/c-variadic/issue-86053-1.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize
4747
| ^^^
4848

4949
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
50-
--> $DIR/issue-86053-1.rs:11:12
50+
--> $DIR/issue-86053-1.rs:11:36
5151
|
5252
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
53-
| ^^^ ^^^
53+
| ^^^
5454

5555
error[E0412]: cannot find type `F` in this scope
5656
--> $DIR/issue-86053-1.rs:11:48

tests/ui/c-variadic/no-closure.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![feature(c_variadic)]
2+
#![crate_type = "lib"]
3+
4+
// Check that `...` in closures is rejected.
5+
6+
const F: extern "C" fn(...) = |_: ...| {};
7+
//~^ ERROR C-variadic type `...` may not be nested inside another type
8+
9+
fn foo() {
10+
let f = |...| {};
11+
//~^ ERROR: `..` patterns are not allowed here
12+
//~| ERROR: unexpected `...`
13+
14+
let f = |_: ...| {};
15+
//~^ ERROR C-variadic type `...` may not be nested inside another type
16+
f(1i64)
17+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error[E0743]: C-variadic type `...` may not be nested inside another type
2+
--> $DIR/no-closure.rs:6:35
3+
|
4+
LL | const F: extern "C" fn(...) = |_: ...| {};
5+
| ^^^
6+
7+
error: unexpected `...`
8+
--> $DIR/no-closure.rs:10:14
9+
|
10+
LL | let f = |...| {};
11+
| ^^^ not a valid pattern
12+
|
13+
help: for a rest pattern, use `..` instead of `...`
14+
|
15+
LL - let f = |...| {};
16+
LL + let f = |..| {};
17+
|
18+
19+
error[E0743]: C-variadic type `...` may not be nested inside another type
20+
--> $DIR/no-closure.rs:14:17
21+
|
22+
LL | let f = |_: ...| {};
23+
| ^^^
24+
25+
error: `..` patterns are not allowed here
26+
--> $DIR/no-closure.rs:10:14
27+
|
28+
LL | let f = |...| {};
29+
| ^^^
30+
|
31+
= note: only allowed in tuple, tuple struct, and slice patterns
32+
33+
error: aborting due to 4 previous errors
34+
35+
For more information about this error, try `rustc --explain E0743`.

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

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,13 @@ error: functions cannot be both `const` and C-variadic
8686
--> $DIR/variadic-ffi-semantic-restrictions.rs:41:1
8787
|
8888
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
89-
| ^^^^^ ^^^ ^^^ C-variadic because of this
90-
| | |
91-
| | C-variadic because of this
92-
| `const` because of this
89+
| ^^^^^ `const` because of this ^^^ C-variadic because of this
9390

9491
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
95-
--> $DIR/variadic-ffi-semantic-restrictions.rs:41:26
92+
--> $DIR/variadic-ffi-semantic-restrictions.rs:41:41
9693
|
9794
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
98-
| ^^^ ^^^
95+
| ^^^
9996

10097
error: `...` must be the last argument of a C-variadic function
10198
--> $DIR/variadic-ffi-semantic-restrictions.rs:47:13
@@ -122,10 +119,10 @@ LL | fn i_f3(..., x: isize, ...) {}
122119
| ^^^
123120

124121
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
125-
--> $DIR/variadic-ffi-semantic-restrictions.rs:58:13
122+
--> $DIR/variadic-ffi-semantic-restrictions.rs:58:28
126123
|
127124
LL | fn i_f3(..., x: isize, ...) {}
128-
| ^^^ ^^^
125+
| ^^^
129126

130127
error: `...` must be the last argument of a C-variadic function
131128
--> $DIR/variadic-ffi-semantic-restrictions.rs:61:13
@@ -134,10 +131,10 @@ LL | fn i_f4(..., x: isize, ...) {}
134131
| ^^^
135132

136133
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
137-
--> $DIR/variadic-ffi-semantic-restrictions.rs:61:13
134+
--> $DIR/variadic-ffi-semantic-restrictions.rs:61:28
138135
|
139136
LL | fn i_f4(..., x: isize, ...) {}
140-
| ^^^ ^^^
137+
| ^^^
141138

142139
error: functions cannot be both `const` and C-variadic
143140
--> $DIR/variadic-ffi-semantic-restrictions.rs:64:5

0 commit comments

Comments
 (0)