Skip to content

Commit 27bb41f

Browse files
committed
error on a safe fn that uses C-variadics
1 parent 2549fdb commit 27bb41f

File tree

5 files changed

+49
-5
lines changed

5 files changed

+49
-5
lines changed

compiler/rustc_ast_passes/messages.ftl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim
2424
.label = {ast_passes_auto_super_lifetime}
2525
.suggestion = remove the super traits or lifetime bounds
2626
27-
ast_passes_bad_c_variadic = only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg
28-
2927
ast_passes_bare_fn_invalid_safety = function pointers cannot be declared with `safe` safety qualifier
3028
.suggestion = remove safe from this item
3129
@@ -36,6 +34,13 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
3634
3735
ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
3836
37+
ast_passes_c_variadic_bad_calling_convention =
38+
only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg
39+
40+
ast_passes_c_variadic_safe_foreign_function =
41+
foreign functions with a C-variadic argument cannot be safe
42+
.suggestion = remove the `safe` keyword from this definition
43+
3944
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
4045
.const = `const` because of this
4146
.variadic = C-variadic because of this

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,16 @@ impl<'a> AstValidator<'a> {
554554
}
555555

556556
match (fk.ctxt(), fk.header()) {
557-
(Some(FnCtxt::Foreign), _) => return,
557+
(Some(FnCtxt::Foreign), Some(header)) => match header.safety {
558+
Safety::Default | Safety::Unsafe(_) => return,
559+
Safety::Safe(safe_span) => {
560+
// The span of the "safe " string that should be removed.
561+
let safe_span = safe_span.with_hi(safe_span.hi() + rustc_span::BytePos(1));
562+
self.dcx().emit_err(errors::CVariadicSafeForeignFunction { safe_span });
563+
return;
564+
}
565+
},
566+
558567
(Some(FnCtxt::Free), Some(header)) => match header.ext {
559568
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _)
560569
| Extern::Explicit(StrLit { symbol_unescaped: sym::C_dash_unwind, .. }, _)

compiler/rustc_ast_passes/src/errors.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,12 +308,25 @@ pub(crate) struct ExternItemAscii {
308308
}
309309

310310
#[derive(Diagnostic)]
311-
#[diag(ast_passes_bad_c_variadic)]
311+
#[diag(ast_passes_c_variadic_bad_calling_convention)]
312312
pub(crate) struct BadCVariadic {
313313
#[primary_span]
314314
pub span: Vec<Span>,
315315
}
316316

317+
#[derive(Diagnostic)]
318+
#[diag(ast_passes_c_variadic_safe_foreign_function)]
319+
pub(crate) struct CVariadicSafeForeignFunction {
320+
#[primary_span]
321+
#[suggestion(
322+
ast_passes_suggestion,
323+
applicability = "maybe-incorrect",
324+
code = "",
325+
style = "verbose"
326+
)]
327+
pub safe_span: Span,
328+
}
329+
317330
#[derive(Diagnostic)]
318331
#[diag(ast_passes_item_underscore)]
319332
pub(crate) struct ItemUnderscore<'a> {

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,8 @@ trait T {
8383
//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg
8484
//~| ERROR `...` must be the last argument of a C-variadic function
8585
}
86+
87+
unsafe extern "C" {
88+
safe fn s_f1(...);
89+
//~^ ERROR foreign functions with a C-variadic argument cannot be safe
90+
}

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,18 @@ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` function
201201
LL | fn t_f6(..., x: isize);
202202
| ^^^
203203

204+
error: foreign functions with a C-variadic argument cannot be safe
205+
--> $DIR/variadic-ffi-semantic-restrictions.rs:88:5
206+
|
207+
LL | safe fn s_f1(...);
208+
| ^^^^^
209+
|
210+
help: remove the `safe` keyword from this definition
211+
|
212+
LL - safe fn s_f1(...);
213+
LL + fn s_f1(...);
214+
|
215+
204216
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
205217
--> $DIR/variadic-ffi-semantic-restrictions.rs:32:43
206218
|
@@ -225,6 +237,6 @@ LL | const fn i_f5(x: isize, ...) {}
225237
| |
226238
| the destructor for this type cannot be evaluated in constant functions
227239

228-
error: aborting due to 36 previous errors
240+
error: aborting due to 37 previous errors
229241

230242
For more information about this error, try `rustc --explain E0493`.

0 commit comments

Comments
 (0)