}
}
TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"),
- TyKind::CVarArgs => bug!("`TyKind::CVarArgs` should have been handled elsewhere"),
+ TyKind::CVarArgs => {
+ self.sess.delay_span_bug(
+ t.span,
+ "`TyKind::CVarArgs` should have been handled elsewhere",
+ );
+ hir::TyKind::Err
+ }
};
hir::Ty {
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec<Param>> {
- let sp = self.token.span;
let is_trait_item = cfg.is_self_allowed;
- let mut c_variadic = false;
// Parse the arguments, starting out with `self` being possibly allowed...
- let (params, _) = self.parse_paren_comma_seq(|p| {
- let param = p.parse_param_general(&cfg, is_trait_item);
+ let (mut params, _) = self.parse_paren_comma_seq(|p| {
+ let param = p.parse_param_general(&cfg, is_trait_item).or_else(|mut e| {
+ e.emit();
+ let lo = p.prev_span;
+ // Skip every token until next possible arg or end.
+ p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
+ // Create a placeholder argument for proper arg count (issue #34264).
+ Ok(dummy_arg(Ident::new(kw::Invalid, lo.to(p.prev_span))))
+ });
// ...now that we've parsed the first argument, `self` is no longer allowed.
cfg.is_self_allowed = false;
-
- match param {
- Ok(param) => Ok(
- if let TyKind::CVarArgs = param.ty.kind {
- c_variadic = true;
- if p.token != token::CloseDelim(token::Paren) {
- p.span_err(
- p.token.span,
- "`...` must be the last argument of a C-variadic function",
- );
- // FIXME(eddyb) this should probably still push `CVarArgs`.
- // Maybe AST validation/HIR lowering should emit the above error?
- None
- } else {
- Some(param)
- }
- } else {
- Some(param)
- }
- ),
- Err(mut e) => {
- e.emit();
- let lo = p.prev_span;
- // Skip every token until next possible arg or end.
- p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
- // Create a placeholder argument for proper arg count (issue #34264).
- let span = lo.to(p.prev_span);
- Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
- }
- }
+ param
})?;
-
- let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect();
-
// Replace duplicated recovered params with `_` pattern to avoid unnecessary errors.
self.deduplicate_recovered_params_names(&mut params);
-
- if c_variadic && params.len() <= 1 {
- self.span_err(
- sp,
- "C-variadic function must be declared with at least one named argument",
- );
- }
-
Ok(params)
}
}
fn check_fn_decl(&self, fn_decl: &FnDecl) {
+ match &*fn_decl.inputs {
+ [Param { ty, span, .. }] => if let TyKind::CVarArgs = ty.kind {
+ self.err_handler()
+ .span_err(
+ *span,
+ "C-variadic function must be declared with at least one named argument",
+ );
+ },
+ [ps @ .., _] => for Param { ty, span, .. } in ps {
+ if let TyKind::CVarArgs = ty.kind {
+ self.err_handler()
+ .span_err(
+ *span,
+ "`...` must be the last argument of a C-variadic function",
+ );
+ }
+ }
+ _ => {}
+ }
+
fn_decl
.inputs
.iter()
)
.span_label(attr.span, "doc comments are not allowed here")
.emit();
- }
- else {
+ } else {
self.err_handler().span_err(attr.span, "allow, cfg, cfg_attr, deny, \
forbid, and warn are the only allowed built-in attributes in function parameters")
});
error: C-variadic function must be declared with at least one named argument
- --> $DIR/variadic-ffi-no-fixed-args.rs:2:11
+ --> $DIR/variadic-ffi-no-fixed-args.rs:2:12
|
LL | fn foo(...);
- | ^
+ | ^^^^
error: aborting due to previous error
fn main() {}
-fn f1(x: isize, ...) {}
-//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
+fn f1_1(x: isize, ...) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
-extern "C" fn f2(x: isize, ...) {}
-//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
+fn f1_2(...) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~| ERROR C-variadic function must be declared with at least one named argument
-extern fn f3(x: isize, ...) {}
-//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
+extern "C" fn f2_1(x: isize, ...) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+
+extern "C" fn f2_2(...) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~| ERROR C-variadic function must be declared with at least one named argument
+
+extern "C" fn f2_3(..., x: isize) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~| ERROR `...` must be the last argument of a C-variadic function
+
+extern fn f3_1(x: isize, ...) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+
+extern fn f3_2(...) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~| ERROR C-variadic function must be declared with at least one named argument
+
+extern fn f3_3(..., x: isize) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~| ERROR `...` must be the last argument of a C-variadic function
+
+extern {
+ fn e_f1(...);
+ //~^ ERROR C-variadic function must be declared with at least one named argument
+ fn e_f2(..., x: isize);
+ //~^ ERROR `...` must be the last argument of a C-variadic function
+}
struct X;
impl X {
- fn f4(x: isize, ...) {}
- //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
+ fn i_f1(x: isize, ...) {}
+ //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+ fn i_f2(...) {}
+ //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+ //~| ERROR C-variadic function must be declared with at least one named argument
+ fn i_f3(..., x: isize, ...) {}
+ //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+ //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+ //~| ERROR `...` must be the last argument of a C-variadic function
+ fn i_f4(..., x: isize, ...) {}
+ //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+ //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+ //~| ERROR `...` must be the last argument of a C-variadic function
}
trait T {
- fn f5(x: isize, ...) {}
- //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
- fn f6(x: isize, ...);
- //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
+ fn t_f1(x: isize, ...) {}
+ //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+ fn t_f2(x: isize, ...);
+ //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+ fn t_f3(...) {}
+ //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+ //~| ERROR C-variadic function must be declared with at least one named argument
+ fn t_f4(...);
+ //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+ //~| ERROR C-variadic function must be declared with at least one named argument
+ fn t_f5(..., x: isize) {}
+ //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+ //~| ERROR `...` must be the last argument of a C-variadic function
+ fn t_f6(..., x: isize);
+ //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+ //~| ERROR `...` must be the last argument of a C-variadic function
}
error: only foreign or `unsafe extern "C" functions may be C-variadic
- --> $DIR/variadic-ffi-semantic-restrictions.rs:5:17
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:5:19
|
-LL | fn f1(x: isize, ...) {}
- | ^^^^
+LL | fn f1_1(x: isize, ...) {}
+ | ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
+ |
+LL | fn f1_2(...) {}
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
+ |
+LL | fn f1_2(...) {}
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
+ |
+LL | extern "C" fn f2_1(x: isize, ...) {}
+ | ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
+ |
+LL | extern "C" fn f2_2(...) {}
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
+ |
+LL | extern "C" fn f2_2(...) {}
+ | ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
+ |
+LL | extern "C" fn f2_3(..., x: isize) {}
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
+ |
+LL | extern "C" fn f2_3(..., x: isize) {}
+ | ^^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
- --> $DIR/variadic-ffi-semantic-restrictions.rs:8:28
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:23:26
|
-LL | extern "C" fn f2(x: isize, ...) {}
+LL | extern fn f3_1(x: isize, ...) {}
+ | ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
+ |
+LL | extern fn f3_2(...) {}
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
+ |
+LL | extern fn f3_2(...) {}
+ | ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
+ |
+LL | extern fn f3_3(..., x: isize) {}
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
+ |
+LL | extern fn f3_3(..., x: isize) {}
+ | ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:35:13
+ |
+LL | fn e_f1(...);
+ | ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:37:13
+ |
+LL | fn e_f2(..., x: isize);
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:44:23
+ |
+LL | fn i_f1(x: isize, ...) {}
+ | ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
+ |
+LL | fn i_f2(...) {}
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
+ |
+LL | fn i_f2(...) {}
+ | ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
+ |
+LL | fn i_f3(..., x: isize, ...) {}
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
+ |
+LL | fn i_f3(..., x: isize, ...) {}
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:49:28
+ |
+LL | fn i_f3(..., x: isize, ...) {}
| ^^^^
+error: `...` must be the last argument of a C-variadic function
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
+ |
+LL | fn i_f4(..., x: isize, ...) {}
+ | ^^^^
+
error: only foreign or `unsafe extern "C" functions may be C-variadic
- --> $DIR/variadic-ffi-semantic-restrictions.rs:11:24
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
|
-LL | extern fn f3(x: isize, ...) {}
- | ^^^^
+LL | fn i_f4(..., x: isize, ...) {}
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:53:28
+ |
+LL | fn i_f4(..., x: isize, ...) {}
+ | ^^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
- --> $DIR/variadic-ffi-semantic-restrictions.rs:17:21
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:60:23
|
-LL | fn f4(x: isize, ...) {}
- | ^^^^
+LL | fn t_f1(x: isize, ...) {}
+ | ^^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
- --> $DIR/variadic-ffi-semantic-restrictions.rs:22:21
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:62:23
+ |
+LL | fn t_f2(x: isize, ...);
+ | ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
+ |
+LL | fn t_f3(...) {}
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
+ |
+LL | fn t_f3(...) {}
+ | ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
+ |
+LL | fn t_f4(...);
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
+ |
+LL | fn t_f4(...);
+ | ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
+ |
+LL | fn t_f5(..., x: isize) {}
+ | ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
+ |
+LL | fn t_f5(..., x: isize) {}
+ | ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
-LL | fn f5(x: isize, ...) {}
- | ^^^^
+LL | fn t_f6(..., x: isize);
+ | ^^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
- --> $DIR/variadic-ffi-semantic-restrictions.rs:24:21
+ --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
-LL | fn f6(x: isize, ...);
- | ^^^^
+LL | fn t_f6(..., x: isize);
+ | ^^^^
-error: aborting due to 6 previous errors
+error: aborting due to 34 previous errors
fn main() {}
#[cfg(FALSE)]
-fn f1(x: isize, ...) {}
+fn f1_1(x: isize, ...) {}
#[cfg(FALSE)]
-extern "C" fn f2(x: isize, ...) {}
+fn f1_2(...) {}
#[cfg(FALSE)]
-extern fn f3(x: isize, ...) {}
+extern "C" fn f2_1(x: isize, ...) {}
+
+#[cfg(FALSE)]
+extern "C" fn f2_2(...) {}
+
+#[cfg(FALSE)]
+extern "C" fn f2_3(..., x: isize) {}
+
+#[cfg(FALSE)]
+extern fn f3_1(x: isize, ...) {}
+
+#[cfg(FALSE)]
+extern fn f3_2(...) {}
+
+#[cfg(FALSE)]
+extern fn f3_3(..., x: isize) {}
+
+#[cfg(FALSE)]
+extern {
+ fn e_f1(...);
+ fn e_f2(..., x: isize);
+}
struct X;
#[cfg(FALSE)]
impl X {
- fn f4(x: isize, ...) {}
+ fn i_f1(x: isize, ...) {}
+ fn i_f2(...) {}
+ fn i_f3(..., x: isize, ...) {}
+ fn i_f4(..., x: isize, ...) {}
}
#[cfg(FALSE)]
trait T {
- fn f5(x: isize, ...) {}
- fn f6(x: isize, ...);
+ fn t_f1(x: isize, ...) {}
+ fn t_f2(x: isize, ...);
+ fn t_f3(...) {}
+ fn t_f4(...);
+ fn t_f5(..., x: isize) {}
+ fn t_f6(..., x: isize);
}