Rollup merge of #150601 - folkertdev:c-variadic-const-eval, r=RalfJung
support c-variadic functions in `rustc_const_eval` tracking issue: https://github.com/rust-lang/rust/issues/44930 The new `GlobalAlloc::VaList` is used to create an `AllocId` that represents the variable argument list of a frame. The allocation itself does not store any data, all we need is the unique identifier. The actual variable argument list is stored in `Memory`, and keyed by the `AllocId`. The `Frame` also stores this `AllocId`, so that when a frame is popped, it can deallocate the variable arguments. At "runtime" a `VaList` value stores a pointer to the global allocation in its first bytes. The provenance on this pointer can be used to retrieve its `AllocId`, and the offset of the pointer is used to store the index of the next argument to read from the variable argument list. Miri does not yet support `va_arg`, but I think that can be done separetely? r? @RalfJung cc @workingjubilee
This commit is contained in:
commit
494c6da389
33 changed files with 1306 additions and 72 deletions
147
tests/ui/consts/const-eval/c-variadic-fail.rs
Normal file
147
tests/ui/consts/const-eval/c-variadic-fail.rs
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
//@ build-fail
|
||||
|
||||
#![feature(c_variadic)]
|
||||
#![feature(const_c_variadic)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_destruct)]
|
||||
#![feature(const_clone)]
|
||||
|
||||
use std::ffi::VaList;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
const unsafe extern "C" fn read_n<const N: usize>(mut ap: ...) {
|
||||
let mut i = N;
|
||||
while i > 0 {
|
||||
i -= 1;
|
||||
let _ = ap.arg::<i32>();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn read_too_many() {
|
||||
// None passed, none read.
|
||||
const { read_n::<0>() }
|
||||
|
||||
// One passed, none read. Ignoring arguments is fine.
|
||||
const { read_n::<0>(1) }
|
||||
|
||||
// None passed, one read.
|
||||
const { read_n::<1>() }
|
||||
//~^ ERROR more C-variadic arguments read than were passed
|
||||
|
||||
// One passed, two read.
|
||||
const { read_n::<2>(1) }
|
||||
//~^ ERROR more C-variadic arguments read than were passed
|
||||
}
|
||||
|
||||
const unsafe extern "C" fn read_as<T: core::ffi::VaArgSafe>(mut ap: ...) -> T {
|
||||
ap.arg::<T>()
|
||||
}
|
||||
|
||||
unsafe fn read_cast() {
|
||||
const { read_as::<i32>(1i32) };
|
||||
const { read_as::<u32>(1u32) };
|
||||
|
||||
const { read_as::<i32>(1i32, 2u64, 3.0f64) };
|
||||
const { read_as::<u32>(1u32, 2u64, 3.0f64) };
|
||||
|
||||
const { read_as::<i64>(1i64) };
|
||||
const { read_as::<u64>(1u64) };
|
||||
|
||||
const { read_as::<u32>(1i32) };
|
||||
//~^ ERROR va_arg type mismatch: requested `u32`, but next argument is `i32`
|
||||
|
||||
const { read_as::<i32>(1u32) };
|
||||
//~^ ERROR va_arg type mismatch: requested `i32`, but next argument is `u32`
|
||||
|
||||
const { read_as::<i32>(1u64) };
|
||||
//~^ ERROR va_arg type mismatch: requested `i32`, but next argument is `u64`
|
||||
|
||||
const { read_as::<f64>(1i32) };
|
||||
//~^ ERROR va_arg type mismatch: requested `f64`, but next argument is `i32`
|
||||
|
||||
const { read_as::<*const u8>(1i32) };
|
||||
//~^ ERROR va_arg type mismatch: requested `*const u8`, but next argument is `i32`
|
||||
}
|
||||
|
||||
fn use_after_free() {
|
||||
const unsafe extern "C" fn helper(ap: ...) -> [u8; size_of::<VaList>()] {
|
||||
unsafe { std::mem::transmute(ap) }
|
||||
}
|
||||
|
||||
const {
|
||||
unsafe {
|
||||
let ap = helper(1, 2, 3);
|
||||
let mut ap = std::mem::transmute::<_, VaList>(ap);
|
||||
ap.arg::<i32>();
|
||||
//~^ ERROR memory access failed: ALLOC0 has been freed, so this pointer is dangling [E0080]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn manual_copy_drop() {
|
||||
const unsafe extern "C" fn helper(ap: ...) {
|
||||
// A copy created using Clone is valid, and can be used to read arguments.
|
||||
let mut copy = ap.clone();
|
||||
assert!(copy.arg::<i32>() == 1i32);
|
||||
|
||||
let mut copy: VaList = unsafe { std::mem::transmute_copy(&ap) };
|
||||
|
||||
// Using the copy is actually fine.
|
||||
let _ = copy.arg::<i32>();
|
||||
drop(copy);
|
||||
|
||||
// But then using the original is UB.
|
||||
drop(ap);
|
||||
}
|
||||
|
||||
const { unsafe { helper(1, 2, 3) } };
|
||||
//~^ ERROR using ALLOC0 as variable argument list pointer but it does not point to a variable argument list [E0080]
|
||||
}
|
||||
|
||||
fn manual_copy_forget() {
|
||||
const unsafe extern "C" fn helper(ap: ...) {
|
||||
let mut copy: VaList = unsafe { std::mem::transmute_copy(&ap) };
|
||||
|
||||
// Using the copy is actually fine.
|
||||
let _ = copy.arg::<i32>();
|
||||
std::mem::forget(copy);
|
||||
|
||||
// The read (via `copy`) deallocated the original allocation.
|
||||
drop(ap);
|
||||
}
|
||||
|
||||
const { unsafe { helper(1, 2, 3) } };
|
||||
//~^ ERROR using ALLOC0 as variable argument list pointer but it does not point to a variable argument list [E0080]
|
||||
}
|
||||
|
||||
fn manual_copy_read() {
|
||||
const unsafe extern "C" fn helper(mut ap: ...) {
|
||||
let mut copy: VaList = unsafe { std::mem::transmute_copy(&ap) };
|
||||
|
||||
// Reading from `ap` after reading from `copy` is UB.
|
||||
let _ = copy.arg::<i32>();
|
||||
let _ = ap.arg::<i32>();
|
||||
}
|
||||
|
||||
const { unsafe { helper(1, 2, 3) } };
|
||||
//~^ ERROR using ALLOC0 as variable argument list pointer but it does not point to a variable argument list [E0080]
|
||||
}
|
||||
|
||||
fn drop_of_invalid() {
|
||||
const {
|
||||
let mut invalid: MaybeUninit<VaList> = MaybeUninit::zeroed();
|
||||
let ap = unsafe { invalid.assume_init() };
|
||||
}
|
||||
//~^ ERROR pointer not dereferenceable: pointer must point to some allocation, but got null pointer [E0080]
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
read_too_many();
|
||||
read_cast();
|
||||
manual_copy_read();
|
||||
manual_copy_drop();
|
||||
manual_copy_forget();
|
||||
drop_of_invalid();
|
||||
}
|
||||
}
|
||||
355
tests/ui/consts/const-eval/c-variadic-fail.stderr
Normal file
355
tests/ui/consts/const-eval/c-variadic-fail.stderr
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
error[E0080]: more C-variadic arguments read than were passed
|
||||
--> $DIR/c-variadic-fail.rs:28:13
|
||||
|
|
||||
LL | const { read_n::<1>() }
|
||||
| ^^^^^^^^^^^^^ evaluation of `read_too_many::{constant#2}` failed inside this call
|
||||
|
|
||||
note: inside `read_n::<1>`
|
||||
--> $DIR/c-variadic-fail.rs:16:17
|
||||
|
|
||||
LL | let _ = ap.arg::<i32>();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: inside `VaList::<'_>::arg::<i32>`
|
||||
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:28:5
|
||||
|
|
||||
LL | const { read_n::<1>() }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:28:5
|
||||
|
|
||||
LL | const { read_n::<1>() }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0080]: more C-variadic arguments read than were passed
|
||||
--> $DIR/c-variadic-fail.rs:32:13
|
||||
|
|
||||
LL | const { read_n::<2>(1) }
|
||||
| ^^^^^^^^^^^^^^ evaluation of `read_too_many::{constant#3}` failed inside this call
|
||||
|
|
||||
note: inside `read_n::<2>`
|
||||
--> $DIR/c-variadic-fail.rs:16:17
|
||||
|
|
||||
LL | let _ = ap.arg::<i32>();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: inside `VaList::<'_>::arg::<i32>`
|
||||
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:32:5
|
||||
|
|
||||
LL | const { read_n::<2>(1) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:32:5
|
||||
|
|
||||
LL | const { read_n::<2>(1) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0080]: va_arg type mismatch: requested `u32`, but next argument is `i32`
|
||||
--> $DIR/c-variadic-fail.rs:50:13
|
||||
|
|
||||
LL | const { read_as::<u32>(1i32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^ evaluation of `read_cast::{constant#6}` failed inside this call
|
||||
|
|
||||
note: inside `read_as::<u32>`
|
||||
--> $DIR/c-variadic-fail.rs:37:5
|
||||
|
|
||||
LL | ap.arg::<T>()
|
||||
| ^^^^^^^^^^^^^
|
||||
note: inside `VaList::<'_>::arg::<u32>`
|
||||
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:50:5
|
||||
|
|
||||
LL | const { read_as::<u32>(1i32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:50:5
|
||||
|
|
||||
LL | const { read_as::<u32>(1i32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0080]: va_arg type mismatch: requested `i32`, but next argument is `u32`
|
||||
--> $DIR/c-variadic-fail.rs:53:13
|
||||
|
|
||||
LL | const { read_as::<i32>(1u32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^ evaluation of `read_cast::{constant#7}` failed inside this call
|
||||
|
|
||||
note: inside `read_as::<i32>`
|
||||
--> $DIR/c-variadic-fail.rs:37:5
|
||||
|
|
||||
LL | ap.arg::<T>()
|
||||
| ^^^^^^^^^^^^^
|
||||
note: inside `VaList::<'_>::arg::<i32>`
|
||||
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:53:5
|
||||
|
|
||||
LL | const { read_as::<i32>(1u32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:53:5
|
||||
|
|
||||
LL | const { read_as::<i32>(1u32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0080]: va_arg type mismatch: requested `i32`, but next argument is `u64`
|
||||
--> $DIR/c-variadic-fail.rs:56:13
|
||||
|
|
||||
LL | const { read_as::<i32>(1u64) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^ evaluation of `read_cast::{constant#8}` failed inside this call
|
||||
|
|
||||
note: inside `read_as::<i32>`
|
||||
--> $DIR/c-variadic-fail.rs:37:5
|
||||
|
|
||||
LL | ap.arg::<T>()
|
||||
| ^^^^^^^^^^^^^
|
||||
note: inside `VaList::<'_>::arg::<i32>`
|
||||
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:56:5
|
||||
|
|
||||
LL | const { read_as::<i32>(1u64) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:56:5
|
||||
|
|
||||
LL | const { read_as::<i32>(1u64) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0080]: va_arg type mismatch: requested `f64`, but next argument is `i32`
|
||||
--> $DIR/c-variadic-fail.rs:59:13
|
||||
|
|
||||
LL | const { read_as::<f64>(1i32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^ evaluation of `read_cast::{constant#9}` failed inside this call
|
||||
|
|
||||
note: inside `read_as::<f64>`
|
||||
--> $DIR/c-variadic-fail.rs:37:5
|
||||
|
|
||||
LL | ap.arg::<T>()
|
||||
| ^^^^^^^^^^^^^
|
||||
note: inside `VaList::<'_>::arg::<f64>`
|
||||
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:59:5
|
||||
|
|
||||
LL | const { read_as::<f64>(1i32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:59:5
|
||||
|
|
||||
LL | const { read_as::<f64>(1i32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0080]: va_arg type mismatch: requested `*const u8`, but next argument is `i32`
|
||||
--> $DIR/c-variadic-fail.rs:62:13
|
||||
|
|
||||
LL | const { read_as::<*const u8>(1i32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `read_cast::{constant#10}` failed inside this call
|
||||
|
|
||||
note: inside `read_as::<*const u8>`
|
||||
--> $DIR/c-variadic-fail.rs:37:5
|
||||
|
|
||||
LL | ap.arg::<T>()
|
||||
| ^^^^^^^^^^^^^
|
||||
note: inside `VaList::<'_>::arg::<*const u8>`
|
||||
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:62:5
|
||||
|
|
||||
LL | const { read_as::<*const u8>(1i32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:62:5
|
||||
|
|
||||
LL | const { read_as::<*const u8>(1i32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0080]: memory access failed: ALLOC0 has been freed, so this pointer is dangling
|
||||
--> $DIR/c-variadic-fail.rs:75:13
|
||||
|
|
||||
LL | ap.arg::<i32>();
|
||||
| ^^^^^^^^^^^^^^^ evaluation of `use_after_free::{constant#0}` failed inside this call
|
||||
|
|
||||
note: inside `VaList::<'_>::arg::<i32>`
|
||||
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:71:5
|
||||
|
|
||||
LL | / const {
|
||||
LL | | unsafe {
|
||||
LL | | let ap = helper(1, 2, 3);
|
||||
LL | | let mut ap = std::mem::transmute::<_, VaList>(ap);
|
||||
... |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:71:5
|
||||
|
|
||||
LL | / const {
|
||||
LL | | unsafe {
|
||||
LL | | let ap = helper(1, 2, 3);
|
||||
LL | | let mut ap = std::mem::transmute::<_, VaList>(ap);
|
||||
... |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0080]: using ALLOC1 as variable argument list pointer but it does not point to a variable argument list
|
||||
--> $DIR/c-variadic-fail.rs:97:22
|
||||
|
|
||||
LL | const { unsafe { helper(1, 2, 3) } };
|
||||
| ^^^^^^^^^^^^^^^ evaluation of `manual_copy_drop::{constant#0}` failed inside this call
|
||||
|
|
||||
note: inside `manual_copy_drop::helper`
|
||||
--> $DIR/c-variadic-fail.rs:94:9
|
||||
|
|
||||
LL | drop(ap);
|
||||
| ^^^^^^^^
|
||||
note: inside `std::mem::drop::<VaList<'_>>`
|
||||
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
||||
note: inside `drop_in_place::<VaList<'_>> - shim(Some(VaList<'_>))`
|
||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
note: inside `<VaList<'_> as Drop>::drop`
|
||||
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:97:5
|
||||
|
|
||||
LL | const { unsafe { helper(1, 2, 3) } };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:97:5
|
||||
|
|
||||
LL | const { unsafe { helper(1, 2, 3) } };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0080]: using ALLOC2 as variable argument list pointer but it does not point to a variable argument list
|
||||
--> $DIR/c-variadic-fail.rs:113:22
|
||||
|
|
||||
LL | const { unsafe { helper(1, 2, 3) } };
|
||||
| ^^^^^^^^^^^^^^^ evaluation of `manual_copy_forget::{constant#0}` failed inside this call
|
||||
|
|
||||
note: inside `manual_copy_forget::helper`
|
||||
--> $DIR/c-variadic-fail.rs:110:9
|
||||
|
|
||||
LL | drop(ap);
|
||||
| ^^^^^^^^
|
||||
note: inside `std::mem::drop::<VaList<'_>>`
|
||||
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
||||
note: inside `drop_in_place::<VaList<'_>> - shim(Some(VaList<'_>))`
|
||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
note: inside `<VaList<'_> as Drop>::drop`
|
||||
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:113:5
|
||||
|
|
||||
LL | const { unsafe { helper(1, 2, 3) } };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:113:5
|
||||
|
|
||||
LL | const { unsafe { helper(1, 2, 3) } };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0080]: using ALLOC3 as variable argument list pointer but it does not point to a variable argument list
|
||||
--> $DIR/c-variadic-fail.rs:126:22
|
||||
|
|
||||
LL | const { unsafe { helper(1, 2, 3) } };
|
||||
| ^^^^^^^^^^^^^^^ evaluation of `manual_copy_read::{constant#0}` failed inside this call
|
||||
|
|
||||
note: inside `manual_copy_read::helper`
|
||||
--> $DIR/c-variadic-fail.rs:123:17
|
||||
|
|
||||
LL | let _ = ap.arg::<i32>();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: inside `VaList::<'_>::arg::<i32>`
|
||||
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:126:5
|
||||
|
|
||||
LL | const { unsafe { helper(1, 2, 3) } };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:126:5
|
||||
|
|
||||
LL | const { unsafe { helper(1, 2, 3) } };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0080]: pointer not dereferenceable: pointer must point to some allocation, but got null pointer
|
||||
--> $DIR/c-variadic-fail.rs:134:5
|
||||
|
|
||||
LL | }
|
||||
| ^ evaluation of `drop_of_invalid::{constant#0}` failed inside this call
|
||||
|
|
||||
note: inside `drop_in_place::<VaList<'_>> - shim(Some(VaList<'_>))`
|
||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
note: inside `<VaList<'_> as Drop>::drop`
|
||||
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:131:5
|
||||
|
|
||||
LL | / const {
|
||||
LL | | let mut invalid: MaybeUninit<VaList> = MaybeUninit::zeroed();
|
||||
LL | | let ap = unsafe { invalid.assume_init() };
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/c-variadic-fail.rs:131:5
|
||||
|
|
||||
LL | / const {
|
||||
LL | | let mut invalid: MaybeUninit<VaList> = MaybeUninit::zeroed();
|
||||
LL | | let ap = unsafe { invalid.assume_init() };
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
155
tests/ui/consts/const-eval/c-variadic.rs
Normal file
155
tests/ui/consts/const-eval/c-variadic.rs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
//@ edition: 2021
|
||||
//@ run-pass
|
||||
//@ ignore-backends: gcc
|
||||
|
||||
#![feature(c_variadic)]
|
||||
#![feature(const_c_variadic)]
|
||||
#![feature(const_destruct)]
|
||||
#![feature(const_cmp)]
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
use std::ffi::*;
|
||||
|
||||
fn ignores_arguments() {
|
||||
const unsafe extern "C" fn variadic(_: ...) {}
|
||||
|
||||
const {
|
||||
unsafe { variadic() };
|
||||
unsafe { variadic(1, 2, 3) };
|
||||
}
|
||||
}
|
||||
|
||||
fn echo() {
|
||||
const unsafe extern "C" fn variadic(mut ap: ...) -> i32 {
|
||||
ap.arg()
|
||||
}
|
||||
|
||||
assert_eq!(unsafe { variadic(1) }, 1);
|
||||
assert_eq!(unsafe { variadic(3, 2, 1) }, 3);
|
||||
|
||||
const {
|
||||
assert!(unsafe { variadic(1) } == 1);
|
||||
assert!(unsafe { variadic(3, 2, 1) } == 3);
|
||||
}
|
||||
}
|
||||
|
||||
fn forward_by_val() {
|
||||
const unsafe fn helper(mut ap: VaList) -> i32 {
|
||||
ap.arg()
|
||||
}
|
||||
|
||||
const unsafe extern "C" fn variadic(ap: ...) -> i32 {
|
||||
helper(ap)
|
||||
}
|
||||
|
||||
assert_eq!(unsafe { variadic(1) }, 1);
|
||||
assert_eq!(unsafe { variadic(3, 2, 1) }, 3);
|
||||
|
||||
const {
|
||||
assert!(unsafe { variadic(1) } == 1);
|
||||
assert!(unsafe { variadic(3, 2, 1) } == 3);
|
||||
}
|
||||
}
|
||||
|
||||
fn forward_by_ref() {
|
||||
const unsafe fn helper(ap: &mut VaList) -> i32 {
|
||||
ap.arg()
|
||||
}
|
||||
|
||||
const unsafe extern "C" fn variadic(mut ap: ...) -> i32 {
|
||||
helper(&mut ap)
|
||||
}
|
||||
|
||||
assert_eq!(unsafe { variadic(1) }, 1);
|
||||
assert_eq!(unsafe { variadic(3, 2, 1) }, 3);
|
||||
|
||||
const {
|
||||
assert!(unsafe { variadic(1) } == 1);
|
||||
assert!(unsafe { variadic(3, 2, 1) } == 3);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(improper_ctypes_definitions)]
|
||||
fn nested() {
|
||||
const unsafe fn helper(mut ap1: VaList, mut ap2: VaList) -> (i32, i32) {
|
||||
(ap1.arg(), ap2.arg())
|
||||
}
|
||||
|
||||
const unsafe extern "C" fn variadic2(ap1: VaList, ap2: ...) -> (i32, i32) {
|
||||
helper(ap1, ap2)
|
||||
}
|
||||
|
||||
const unsafe extern "C" fn variadic1(ap1: ...) -> (i32, i32) {
|
||||
variadic2(ap1, 2, 2)
|
||||
}
|
||||
|
||||
assert_eq!(unsafe { variadic1(1) }, (1, 2));
|
||||
|
||||
const {
|
||||
let (a, b) = unsafe { variadic1(1, 1) };
|
||||
|
||||
assert!(a != 2);
|
||||
assert!(a == 1);
|
||||
assert!(b != 1);
|
||||
assert!(b == 2);
|
||||
}
|
||||
}
|
||||
|
||||
fn various_types() {
|
||||
const unsafe extern "C" fn check_list_2(mut ap: ...) {
|
||||
macro_rules! continue_if {
|
||||
($cond:expr) => {
|
||||
if !($cond) {
|
||||
panic!();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const unsafe fn compare_c_str(ptr: *const c_char, val: &str) -> bool {
|
||||
match CStr::from_ptr(ptr).to_str() {
|
||||
Ok(cstr) => cstr == val,
|
||||
Err(_) => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
continue_if!(ap.arg::<c_double>().floor() == 3.14f64.floor());
|
||||
continue_if!(ap.arg::<c_long>() == 12);
|
||||
continue_if!(ap.arg::<c_int>() == 'a' as c_int);
|
||||
continue_if!(ap.arg::<c_double>().floor() == 6.18f64.floor());
|
||||
continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Hello"));
|
||||
continue_if!(ap.arg::<c_int>() == 42);
|
||||
continue_if!(compare_c_str(ap.arg::<*const c_char>(), "World"));
|
||||
}
|
||||
|
||||
unsafe {
|
||||
check_list_2(
|
||||
3.14 as c_double,
|
||||
12 as c_long,
|
||||
b'a' as c_int,
|
||||
6.28 as c_double,
|
||||
c"Hello".as_ptr(),
|
||||
42 as c_int,
|
||||
c"World".as_ptr(),
|
||||
);
|
||||
const {
|
||||
check_list_2(
|
||||
3.14 as c_double,
|
||||
12 as c_long,
|
||||
b'a' as c_int,
|
||||
6.28 as c_double,
|
||||
c"Hello".as_ptr(),
|
||||
42 as c_int,
|
||||
c"World".as_ptr(),
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
ignores_arguments();
|
||||
echo();
|
||||
forward_by_val();
|
||||
forward_by_ref();
|
||||
nested();
|
||||
various_types();
|
||||
}
|
||||
11
tests/ui/feature-gates/feature-gate-const-c-variadic.rs
Normal file
11
tests/ui/feature-gates/feature-gate-const-c-variadic.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#![feature(c_variadic)]
|
||||
|
||||
fn main() {
|
||||
const unsafe extern "C" fn foo(ap: ...) {
|
||||
//~^ ERROR c-variadic const function definitions are unstable
|
||||
core::mem::forget(ap);
|
||||
}
|
||||
|
||||
const { unsafe { foo() } }
|
||||
//~^ ERROR calling const c-variadic functions is unstable in constants
|
||||
}
|
||||
24
tests/ui/feature-gates/feature-gate-const-c-variadic.stderr
Normal file
24
tests/ui/feature-gates/feature-gate-const-c-variadic.stderr
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
error[E0658]: c-variadic const function definitions are unstable
|
||||
--> $DIR/feature-gate-const-c-variadic.rs:4:5
|
||||
|
|
||||
LL | const unsafe extern "C" fn foo(ap: ...) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #151787 <https://github.com/rust-lang/rust/issues/151787> for more information
|
||||
= help: add `#![feature(const_c_variadic)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0015]: calling const c-variadic functions is unstable in constants
|
||||
--> $DIR/feature-gate-const-c-variadic.rs:9:22
|
||||
|
|
||||
LL | const { unsafe { foo() } }
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #151787 <https://github.com/rust-lang/rust/issues/151787> for more information
|
||||
= help: add `#![feature(const_c_variadic)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0015, E0658.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
|
|
@ -31,18 +31,18 @@ extern "C" fn f3_3(_: ..., x: isize) {}
|
|||
//~^ ERROR `...` must be the last argument of a C-variadic function
|
||||
|
||||
const unsafe extern "C" fn f4_1(x: isize, _: ...) {}
|
||||
//~^ ERROR functions cannot be both `const` and C-variadic
|
||||
//~| ERROR destructor of `VaList<'_>` cannot be evaluated at compile-time
|
||||
//~^ ERROR destructor of `VaList<'_>` cannot be evaluated at compile-time
|
||||
//~| ERROR c-variadic const function definitions are unstable
|
||||
|
||||
const extern "C" fn f4_2(x: isize, _: ...) {}
|
||||
//~^ ERROR functions cannot be both `const` and C-variadic
|
||||
//~| ERROR functions with a C variable argument list must be unsafe
|
||||
//~^ ERROR functions with a C variable argument list must be unsafe
|
||||
//~| ERROR destructor of `VaList<'_>` cannot be evaluated at compile-time
|
||||
//~| ERROR c-variadic const function definitions are unstable
|
||||
|
||||
const extern "C" fn f4_3(_: ..., x: isize, _: ...) {}
|
||||
//~^ ERROR functions cannot be both `const` and C-variadic
|
||||
//~| ERROR functions with a C variable argument list must be unsafe
|
||||
//~^ ERROR functions with a C variable argument list must be unsafe
|
||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||
//~| ERROR c-variadic const function definitions are unstable
|
||||
|
||||
extern "C" {
|
||||
fn e_f2(..., x: isize);
|
||||
|
|
@ -64,8 +64,8 @@ impl X {
|
|||
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||
const fn i_f5(x: isize, _: ...) {}
|
||||
//~^ ERROR `...` is not supported for non-extern functions
|
||||
//~| ERROR functions cannot be both `const` and C-variadic
|
||||
//~| ERROR destructor of `VaList<'_>` cannot be evaluated at compile-time
|
||||
//~| ERROR c-variadic const function definitions are unstable
|
||||
}
|
||||
|
||||
trait T {
|
||||
|
|
|
|||
|
|
@ -80,17 +80,25 @@ error: `...` must be the last argument of a C-variadic function
|
|||
LL | extern "C" fn f3_3(_: ..., x: isize) {}
|
||||
| ^^^^^^
|
||||
|
||||
error: functions cannot be both `const` and C-variadic
|
||||
error[E0658]: c-variadic const function definitions are unstable
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:33:1
|
||||
|
|
||||
LL | const unsafe extern "C" fn f4_1(x: isize, _: ...) {}
|
||||
| ^^^^^ `const` because of this ^^^^^^ C-variadic because of this
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #151787 <https://github.com/rust-lang/rust/issues/151787> for more information
|
||||
= help: add `#![feature(const_c_variadic)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: functions cannot be both `const` and C-variadic
|
||||
error[E0658]: c-variadic const function definitions are unstable
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:1
|
||||
|
|
||||
LL | const extern "C" fn f4_2(x: isize, _: ...) {}
|
||||
| ^^^^^ `const` because of this ^^^^^^ C-variadic because of this
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #151787 <https://github.com/rust-lang/rust/issues/151787> for more information
|
||||
= help: add `#![feature(const_c_variadic)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:36
|
||||
|
|
@ -109,11 +117,15 @@ error: `...` must be the last argument of a C-variadic function
|
|||
LL | const extern "C" fn f4_3(_: ..., x: isize, _: ...) {}
|
||||
| ^^^^^^
|
||||
|
||||
error: functions cannot be both `const` and C-variadic
|
||||
error[E0658]: c-variadic const function definitions are unstable
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:1
|
||||
|
|
||||
LL | const extern "C" fn f4_3(_: ..., x: isize, _: ...) {}
|
||||
| ^^^^^ `const` because of this ^^^^^^ C-variadic because of this
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #151787 <https://github.com/rust-lang/rust/issues/151787> for more information
|
||||
= help: add `#![feature(const_c_variadic)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:44
|
||||
|
|
@ -176,13 +188,15 @@ 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
|
||||
error[E0658]: c-variadic const function definitions are unstable
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:5
|
||||
|
|
||||
LL | const fn i_f5(x: isize, _: ...) {}
|
||||
| ^^^^^ ^^^^^^ C-variadic because of this
|
||||
| |
|
||||
| `const` because of this
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #151787 <https://github.com/rust-lang/rust/issues/151787> for more information
|
||||
= help: add `#![feature(const_c_variadic)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: `...` is not supported for non-extern functions
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:29
|
||||
|
|
@ -243,6 +257,10 @@ LL | const unsafe extern "C" fn f4_1(x: isize, _: ...) {}
|
|||
| ^ - value is dropped here
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
|
||||
= note: see issue #133214 <https://github.com/rust-lang/rust/issues/133214> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0493]: destructor of `VaList<'_>` cannot be evaluated at compile-time
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:36
|
||||
|
|
@ -251,6 +269,10 @@ LL | const extern "C" fn f4_2(x: isize, _: ...) {}
|
|||
| ^ - value is dropped here
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
|
||||
= note: see issue #133214 <https://github.com/rust-lang/rust/issues/133214> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0493]: destructor of `VaList<'_>` cannot be evaluated at compile-time
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:29
|
||||
|
|
@ -259,7 +281,12 @@ LL | const fn i_f5(x: isize, _: ...) {}
|
|||
| ^ - value is dropped here
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
|
||||
= note: see issue #133214 <https://github.com/rust-lang/rust/issues/133214> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 33 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0493`.
|
||||
Some errors have detailed explanations: E0493, E0658.
|
||||
For more information about an error, try `rustc --explain E0493`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue