Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 68baa87

Browse files
committed
Auto merge of rust-lang#146165 - folkertdev:c-variadic-errors-take-2, r=lcnr
improve c-variadic error reporting tracking issue: rust-lang#44930 The parts of rust-lang#143546 that don't require any particular knowledge about c-variadic functions. This prepares the way for rejecting c-variadic functions that are also coroutines, safe functions, or associated functions.
2 parents beeb8e3 + 8d11719 commit 68baa87

File tree

8 files changed

+140
-94
lines changed

8 files changed

+140
-94
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+
// `...` is already rejected 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+
}

‎tests/ui/c-variadic/no-closure.stderr

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/c-variadic/valid.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@ run-pass
2+
#![feature(c_variadic)]
3+
4+
// In rust (and C23 and above) `...` can be the only argument.
5+
unsafe extern "C" fn only_dot_dot_dot(mut ap: ...) -> i32 {
6+
unsafe { ap.arg() }
7+
}
8+
9+
unsafe extern "C-unwind" fn abi_c_unwind(mut ap: ...) -> i32 {
10+
unsafe { ap.arg() }
11+
}
12+
13+
#[allow(improper_ctypes_definitions)]
14+
unsafe extern "C" fn mix_int_float(mut ap: ...) -> (i64, f64, *const i32, f64) {
15+
(ap.arg(), ap.arg(), ap.arg(), ap.arg())
16+
}
17+
18+
fn main() {
19+
unsafe {
20+
assert_eq!(only_dot_dot_dot(32), 32);
21+
assert_eq!(abi_c_unwind(32), 32);
22+
23+
// Passing more arguments than expected is allowed.
24+
assert_eq!(only_dot_dot_dot(32, 1i64, core::ptr::null::<i32>(), 3.14f64), 32);
25+
26+
let ptr = &14i32 as *const i32;
27+
assert_eq!(mix_int_float(12i64, 13.0f64, ptr, 15.0f64), (12, 13.0, ptr, 15.0));
28+
}
29+
}

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ extern "C" fn f2_2(...) {}
1616
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
1717

1818
extern "C" fn f2_3(..., x: isize) {}
19-
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
20-
//~| ERROR `...` must be the last argument of a C-variadic function
19+
//~^ ERROR `...` must be the last argument of a C-variadic function
2120

2221
extern "C" fn f3_1(x: isize, ...) {}
2322
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
@@ -26,8 +25,7 @@ extern "C" fn f3_2(...) {}
2625
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
2726

2827
extern "C" fn f3_3(..., x: isize) {}
29-
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
30-
//~| ERROR `...` must be the last argument of a C-variadic function
28+
//~^ ERROR `...` must be the last argument of a C-variadic function
3129

3230
const unsafe extern "C" fn f4_1(x: isize, ...) {}
3331
//~^ ERROR functions cannot be both `const` and C-variadic
@@ -77,9 +75,7 @@ trait T {
7775
fn t_f4(...);
7876
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
7977
fn t_f5(..., x: isize) {}
80-
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
81-
//~| ERROR `...` must be the last argument of a C-variadic function
78+
//~^ ERROR `...` must be the last argument of a C-variadic function
8279
fn t_f6(..., x: isize);
83-
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
84-
//~| ERROR `...` must be the last argument of a C-variadic function
80+
//~^ ERROR `...` must be the last argument of a C-variadic function
8581
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /