diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs index c5ecf43046c74..187e4b90656ab 100644 --- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs @@ -36,10 +36,10 @@ pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes { vtable_byte_offset: u64, typeid: Self::Metadata, ) -> Self::Value; - /// Trait method used to inject `va_start` on the "spoofed" `VaListImpl` in + /// Trait method used to inject `va_start` on the "spoofed" `VaList` in /// Rust defined C-variadic functions. fn va_start(&mut self, val: Self::Value) -> Self::Value; - /// Trait method used to inject `va_end` on the "spoofed" `VaListImpl` before + /// Trait method used to inject `va_end` on the "spoofed" `VaList` before /// Rust defined C-variadic functions return. fn va_end(&mut self, val: Self::Value) -> Self::Value; } diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 1356ca217c9a2..f1b928da7ef3c 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -28,7 +28,7 @@ pub mod c_str; issue = "44930", reason = "the `c_variadic` feature has not been properly tested on all supported platforms" )] -pub use self::va_list::{VaArgSafe, VaList, VaListImpl}; +pub use self::va_list::{VaArgSafe, VaList}; #[unstable( feature = "c_variadic", diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs index 3c9587d383e30..e3668de15c46d 100644 --- a/library/core/src/ffi/va_list.rs +++ b/library/core/src/ffi/va_list.rs @@ -4,15 +4,33 @@ #[cfg(not(target_arch = "xtensa"))] use crate::ffi::c_void; -#[allow(unused_imports)] use crate::fmt; -use crate::intrinsics::{va_arg, va_copy, va_end}; -use crate::marker::{PhantomData, PhantomInvariantLifetime}; -use crate::ops::{Deref, DerefMut}; +use crate::intrinsics::{va_arg, va_copy}; +use crate::marker::PhantomCovariantLifetime; -// The name is WIP, using `VaListImpl` for now. +// There are currently three flavors of how a C `va_list` is implemented for +// targets that Rust supports: // -// Most targets explicitly specify the layout of `va_list`, this layout is matched here. +// - `va_list` is an opaque pointer +// - `va_list` is a struct +// - `va_list` is a single-element array, containing a struct +// +// The opaque pointer approach is the simplest to implement: the pointer just +// points to an array of arguments on the caller's stack. +// +// The struct and single-element array variants are more complex, but +// potentially more efficient because the additional state makes it +// possible to pass variadic arguments via registers. +// +// The Rust `VaList` type is ABI-compatible with the C `va_list`. +// The struct and pointer cases straightforwardly map to their rust equivalents, +// but the single-element array case is special: in C, this type is subject to +// array-to-pointer decay. +// +// The `#[rustc_pass_indirectly_in_non_rustic_abis]` attribute is used to match +// the pointer decay behavior in Rust. This attribute ensures that the compiler +// uses the correct ABI for functions like +// `extern "C" fn takes_va_list(va: VaList<'_>)` by passing `va` indirectly. crate::cfg_select! { all( target_arch = "aarch64", @@ -20,73 +38,89 @@ crate::cfg_select! { not(target_os = "uefi"), not(windows), ) => { - /// AArch64 ABI implementation of a `va_list`. See the - /// [AArch64 Procedure Call Standard] for more details. + /// AArch64 ABI implementation of a `va_list`. + /// + /// See the [AArch64 Procedure Call Standard] for more details. /// /// [AArch64 Procedure Call Standard]: /// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf #[repr(C)] #[derive(Debug)] - #[lang = "va_list"] - pub struct VaListImpl<'f> { - stack: *mut c_void, - gr_top: *mut c_void, - vr_top: *mut c_void, + struct VaListInner { + stack: *const c_void, + gr_top: *const c_void, + vr_top: *const c_void, gr_offs: i32, vr_offs: i32, - _marker: PhantomInvariantLifetime<'f>, } } all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)) => { /// PowerPC ABI implementation of a `va_list`. + /// + /// See the [LLVM source] and [GCC header] for more details. + /// + /// [LLVM source]: + /// https://github.com/llvm/llvm-project/blob/af9a4263a1a209953a1d339ef781a954e31268ff/llvm/lib/Target/PowerPC/PPCISelLowering.cpp#L4089-L4111 + /// [GCC header]: https://web.mit.edu/darwin/src/modules/gcc/gcc/ginclude/va-ppc.h #[repr(C)] #[derive(Debug)] - #[lang = "va_list"] - pub struct VaListImpl<'f> { + #[rustc_pass_indirectly_in_non_rustic_abis] + struct VaListInner { gpr: u8, fpr: u8, reserved: u16, - overflow_arg_area: *mut c_void, - reg_save_area: *mut c_void, - _marker: PhantomInvariantLifetime<'f>, + overflow_arg_area: *const c_void, + reg_save_area: *const c_void, } } target_arch = "s390x" => { /// s390x ABI implementation of a `va_list`. + /// + /// See the [S/390x ELF Application Binary Interface Supplement] for more details. + /// + /// [S/390x ELF Application Binary Interface Supplement]: + /// https://docs.google.com/gview?embedded=true&url=https://github.com/IBM/s390x-abi/releases/download/v1.7/lzsabi_s390x.pdf #[repr(C)] #[derive(Debug)] - #[lang = "va_list"] - pub struct VaListImpl<'f> { + #[rustc_pass_indirectly_in_non_rustic_abis] + struct VaListInner { gpr: i64, fpr: i64, - overflow_arg_area: *mut c_void, - reg_save_area: *mut c_void, - _marker: PhantomInvariantLifetime<'f>, + overflow_arg_area: *const c_void, + reg_save_area: *const c_void, } } all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)) => { - /// x86_64 ABI implementation of a `va_list`. + /// x86_64 System V ABI implementation of a `va_list`. + /// + /// See the [System V AMD64 ABI] for more details. + /// + /// [System V AMD64 ABI]: + /// https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf #[repr(C)] #[derive(Debug)] - #[lang = "va_list"] - pub struct VaListImpl<'f> { + #[rustc_pass_indirectly_in_non_rustic_abis] + struct VaListInner { gp_offset: i32, fp_offset: i32, - overflow_arg_area: *mut c_void, - reg_save_area: *mut c_void, - _marker: PhantomInvariantLifetime<'f>, + overflow_arg_area: *const c_void, + reg_save_area: *const c_void, } } target_arch = "xtensa" => { /// Xtensa ABI implementation of a `va_list`. + /// + /// See the [LLVM source] for more details. + /// + /// [LLVM source]: + /// https://github.com/llvm/llvm-project/blob/af9a4263a1a209953a1d339ef781a954e31268ff/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp#L1211-L1215 #[repr(C)] #[derive(Debug)] - #[lang = "va_list"] - pub struct VaListImpl<'f> { - stk: *mut i32, - reg: *mut i32, + #[rustc_pass_indirectly_in_non_rustic_abis] + struct VaListInner { + stk: *const i32, + reg: *const i32, ndx: i32, - _marker: PhantomInvariantLifetime<'f>, } } @@ -94,95 +128,34 @@ crate::cfg_select! { // // - apple aarch64 (see https://github.com/rust-lang/rust/pull/56599) // - windows + // - powerpc64 & powerpc64le // - uefi - // - any other target for which we don't specify the `VaListImpl` above + // - any other target for which we don't specify the `VaListInner` above // // In this implementation the `va_list` type is just an alias for an opaque pointer. // That pointer is probably just the next variadic argument on the caller's stack. _ => { /// Basic implementation of a `va_list`. #[repr(transparent)] - #[lang = "va_list"] - pub struct VaListImpl<'f> { - ptr: *mut c_void, - - // Invariant over `'f`, so each `VaListImpl<'f>` object is tied to - // the region of the function it's defined in - _marker: PhantomInvariantLifetime<'f>, - } - - impl<'f> fmt::Debug for VaListImpl<'f> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "va_list* {:p}", self.ptr) - } - } - } -} - -crate::cfg_select! { - all( - any( - target_arch = "aarch64", - target_arch = "powerpc", - target_arch = "s390x", - target_arch = "x86_64" - ), - not(target_arch = "xtensa"), - any(not(target_arch = "aarch64"), not(target_vendor = "apple")), - not(target_family = "wasm"), - not(target_os = "uefi"), - not(windows), - ) => { - /// A wrapper for a `va_list` - #[repr(transparent)] - #[derive(Debug)] - pub struct VaList<'a, 'f: 'a> { - inner: &'a mut VaListImpl<'f>, - _marker: PhantomData<&'a mut VaListImpl<'f>>, - } - - - impl<'f> VaListImpl<'f> { - /// Converts a [`VaListImpl`] into a [`VaList`] that is binary-compatible with C's `va_list`. - #[inline] - pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { - VaList { inner: self, _marker: PhantomData } - } - } - } - - _ => { - /// A wrapper for a `va_list` - #[repr(transparent)] #[derive(Debug)] - pub struct VaList<'a, 'f: 'a> { - inner: VaListImpl<'f>, - _marker: PhantomData<&'a mut VaListImpl<'f>>, - } - - impl<'f> VaListImpl<'f> { - /// Converts a [`VaListImpl`] into a [`VaList`] that is binary-compatible with C's `va_list`. - #[inline] - pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { - VaList { inner: VaListImpl { ..*self }, _marker: PhantomData } - } + struct VaListInner { + ptr: *const c_void, } } } -impl<'a, 'f: 'a> Deref for VaList<'a, 'f> { - type Target = VaListImpl<'f>; - - #[inline] - fn deref(&self) -> &VaListImpl<'f> { - &self.inner - } +/// A variable argument list, equivalent to `va_list` in C. +#[repr(transparent)] +#[lang = "va_list"] +pub struct VaList<'a> { + inner: VaListInner, + _marker: PhantomCovariantLifetime<'a>, } -impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> { - #[inline] - fn deref_mut(&mut self) -> &mut VaListImpl<'f> { - &mut self.inner +impl fmt::Debug for VaList<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // No need to include `_marker` in debug output. + f.debug_tuple("VaList").field(&self.inner).finish() } } @@ -203,7 +176,7 @@ mod sealed { impl Sealed for *const T {} } -/// Types that are valid to read using [`VaListImpl::arg`]. +/// Types that are valid to read using [`VaList::arg`]. /// /// # Safety /// @@ -238,7 +211,7 @@ unsafe impl VaArgSafe for f64 {} unsafe impl VaArgSafe for *mut T {} unsafe impl VaArgSafe for *const T {} -impl<'f> VaListImpl<'f> { +impl<'f> VaList<'f> { /// Advance to and read the next variable argument. /// /// # Safety @@ -257,27 +230,13 @@ impl<'f> VaListImpl<'f> { // SAFETY: the caller must uphold the safety contract for `va_arg`. unsafe { va_arg(self) } } - - /// Copies the `va_list` at the current location. - pub unsafe fn with_copy(&self, f: F) -> R - where - F: for<'copy> FnOnce(VaList<'copy, 'f>) -> R, - { - let mut ap = self.clone(); - let ret = f(ap.as_va_list()); - // SAFETY: the caller must uphold the safety contract for `va_end`. - unsafe { - va_end(&mut ap); - } - ret - } } -impl<'f> Clone for VaListImpl<'f> { +impl<'f> Clone for VaList<'f> { #[inline] fn clone(&self) -> Self { let mut dest = crate::mem::MaybeUninit::uninit(); - // SAFETY: we write to the `MaybeUninit`, thus it is initialized and `assume_init` is legal + // SAFETY: we write to the `MaybeUninit`, thus it is initialized and `assume_init` is legal. unsafe { va_copy(dest.as_mut_ptr(), self); dest.assume_init() @@ -285,18 +244,11 @@ impl<'f> Clone for VaListImpl<'f> { } } -impl<'f> Drop for VaListImpl<'f> { +impl<'f> Drop for VaList<'f> { fn drop(&mut self) { - // FIXME: this should call `va_end`, but there's no clean way to - // guarantee that `drop` always gets inlined into its caller, - // so the `va_end` would get directly called from the same function as - // the corresponding `va_copy`. `man va_end` states that C requires this, - // and LLVM basically follows the C semantics, so we need to make sure - // that `va_end` is always called from the same function as `va_copy`. - // For more details, see https://github.com/rust-lang/rust/pull/59625 - // and https://llvm.org/docs/LangRef.html#llvm-va-end-intrinsic. - // - // This works for now, since `va_end` is a no-op on all current LLVM targets. + // Rust requires that not calling `va_end` on a `va_list` does not cause undefined behaviour + // (as it is safe to leak values). As `va_end` is a no-op on all current LLVM targets, this + // destructor is empty. } } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 5ba2d92a4596f..aecbba8037988 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -54,7 +54,7 @@ )] #![allow(missing_docs)] -use crate::ffi::va_list::{VaArgSafe, VaListImpl}; +use crate::ffi::va_list::{VaArgSafe, VaList}; use crate::marker::{ConstParamTy, Destruct, DiscriminantKind, PointeeSized, Tuple}; use crate::ptr; @@ -3305,7 +3305,7 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize /// FIXME: document safety requirements #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>); +pub unsafe fn va_copy<'f>(dest: *mut VaList<'f>, src: &VaList<'f>); /// Loads an argument of type `T` from the `va_list` `ap` and increment the /// argument `ap` points to. @@ -3313,11 +3313,11 @@ pub unsafe fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>); /// FIXME: document safety requirements #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn va_arg(ap: &mut VaListImpl<'_>) -> T; +pub unsafe fn va_arg(ap: &mut VaList<'_>) -> T; /// Destroy the arglist `ap` after initialization with `va_start` or `va_copy`. /// /// FIXME: document safety requirements #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn va_end(ap: &mut VaListImpl<'_>); +pub unsafe fn va_end(ap: &mut VaList<'_>); diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index f44e12d48addf..999bd5e63dc45 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -172,7 +172,7 @@ pub use core::ffi::c_void; all supported platforms", issue = "44930" )] -pub use core::ffi::{VaArgSafe, VaList, VaListImpl}; +pub use core::ffi::{VaArgSafe, VaList}; #[stable(feature = "core_ffi_c", since = "1.64.0")] pub use core::ffi::{ c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index 1474df146f9ce..4e098bff7134c 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -111,6 +111,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-thumbv8m.base-none-eabi", "ignore-thumbv8m.main-none-eabi", "ignore-tvos", + "ignore-uefi", "ignore-unix", "ignore-unknown", "ignore-uwp", diff --git a/tests/auxiliary/rust_test_helpers.c b/tests/auxiliary/rust_test_helpers.c index 34cc7fd5dfbed..cd10d6b98ca7b 100644 --- a/tests/auxiliary/rust_test_helpers.c +++ b/tests/auxiliary/rust_test_helpers.c @@ -314,6 +314,10 @@ double rust_interesting_average(uint64_t n, ...) { return sum; } +int32_t rust_va_list_next_i32(va_list* ap) { + return va_arg(*ap, int32_t); +} + int32_t rust_int8_to_int32(int8_t x) { return (int32_t)x; } diff --git a/tests/codegen-llvm/cffi/c-variadic-copy.rs b/tests/codegen-llvm/cffi/c-variadic-copy.rs index 4c61c4fcf68d3..0cbdcb4bbb85c 100644 --- a/tests/codegen-llvm/cffi/c-variadic-copy.rs +++ b/tests/codegen-llvm/cffi/c-variadic-copy.rs @@ -1,4 +1,4 @@ -// Tests that `VaListImpl::clone` gets inlined into a call to `llvm.va_copy` +// Tests that `VaList::clone` gets inlined into a call to `llvm.va_copy` #![crate_type = "lib"] #![feature(c_variadic)] @@ -12,5 +12,5 @@ extern "C" { pub unsafe extern "C" fn clone_variadic(ap: VaList) { let mut ap2 = ap.clone(); // CHECK: call void @llvm.va_copy - foreign_c_variadic_1(ap2.as_va_list(), 42i32); + foreign_c_variadic_1(ap2, 42i32); } diff --git a/tests/codegen-llvm/cffi/c-variadic-opt.rs b/tests/codegen-llvm/cffi/c-variadic-opt.rs index 7e544ee7f37da..3cc0c3e9f9bdd 100644 --- a/tests/codegen-llvm/cffi/c-variadic-opt.rs +++ b/tests/codegen-llvm/cffi/c-variadic-opt.rs @@ -10,21 +10,21 @@ extern "C" { } // Ensure that `va_start` and `va_end` are properly injected even -// when the "spoofed" `VaListImpl` is not used. +// when the "spoofed" `VaList` is not used. #[no_mangle] pub unsafe extern "C" fn c_variadic_no_use(fmt: *const i8, mut ap: ...) -> i32 { // CHECK: call void @llvm.va_start - vprintf(fmt, ap.as_va_list()) + vprintf(fmt, ap) // CHECK: call void @llvm.va_end } -// Check that `VaListImpl::clone` gets inlined into a direct call to `llvm.va_copy` +// Check that `VaList::clone` gets inlined into a direct call to `llvm.va_copy` #[no_mangle] pub unsafe extern "C" fn c_variadic_clone(fmt: *const i8, mut ap: ...) -> i32 { // CHECK: call void @llvm.va_start let mut ap2 = ap.clone(); // CHECK: call void @llvm.va_copy - let res = vprintf(fmt, ap2.as_va_list()); + let res = vprintf(fmt, ap2); res // CHECK: call void @llvm.va_end } diff --git a/tests/codegen-llvm/cffi/c-variadic.rs b/tests/codegen-llvm/cffi/c-variadic.rs index 140d2f37f4693..46d85121c2333 100644 --- a/tests/codegen-llvm/cffi/c-variadic.rs +++ b/tests/codegen-llvm/cffi/c-variadic.rs @@ -25,7 +25,7 @@ pub unsafe extern "C" fn use_foreign_c_variadic_0() { } // Ensure that we do not remove the `va_list` passed to the foreign function when -// removing the "spoofed" `VaListImpl` that is used by Rust defined C-variadics. +// removing the "spoofed" `VaList` that is used by Rust defined C-variadics. pub unsafe extern "C" fn use_foreign_c_variadic_1_0(ap: VaList) { // CHECK: call void ({{.*}}, ...) @foreign_c_variadic_1({{.*}} %ap) foreign_c_variadic_1(ap); diff --git a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs index 63d8d713d6226..dd2d094709942 100644 --- a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs +++ b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs @@ -2,7 +2,7 @@ #![feature(c_variadic)] #![feature(cfg_select)] -use std::ffi::{CStr, CString, VaList, VaListImpl, c_char, c_double, c_int, c_long, c_longlong}; +use std::ffi::{CStr, CString, VaList, c_char, c_double, c_int, c_long, c_longlong}; macro_rules! continue_if { ($cond:expr) => { @@ -58,11 +58,8 @@ pub unsafe extern "C" fn check_list_copy_0(mut ap: VaList) -> usize { continue_if!(ap.arg::() == 16); continue_if!(ap.arg::() == 'A' as c_int); continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Skip Me!")); - ap.with_copy( - |mut ap| { - if compare_c_str(ap.arg::<*const c_char>(), "Correct") { 0 } else { 0xff } - }, - ) + let mut ap = ap.clone(); + if compare_c_str(ap.arg::<*const c_char>(), "Correct") { 0 } else { 0xff } } #[unsafe(no_mangle)] @@ -153,8 +150,8 @@ pub unsafe extern "C" fn check_varargs_5(_: c_int, mut ap: ...) -> usize { unsafe extern "C" { fn test_variadic(_: c_int, ...) -> usize; fn test_va_list_by_value(_: VaList) -> usize; - fn test_va_list_by_pointer(_: *mut VaListImpl) -> usize; - fn test_va_list_by_pointer_pointer(_: *mut *mut VaListImpl) -> usize; + fn test_va_list_by_pointer(_: *mut VaList) -> usize; + fn test_va_list_by_pointer_pointer(_: *mut *mut VaList) -> usize; } #[unsafe(no_mangle)] @@ -165,7 +162,7 @@ extern "C" fn run_test_variadic() -> usize { #[unsafe(no_mangle)] extern "C" fn run_test_va_list_by_value() -> usize { unsafe extern "C" fn helper(mut ap: ...) -> usize { - unsafe { test_va_list_by_value(ap.as_va_list()) } + unsafe { test_va_list_by_value(ap) } } unsafe { helper(1 as c_longlong, 2 as c_int, 3 as c_longlong) } diff --git a/tests/ui/abi/variadic-ffi.rs b/tests/ui/abi/variadic-ffi.rs index dfdbff33264be..3ffa0bea0ecf8 100644 --- a/tests/ui/abi/variadic-ffi.rs +++ b/tests/ui/abi/variadic-ffi.rs @@ -10,37 +10,45 @@ extern "C" { fn rust_interesting_average(_: u64, ...) -> f64; fn rust_valist_interesting_average(_: u64, _: VaList) -> f64; + + fn rust_va_list_next_i32(_: *mut VaList<'_>) -> i32; } -pub unsafe extern "C" fn test_valist_forward(n: u64, mut ap: ...) -> f64 { - rust_valist_interesting_average(n, ap.as_va_list()) +pub unsafe extern "C" fn test_valist_forward(n: u64, ap: ...) -> f64 { + rust_valist_interesting_average(n, ap) } -pub unsafe extern "C-unwind" fn c_unwind_can_forward(n: u64, mut ap: ...) -> f64 { - rust_valist_interesting_average(n, ap.as_va_list()) +pub unsafe extern "C-unwind" fn c_unwind_can_forward(n: u64, ap: ...) -> f64 { + rust_valist_interesting_average(n, ap) } pub unsafe extern "C" fn test_va_copy(_: u64, mut ap: ...) { - let mut ap2 = ap.clone(); - assert_eq!(rust_valist_interesting_average(2, ap2.as_va_list()) as i64, 30); + let ap2 = ap.clone(); + assert_eq!(rust_valist_interesting_average(2, ap2) as i64, 30); // Advance one pair in the copy before checking let mut ap2 = ap.clone(); let _ = ap2.arg::(); let _ = ap2.arg::(); - assert_eq!(rust_valist_interesting_average(2, ap2.as_va_list()) as i64, 50); + assert_eq!(rust_valist_interesting_average(2, ap2) as i64, 50); // Advance one pair in the original let _ = ap.arg::(); let _ = ap.arg::(); - let mut ap2 = ap.clone(); - assert_eq!(rust_valist_interesting_average(2, ap2.as_va_list()) as i64, 50); + let ap2 = ap.clone(); + assert_eq!(rust_valist_interesting_average(2, ap2) as i64, 50); let mut ap2 = ap.clone(); let _ = ap2.arg::(); let _ = ap2.arg::(); - assert_eq!(rust_valist_interesting_average(2, ap2.as_va_list()) as i64, 70); + assert_eq!(rust_valist_interesting_average(2, ap2) as i64, 70); +} + +pub unsafe extern "C" fn test_ref(mut ap: ...) { + assert_eq!(rust_va_list_next_i32(&mut ap), 2); + assert_eq!(rust_va_list_next_i32(&mut ap), 4); + assert_eq!(rust_va_list_next_i32(&mut ap), 8); } pub fn main() { @@ -85,4 +93,8 @@ pub fn main() { unsafe { test_va_copy(4, 10i64, 10f64, 20i64, 20f64, 30i64, 30f64, 40i64, 40f64); } + + unsafe { + test_ref(2, 4, 8); + } } diff --git a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr new file mode 100644 index 0000000000000..fe11c42886188 --- /dev/null +++ b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr @@ -0,0 +1,80 @@ +error: fn_abi_of(take_va_list) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: VaList<'_>, + layout: Layout { + size: Size(32 bytes), + align: AbiAlign { + abi: Align(8 bytes), + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: $OFFSETS, + memory_index: $MEMORY_INDEX, + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(8 bytes), + randomization_seed: $SEED, + }, + }, + mode: Indirect { + attrs: ArgAttributes { + regular: CapturesAddress | NoAlias | NonNull | NoUndef, + arg_ext: None, + pointee_size: Size(32 bytes), + pointee_align: Some( + Align(8 bytes), + ), + }, + meta_attrs: None, + on_stack: false, + }, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: C, + can_unwind: false, + } + --> $DIR/pass-by-value-abi.rs:26:1 + | +LL | pub extern "C" fn take_va_list(_: VaList<'_>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/c-variadic/pass-by-value-abi.rs b/tests/ui/c-variadic/pass-by-value-abi.rs new file mode 100644 index 0000000000000..b65442af24727 --- /dev/null +++ b/tests/ui/c-variadic/pass-by-value-abi.rs @@ -0,0 +1,46 @@ +//@ check-fail +//@ normalize-stderr: "randomization_seed: \d+" -> "randomization_seed: $$SEED" +//@ normalize-stderr: "valid_range: 0\.\.=\d+" -> "valid_range: 0..=$$MAX" +//@ normalize-stderr: "memory_index: \[[^\]]+\]" -> "memory_index: $$MEMORY_INDEX" +//@ normalize-stderr: "offsets: \[[^\]]+\]" -> "offsets: $$OFFSETS" +//@ revisions: x86_64 aarch64 win +//@ compile-flags: -O +//@ [x86_64] only-x86_64 +//@ [x86_64] ignore-windows +//@ [x86_64] ignore-uefi +//@ [aarch64] only-aarch64 +//@ [aarch64] ignore-windows +//@ [aarch64] ignore-apple +//@ [aarch64] ignore-uefi +// Windows dosen't use `#[rustc_pass_indirectly_in_non_rustic_abis]` and is tested in CI, so is here +// for comparison. +//@ [win] only-windows + +#![feature(rustc_attrs, c_variadic)] +#![crate_type = "lib"] + +// Can't use `minicore` here as this is testing the implementation in `core::ffi` specifically. +use std::ffi::VaList; + +#[rustc_abi(debug)] +pub extern "C" fn take_va_list(_: VaList<'_>) {} +//~^ ERROR fn_abi_of(take_va_list) = FnAbi { +//[x86_64]~^^ ERROR mode: Indirect { +//[x86_64]~^^^ ERROR on_stack: false, +//[aarch64]~^^^^ ERROR mode: Indirect { +//[aarch64]~^^^^^ ERROR on_stack: false, +//[win]~^^^^^^ ERROR mode: Direct( + +#[cfg(all(target_arch = "x86_64", not(windows)))] +#[rustc_abi(debug)] +pub extern "sysv64" fn take_va_list_sysv64(_: VaList<'_>) {} +//[x86_64]~^ ERROR fn_abi_of(take_va_list_sysv64) = FnAbi { +//[x86_64]~^^ ERROR mode: Indirect { +//[x86_64]~^^^ ERROR on_stack: false, + +#[cfg(all(target_arch = "x86_64", not(windows)))] +#[rustc_abi(debug)] +pub extern "win64" fn take_va_list_win64(_: VaList<'_>) {} +//[x86_64]~^ ERROR: fn_abi_of(take_va_list_win64) = FnAbi { +//[x86_64]~^^ ERROR mode: Indirect { +//[x86_64]~^^^ ERROR on_stack: false, diff --git a/tests/ui/c-variadic/pass-by-value-abi.win.stderr b/tests/ui/c-variadic/pass-by-value-abi.win.stderr new file mode 100644 index 0000000000000..e84430859e029 --- /dev/null +++ b/tests/ui/c-variadic/pass-by-value-abi.win.stderr @@ -0,0 +1,83 @@ +error: fn_abi_of(take_va_list) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: VaList<'_>, + layout: Layout { + size: Size(8 bytes), + align: AbiAlign { + abi: Align(8 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Pointer( + AddressSpace( + 0, + ), + ), + valid_range: 0..=$MAX, + }, + ), + fields: Arbitrary { + offsets: $OFFSETS, + memory_index: $MEMORY_INDEX, + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(8 bytes), + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: C, + can_unwind: false, + } + --> $DIR/pass-by-value-abi.rs:26:1 + | +LL | pub extern "C" fn take_va_list(_: VaList<'_>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr new file mode 100644 index 0000000000000..73f1ccd5992a9 --- /dev/null +++ b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr @@ -0,0 +1,240 @@ +error: fn_abi_of(take_va_list) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: VaList<'_>, + layout: Layout { + size: Size(24 bytes), + align: AbiAlign { + abi: Align(8 bytes), + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: $OFFSETS, + memory_index: $MEMORY_INDEX, + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(8 bytes), + randomization_seed: $SEED, + }, + }, + mode: Indirect { + attrs: ArgAttributes { + regular: CapturesAddress | NoAlias | NonNull | NoUndef, + arg_ext: None, + pointee_size: Size(24 bytes), + pointee_align: Some( + Align(8 bytes), + ), + }, + meta_attrs: None, + on_stack: false, + }, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: C, + can_unwind: false, + } + --> $DIR/pass-by-value-abi.rs:26:1 + | +LL | pub extern "C" fn take_va_list(_: VaList<'_>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(take_va_list_sysv64) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: VaList<'_>, + layout: Layout { + size: Size(24 bytes), + align: AbiAlign { + abi: Align(8 bytes), + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: $OFFSETS, + memory_index: $MEMORY_INDEX, + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(8 bytes), + randomization_seed: $SEED, + }, + }, + mode: Indirect { + attrs: ArgAttributes { + regular: CapturesAddress | NoAlias | NonNull | NoUndef, + arg_ext: None, + pointee_size: Size(24 bytes), + pointee_align: Some( + Align(8 bytes), + ), + }, + meta_attrs: None, + on_stack: false, + }, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/pass-by-value-abi.rs:36:1 + | +LL | pub extern "sysv64" fn take_va_list_sysv64(_: VaList<'_>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(take_va_list_win64) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: VaList<'_>, + layout: Layout { + size: Size(24 bytes), + align: AbiAlign { + abi: Align(8 bytes), + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: $OFFSETS, + memory_index: $MEMORY_INDEX, + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(8 bytes), + randomization_seed: $SEED, + }, + }, + mode: Indirect { + attrs: ArgAttributes { + regular: CapturesAddress | NoAlias | NonNull | NoUndef, + arg_ext: None, + pointee_size: Size(24 bytes), + pointee_align: Some( + Align(8 bytes), + ), + }, + meta_attrs: None, + on_stack: false, + }, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + Win64, + ), + can_unwind: false, + } + --> $DIR/pass-by-value-abi.rs:43:1 + | +LL | pub extern "win64" fn take_va_list_win64(_: VaList<'_>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/c-variadic/variadic-ffi-4.rs b/tests/ui/c-variadic/variadic-ffi-4.rs index 8064037942259..d9e2e617ce3a1 100644 --- a/tests/ui/c-variadic/variadic-ffi-4.rs +++ b/tests/ui/c-variadic/variadic-ffi-4.rs @@ -2,37 +2,30 @@ #![no_std] #![feature(c_variadic)] -use core::ffi::{VaList, VaListImpl}; +use core::ffi::VaList; -pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { +pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaList<'f> { ap //~^ ERROR: lifetime may not live long enough - //~| ERROR: lifetime may not live long enough } -pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> { +pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaList<'static> { ap //~ ERROR: lifetime may not live long enough } -pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) { - let _ = ap.with_copy(|ap| ap); //~ ERROR: lifetime may not live long enough -} - -pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { +pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaList, mut ap1: ...) { *ap0 = ap1; //~^ ERROR: lifetime may not live long enough - //~| ERROR: lifetime may not live long enough } -pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { +pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) { ap0 = &mut ap1; //~^ ERROR: `ap1` does not live long enough //~| ERROR: lifetime may not live long enough //~| ERROR: lifetime may not live long enough } -pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { +pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaList, mut ap1: ...) { *ap0 = ap1.clone(); //~^ ERROR: lifetime may not live long enough - //~| ERROR: lifetime may not live long enough } diff --git a/tests/ui/c-variadic/variadic-ffi-4.stderr b/tests/ui/c-variadic/variadic-ffi-4.stderr index fc9f8036083a6..a230bb6f5861e 100644 --- a/tests/ui/c-variadic/variadic-ffi-4.stderr +++ b/tests/ui/c-variadic/variadic-ffi-4.stderr @@ -1,113 +1,64 @@ error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:8:5 | -LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { - | -- -- has type `VaListImpl<'1>` - | | - | lifetime `'f` defined here -LL | ap - | ^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'f` - | - = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant - = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` - = help: see for more information about variance - -error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:8:5 - | -LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { - | -- -- has type `VaListImpl<'1>` +LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaList<'f> { + | -- -- has type `VaList<'1>` | | | lifetime `'f` defined here LL | ap | ^^ function was supposed to return data with lifetime `'f` but it is returning data with lifetime `'1` - | - = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant - = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` - = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:14:5 + --> $DIR/variadic-ffi-4.rs:13:5 | -LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> { - | -- has type `VaListImpl<'1>` +LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaList<'static> { + | -- has type `VaList<'1>` LL | ap | ^^ returning this value requires that `'1` must outlive `'static` - | - = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant - = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` - = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:18:31 + --> $DIR/variadic-ffi-4.rs:17:5 | -LL | let _ = ap.with_copy(|ap| ap); - | --- ^^ returning this value requires that `'1` must outlive `'2` - | | | - | | return type of closure is VaList<'2, '_> - | has type `VaList<'1, '_>` - -error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:22:5 - | -LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { - | ------- ------- has type `VaListImpl<'2>` +LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaList, mut ap1: ...) { + | ------- ------- has type `VaList<'1>` | | - | has type `&mut VaListImpl<'1>` + | has type `&mut VaList<'2>` LL | *ap0 = ap1; | ^^^^ assignment requires that `'1` must outlive `'2` - | - = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant - = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` - = help: see for more information about variance error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:22:5 | -LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { - | ------- ------- has type `VaListImpl<'2>` +LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) { + | ------- ------- has type `VaList<'2>` | | - | has type `&mut VaListImpl<'1>` -LL | *ap0 = ap1; - | ^^^^ assignment requires that `'2` must outlive `'1` - | - = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant - = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` - = help: see for more information about variance - -error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:28:5 - | -LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { - | ------- ------- has type `VaListImpl<'2>` - | | - | has type `&mut VaListImpl<'1>` + | has type `&mut VaList<'1>` LL | ap0 = &mut ap1; | ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2` | - = note: requirement occurs because of a mutable reference to `VaListImpl<'_>` + = note: requirement occurs because of a mutable reference to `VaList<'_>` = note: mutable references are invariant over their type parameter = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:28:5 + --> $DIR/variadic-ffi-4.rs:22:5 | -LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { - | ------- ------- has type `VaListImpl<'2>` +LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) { + | ------- ------- has type `VaList<'2>` | | - | has type `&mut VaListImpl<'1>` + | has type `&mut VaList<'1>` LL | ap0 = &mut ap1; | ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1` | - = note: requirement occurs because of a mutable reference to `VaListImpl<'_>` + = note: requirement occurs because of a mutable reference to `VaList<'_>` = note: mutable references are invariant over their type parameter = help: see for more information about variance error[E0597]: `ap1` does not live long enough - --> $DIR/variadic-ffi-4.rs:28:11 + --> $DIR/variadic-ffi-4.rs:22:11 | -LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { - | - ------- binding `ap1` declared here +LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) { + | - ------- binding `ap1` declared here | | | let's call the lifetime of this reference `'3` LL | ap0 = &mut ap1; @@ -120,33 +71,15 @@ LL | } | - `ap1` dropped here while still borrowed error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:35:5 - | -LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { - | ------- ------- has type `VaListImpl<'2>` - | | - | has type `&mut VaListImpl<'1>` -LL | *ap0 = ap1.clone(); - | ^^^^ assignment requires that `'2` must outlive `'1` - | - = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant - = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` - = help: see for more information about variance - -error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:35:12 + --> $DIR/variadic-ffi-4.rs:29:5 | -LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { - | ------- ------- has type `VaListImpl<'2>` +LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaList, mut ap1: ...) { + | ------- ------- has type `VaList<'1>` | | - | has type `&mut VaListImpl<'1>` + | has type `&mut VaList<'2>` LL | *ap0 = ap1.clone(); - | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2` - | - = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant - = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` - = help: see for more information about variance + | ^^^^ assignment requires that `'1` must outlive `'2` -error: aborting due to 11 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/parser/macro/macro-dotdotdot-may-not-begin-a-type.rs b/tests/ui/parser/macro/macro-dotdotdot-may-not-begin-a-type.rs index 8be99f22d2ee0..b29f6915ae3d6 100644 --- a/tests/ui/parser/macro/macro-dotdotdot-may-not-begin-a-type.rs +++ b/tests/ui/parser/macro/macro-dotdotdot-may-not-begin-a-type.rs @@ -1,4 +1,4 @@ -// A bare `...` represents `CVarArgs` (`VaListImpl<'_>`) in function argument type +// A bare `...` represents `CVarArgs` (`VaList<'_>`) in function argument type // position without being a proper type syntactically. // This test ensures that we do not regress certain MBE calls would we ever promote // `...` to a proper type syntactically. diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs index 415472176d9c4..558f10208878a 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -32,12 +32,12 @@ extern "C" fn f3_3(..., x: isize) {} const unsafe extern "C" fn f4_1(x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic -//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time +//~| ERROR destructor of `VaList<'_>` cannot be evaluated at compile-time 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 destructor of `VaListImpl<'_>` cannot be evaluated at compile-time +//~| ERROR destructor of `VaList<'_>` cannot be evaluated at compile-time const extern "C" fn f4_3(..., x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic @@ -65,7 +65,7 @@ impl X { 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 `VaListImpl<'_>` cannot be evaluated at compile-time + //~| ERROR destructor of `VaList<'_>` cannot be evaluated at compile-time } trait T { diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr index da9c9b0f76099..3b178d984e1bb 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -236,7 +236,7 @@ error: `...` must be the last argument of a C-variadic function LL | fn t_f6(..., x: isize); | ^^^ -error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time +error[E0493]: destructor of `VaList<'_>` cannot be evaluated at compile-time --> $DIR/variadic-ffi-semantic-restrictions.rs:33:43 | LL | const unsafe extern "C" fn f4_1(x: isize, ...) {} @@ -244,7 +244,7 @@ LL | const unsafe extern "C" fn f4_1(x: isize, ...) {} | | | the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time +error[E0493]: destructor of `VaList<'_>` cannot be evaluated at compile-time --> $DIR/variadic-ffi-semantic-restrictions.rs:37:36 | LL | const extern "C" fn f4_2(x: isize, ...) {} @@ -252,7 +252,7 @@ LL | const extern "C" fn f4_2(x: isize, ...) {} | | | the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time +error[E0493]: destructor of `VaList<'_>` cannot be evaluated at compile-time --> $DIR/variadic-ffi-semantic-restrictions.rs:65:29 | LL | const fn i_f5(x: isize, ...) {} diff --git a/tests/ui/thir-print/c-variadic.stdout b/tests/ui/thir-print/c-variadic.stdout index 8363f06ebe887..94e949f86c2bf 100644 --- a/tests/ui/thir-print/c-variadic.stdout +++ b/tests/ui/thir-print/c-variadic.stdout @@ -16,13 +16,13 @@ params: [ ) } Param { - ty: std::ffi::VaListImpl<'{erased}> + ty: std::ffi::VaList<'{erased}> ty_span: None self_kind: None hir_id: Some(HirId(DefId(0:3 ~ c_variadic[a5de]::foo).3)) param: Some( Pat: { - ty: std::ffi::VaListImpl<'{erased}> + ty: std::ffi::VaList<'{erased}> span: $DIR/c-variadic.rs:6:34: 6:37 (#0) kind: PatKind { Missing