mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
c-variadic: allow inherent methods to be c-variadic
This commit is contained in:
@@ -696,36 +696,38 @@ fn check_c_variadic_type(&self, fk: FnKind<'a>) {
|
||||
|
||||
match fn_ctxt {
|
||||
FnCtxt::Foreign => return,
|
||||
FnCtxt::Free => match sig.header.ext {
|
||||
Extern::Implicit(_) => {
|
||||
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
|
||||
span: variadic_param.span,
|
||||
unsafe_span: sig.safety_span(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => {
|
||||
if !matches!(symbol_unescaped, sym::C | sym::C_dash_unwind) {
|
||||
self.dcx().emit_err(errors::CVariadicBadExtern {
|
||||
span: variadic_param.span,
|
||||
abi: symbol_unescaped,
|
||||
extern_span: sig.extern_span(),
|
||||
});
|
||||
FnCtxt::Free | FnCtxt::Assoc(AssocCtxt::Impl { of_trait: false }) => {
|
||||
match sig.header.ext {
|
||||
Extern::Implicit(_) => {
|
||||
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
|
||||
span: variadic_param.span,
|
||||
unsafe_span: sig.safety_span(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => {
|
||||
if !matches!(symbol_unescaped, sym::C | sym::C_dash_unwind) {
|
||||
self.dcx().emit_err(errors::CVariadicBadExtern {
|
||||
span: variadic_param.span,
|
||||
abi: symbol_unescaped,
|
||||
extern_span: sig.extern_span(),
|
||||
});
|
||||
}
|
||||
|
||||
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
|
||||
span: variadic_param.span,
|
||||
unsafe_span: sig.safety_span(),
|
||||
});
|
||||
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
|
||||
span: variadic_param.span,
|
||||
unsafe_span: sig.safety_span(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Extern::None => {
|
||||
let err = errors::CVariadicNoExtern { span: variadic_param.span };
|
||||
self.dcx().emit_err(err);
|
||||
}
|
||||
}
|
||||
Extern::None => {
|
||||
let err = errors::CVariadicNoExtern { span: variadic_param.span };
|
||||
self.dcx().emit_err(err);
|
||||
}
|
||||
},
|
||||
}
|
||||
FnCtxt::Assoc(_) => {
|
||||
// For now, C variable argument lists are unsupported in associated functions.
|
||||
let err = errors::CVariadicAssociatedFunction { span: variadic_param.span };
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
//@ run-pass
|
||||
#![feature(c_variadic)]
|
||||
|
||||
#[repr(transparent)]
|
||||
struct S(i32);
|
||||
|
||||
impl S {
|
||||
unsafe extern "C" fn associated_function(mut ap: ...) -> i32 {
|
||||
unsafe { ap.arg() }
|
||||
}
|
||||
|
||||
unsafe extern "C" fn method_owned(self, mut ap: ...) -> i32 {
|
||||
self.0 + unsafe { ap.arg::<i32>() }
|
||||
}
|
||||
|
||||
unsafe extern "C" fn method_ref(&self, mut ap: ...) -> i32 {
|
||||
self.0 + unsafe { ap.arg::<i32>() }
|
||||
}
|
||||
|
||||
unsafe extern "C" fn method_mut(&mut self, mut ap: ...) -> i32 {
|
||||
self.0 + unsafe { ap.arg::<i32>() }
|
||||
}
|
||||
|
||||
unsafe extern "C" fn fat_pointer(self: Box<Self>, mut ap: ...) -> i32 {
|
||||
self.0 + unsafe { ap.arg::<i32>() }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
assert_eq!(S::associated_function(32), 32);
|
||||
assert_eq!(S(100).method_owned(32), 132);
|
||||
assert_eq!(S(100).method_ref(32), 132);
|
||||
assert_eq!(S(100).method_mut(32), 132);
|
||||
assert_eq!(S::fat_pointer(Box::new(S(100)), 32), 132);
|
||||
|
||||
type Method<T> = unsafe extern "C" fn(T, ...) -> i32;
|
||||
|
||||
assert_eq!((S::associated_function as unsafe extern "C" fn(...) -> i32)(32), 32);
|
||||
assert_eq!((S::method_owned as Method<_>)(S(100), 32), 132);
|
||||
assert_eq!((S::method_ref as Method<_>)(&S(100), 32), 132);
|
||||
assert_eq!((S::method_mut as Method<_>)(&mut S(100), 32), 132);
|
||||
assert_eq!((S::fat_pointer as Method<_>)(Box::new(S(100)), 32), 132);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,14 @@
|
||||
#![feature(c_variadic)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
|
||||
async unsafe extern "C" fn fn_cannot_be_async(x: isize, ...) {}
|
||||
//~^ ERROR functions cannot be both `async` and C-variadic
|
||||
//~| ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
|
||||
|
||||
struct S;
|
||||
|
||||
impl S {
|
||||
async unsafe extern "C" fn method_cannot_be_async(x: isize, ...) {}
|
||||
//~^ ERROR functions cannot be both `async` and C-variadic
|
||||
//~| ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
|
||||
}
|
||||
|
||||
@@ -1,19 +1,35 @@
|
||||
error: functions cannot be both `async` and C-variadic
|
||||
--> $DIR/not-async.rs:5:1
|
||||
|
|
||||
LL | async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
|
||||
| ^^^^^ `async` because of this ^^^ C-variadic because of this
|
||||
LL | async unsafe extern "C" fn fn_cannot_be_async(x: isize, ...) {}
|
||||
| ^^^^^ `async` because of this ^^^ C-variadic because of this
|
||||
|
||||
error: functions cannot be both `async` and C-variadic
|
||||
--> $DIR/not-async.rs:12:5
|
||||
|
|
||||
LL | async unsafe extern "C" fn method_cannot_be_async(x: isize, ...) {}
|
||||
| ^^^^^ `async` because of this ^^^ C-variadic because of this
|
||||
|
||||
error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
|
||||
--> $DIR/not-async.rs:5:59
|
||||
--> $DIR/not-async.rs:5:62
|
||||
|
|
||||
LL | async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
|
||||
| --------------------------------------------------------- ^^
|
||||
LL | async unsafe extern "C" fn fn_cannot_be_async(x: isize, ...) {}
|
||||
| ------------------------------------------------------------ ^^
|
||||
| |
|
||||
| opaque type defined here
|
||||
|
|
||||
= note: hidden type `{async fn body of cannot_be_async()}` captures lifetime `'_`
|
||||
= note: hidden type `{async fn body of fn_cannot_be_async()}` captures lifetime `'_`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
|
||||
--> $DIR/not-async.rs:12:70
|
||||
|
|
||||
LL | async unsafe extern "C" fn method_cannot_be_async(x: isize, ...) {}
|
||||
| ---------------------------------------------------------------- ^^
|
||||
| |
|
||||
| opaque type defined here
|
||||
|
|
||||
= note: hidden type `{async fn body of S::method_cannot_be_async()}` captures lifetime `'_`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0700`.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// For now C-variadic arguments in trait methods are rejected, though we aim to lift this
|
||||
// restriction in the future. In particular we need to think about the interaction with
|
||||
// `dyn Trait` and the `ReifyShim`s that it may generate for methods.
|
||||
#![feature(c_variadic)]
|
||||
#![crate_type = "lib"]
|
||||
struct S;
|
||||
|
||||
impl S {
|
||||
unsafe extern "C" fn associated_function(mut ap: ...) -> i32 {
|
||||
unsafe { ap.arg() }
|
||||
}
|
||||
|
||||
unsafe extern "C" fn method(&self, mut ap: ...) -> i32 {
|
||||
unsafe { ap.arg() }
|
||||
}
|
||||
}
|
||||
|
||||
trait T {
|
||||
unsafe extern "C" fn trait_associated_function(mut ap: ...) -> i32 {
|
||||
//~^ ERROR: associated functions cannot have a C variable argument list
|
||||
unsafe { ap.arg() }
|
||||
}
|
||||
|
||||
unsafe extern "C" fn trait_method(&self, mut ap: ...) -> i32 {
|
||||
//~^ ERROR: associated functions cannot have a C variable argument list
|
||||
unsafe { ap.arg() }
|
||||
}
|
||||
}
|
||||
|
||||
impl T for S {}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
assert_eq!(S::associated_function(32), 32);
|
||||
assert_eq!(S.method(32), 32);
|
||||
|
||||
assert_eq!(S::trait_associated_function(32), 32);
|
||||
assert_eq!(S.trait_method(32), 32);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
error: associated functions cannot have a C variable argument list
|
||||
--> $DIR/trait-method.rs:19:52
|
||||
|
|
||||
LL | unsafe extern "C" fn trait_associated_function(mut ap: ...) -> i32 {
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: associated functions cannot have a C variable argument list
|
||||
--> $DIR/trait-method.rs:24:46
|
||||
|
|
||||
LL | unsafe extern "C" fn trait_method(&self, mut ap: ...) -> i32 {
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
@@ -53,17 +53,17 @@ extern "C" fn f3_3(..., x: isize) {}
|
||||
|
||||
impl X {
|
||||
fn i_f1(x: isize, ...) {}
|
||||
//~^ ERROR associated functions cannot have a C variable argument list
|
||||
//~^ ERROR `...` is not supported for non-extern functions
|
||||
fn i_f2(...) {}
|
||||
//~^ ERROR associated functions cannot have a C variable argument list
|
||||
//~^ ERROR `...` is not supported for non-extern functions
|
||||
fn i_f3(..., x: isize, ...) {}
|
||||
//~^ ERROR associated functions cannot have a C variable argument list
|
||||
//~^ ERROR `...` is not supported for non-extern functions
|
||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||
fn i_f4(..., x: isize, ...) {}
|
||||
//~^ ERROR associated functions cannot have a C variable argument list
|
||||
//~^ ERROR `...` is not supported for non-extern functions
|
||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||
const fn i_f5(x: isize, ...) {}
|
||||
//~^ ERROR associated functions cannot have a C variable argument list
|
||||
//~^ ERROR `...` is not supported for non-extern functions
|
||||
//~| ERROR functions cannot be both `const` and C-variadic
|
||||
//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
||||
}
|
||||
|
||||
@@ -132,17 +132,21 @@ error: `...` must be the last argument of a C-variadic function
|
||||
LL | fn e_f2(..., x: isize);
|
||||
| ^^^
|
||||
|
||||
error: associated functions cannot have a C variable argument list
|
||||
error: `...` is not supported for non-extern functions
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:55:23
|
||||
|
|
||||
LL | fn i_f1(x: isize, ...) {}
|
||||
| ^^^
|
||||
|
|
||||
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||
|
||||
error: associated functions cannot have a C variable argument list
|
||||
error: `...` is not supported for non-extern functions
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:57:13
|
||||
|
|
||||
LL | fn i_f2(...) {}
|
||||
| ^^^
|
||||
|
|
||||
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
|
||||
@@ -150,11 +154,13 @@ error: `...` must be the last argument of a C-variadic function
|
||||
LL | fn i_f3(..., x: isize, ...) {}
|
||||
| ^^^
|
||||
|
||||
error: associated functions cannot have a C variable argument list
|
||||
error: `...` is not supported for non-extern functions
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:28
|
||||
|
|
||||
LL | fn i_f3(..., x: isize, ...) {}
|
||||
| ^^^
|
||||
|
|
||||
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
|
||||
@@ -162,11 +168,13 @@ error: `...` must be the last argument of a C-variadic function
|
||||
LL | fn i_f4(..., x: isize, ...) {}
|
||||
| ^^^
|
||||
|
||||
error: associated functions cannot have a C variable argument list
|
||||
error: `...` is not supported for non-extern functions
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:28
|
||||
|
|
||||
LL | fn i_f4(..., x: isize, ...) {}
|
||||
| ^^^
|
||||
|
|
||||
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||
|
||||
error: functions cannot be both `const` and C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:5
|
||||
@@ -176,11 +184,13 @@ LL | const fn i_f5(x: isize, ...) {}
|
||||
| |
|
||||
| `const` because of this
|
||||
|
||||
error: associated functions cannot have a C variable argument list
|
||||
error: `...` is not supported for non-extern functions
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:29
|
||||
|
|
||||
LL | const fn i_f5(x: isize, ...) {}
|
||||
| ^^^
|
||||
|
|
||||
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||
|
||||
error: associated functions cannot have a C variable argument list
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:72:23
|
||||
|
||||
Reference in New Issue
Block a user