1
Fork 0

Auto merge of #136965 - jhpratt:rollup-bsnqvmf, r=jhpratt

Rollup of 8 pull requests

Successful merges:

 - #134999 (Add cygwin target.)
 - #136559 (Resolve named regions when reporting type test failures in NLL)
 - #136660 (Use a trait to enforce field validity for union fields + `unsafe` fields + `unsafe<>` binder types)
 - #136858 (Parallel-compiler-related cleanup)
 - #136881 (cg_llvm: Reduce visibility of all functions in the llvm module)
 - #136888 (Always perform discr read for never pattern in EUV)
 - #136948 (Split out the `extern_system_varargs` feature)
 - #136949 (Fix import in bench for wasm)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-02-13 11:45:11 +00:00
commit 54cdc751df
71 changed files with 1231 additions and 790 deletions

View file

@ -195,7 +195,6 @@ impl ExternAbi {
// * C and Cdecl obviously support varargs.
// * C can be based on Aapcs, SysV64 or Win64, so they must support varargs.
// * EfiApi is based on Win64 or C, so it also supports it.
// * System falls back to C for functions with varargs.
//
// * Stdcall does not, because it would be impossible for the callee to clean
// up the arguments. (callee doesn't know how many arguments are there)
@ -204,7 +203,6 @@ impl ExternAbi {
match self {
Self::C { .. }
| Self::Cdecl { .. }
| Self::System { .. }
| Self::Aapcs { .. }
| Self::Win64 { .. }
| Self::SysV64 { .. }

View file

@ -316,13 +316,16 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let type_test_span = type_test.span;
if let Some(lower_bound_region) = lower_bound_region {
let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
let generic_ty = self.regioncx.name_regions(
self.infcx.tcx,
type_test.generic_kind.to_ty(self.infcx.tcx),
);
let origin = RelateParamBound(type_test_span, generic_ty, None);
self.buffer_error(self.infcx.err_ctxt().construct_generic_bound_failure(
self.body.source.def_id().expect_local(),
type_test_span,
Some(origin),
type_test.generic_kind,
self.regioncx.name_regions(self.infcx.tcx, type_test.generic_kind),
lower_bound_region,
));
} else {

View file

@ -57,6 +57,9 @@ impl<T: ?Sized> LegacyReceiver for Box<T> {}
#[lang = "copy"]
pub trait Copy {}
#[lang = "bikeshed_guaranteed_no_drop"]
pub trait BikeshedGuaranteedNoDrop {}
impl Copy for bool {}
impl Copy for u8 {}
impl Copy for u16 {}

View file

@ -54,6 +54,9 @@ impl<T: ?Sized, A: Allocator> LegacyReceiver for Box<T, A> {}
#[lang = "copy"]
pub trait Copy {}
#[lang = "bikeshed_guaranteed_no_drop"]
pub trait BikeshedGuaranteedNoDrop {}
impl Copy for bool {}
impl Copy for u8 {}
impl Copy for u16 {}

View file

@ -710,10 +710,6 @@ pub struct ThinBuffer {
context: Arc<SyncContext>,
}
// TODO: check if this makes sense to make ThinBuffer Send and Sync.
unsafe impl Send for ThinBuffer {}
unsafe impl Sync for ThinBuffer {}
impl ThinBuffer {
pub(crate) fn new(context: &Arc<SyncContext>) -> Self {
Self { context: Arc::clone(context) }

View file

@ -245,9 +245,6 @@ impl WriteBackendMethods for LlvmCodegenBackend {
}
}
unsafe impl Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis
unsafe impl Sync for LlvmCodegenBackend {}
impl LlvmCodegenBackend {
pub fn new() -> Box<dyn CodegenBackend> {
Box::new(LlvmCodegenBackend(()))

View file

@ -26,7 +26,7 @@ impl ArchiveRO {
///
/// If this archive is used with a mutable method, then an error will be
/// raised.
pub fn open(dst: &Path) -> Result<ArchiveRO, String> {
pub(crate) fn open(dst: &Path) -> Result<ArchiveRO, String> {
unsafe {
let s = path_to_c_string(dst);
let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| {
@ -36,7 +36,7 @@ impl ArchiveRO {
}
}
pub fn iter(&self) -> Iter<'_> {
pub(crate) fn iter(&self) -> Iter<'_> {
unsafe { Iter { raw: super::LLVMRustArchiveIteratorNew(self.raw) } }
}
}
@ -71,7 +71,7 @@ impl<'a> Drop for Iter<'a> {
}
impl<'a> Child<'a> {
pub fn name(&self) -> Option<&'a str> {
pub(crate) fn name(&self) -> Option<&'a str> {
unsafe {
let mut name_len = 0;
let name_ptr = super::LLVMRustArchiveChildName(self.raw, &mut name_len);

View file

@ -1,4 +1,5 @@
#![allow(non_camel_case_types)]
#![expect(dead_code)]
use libc::{c_char, c_uint};
@ -8,23 +9,23 @@ use crate::llvm::Bool;
#[link(name = "llvm-wrapper", kind = "static")]
extern "C" {
// Enzyme
pub fn LLVMRustHasMetadata(I: &Value, KindID: c_uint) -> bool;
pub fn LLVMRustEraseInstUntilInclusive(BB: &BasicBlock, I: &Value);
pub fn LLVMRustGetLastInstruction<'a>(BB: &BasicBlock) -> Option<&'a Value>;
pub fn LLVMRustDIGetInstMetadata(I: &Value) -> Option<&Metadata>;
pub fn LLVMRustEraseInstFromParent(V: &Value);
pub fn LLVMRustGetTerminator<'a>(B: &BasicBlock) -> &'a Value;
pub fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool;
pub(crate) fn LLVMRustHasMetadata(I: &Value, KindID: c_uint) -> bool;
pub(crate) fn LLVMRustEraseInstUntilInclusive(BB: &BasicBlock, I: &Value);
pub(crate) fn LLVMRustGetLastInstruction<'a>(BB: &BasicBlock) -> Option<&'a Value>;
pub(crate) fn LLVMRustDIGetInstMetadata(I: &Value) -> Option<&Metadata>;
pub(crate) fn LLVMRustEraseInstFromParent(V: &Value);
pub(crate) fn LLVMRustGetTerminator<'a>(B: &BasicBlock) -> &'a Value;
pub(crate) fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool;
}
extern "C" {
// Enzyme
pub fn LLVMDumpModule(M: &Module);
pub fn LLVMDumpValue(V: &Value);
pub fn LLVMGetFunctionCallConv(F: &Value) -> c_uint;
pub fn LLVMGetReturnType(T: &Type) -> &Type;
pub fn LLVMGetParams(Fnc: &Value, parms: *mut &Value);
pub fn LLVMGetNamedFunction(M: &Module, Name: *const c_char) -> Option<&Value>;
pub(crate) fn LLVMDumpModule(M: &Module);
pub(crate) fn LLVMDumpValue(V: &Value);
pub(crate) fn LLVMGetFunctionCallConv(F: &Value) -> c_uint;
pub(crate) fn LLVMGetReturnType(T: &Type) -> &Type;
pub(crate) fn LLVMGetParams(Fnc: &Value, parms: *mut &Value);
pub(crate) fn LLVMGetNamedFunction(M: &Module, Name: *const c_char) -> Option<&Value>;
}
#[repr(C)]

File diff suppressed because it is too large Load diff

View file

@ -24,7 +24,7 @@ mod ffi;
pub use self::enzyme_ffi::*;
impl LLVMRustResult {
pub fn into_result(self) -> Result<(), ()> {
pub(crate) fn into_result(self) -> Result<(), ()> {
match self {
LLVMRustResult::Success => Ok(()),
LLVMRustResult::Failure => Err(()),
@ -32,13 +32,17 @@ impl LLVMRustResult {
}
}
pub fn AddFunctionAttributes<'ll>(llfn: &'ll Value, idx: AttributePlace, attrs: &[&'ll Attribute]) {
pub(crate) fn AddFunctionAttributes<'ll>(
llfn: &'ll Value,
idx: AttributePlace,
attrs: &[&'ll Attribute],
) {
unsafe {
LLVMRustAddFunctionAttributes(llfn, idx.as_uint(), attrs.as_ptr(), attrs.len());
}
}
pub fn AddCallSiteAttributes<'ll>(
pub(crate) fn AddCallSiteAttributes<'ll>(
callsite: &'ll Value,
idx: AttributePlace,
attrs: &[&'ll Attribute],
@ -48,7 +52,11 @@ pub fn AddCallSiteAttributes<'ll>(
}
}
pub fn CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &str, value: &str) -> &'ll Attribute {
pub(crate) fn CreateAttrStringValue<'ll>(
llcx: &'ll Context,
attr: &str,
value: &str,
) -> &'ll Attribute {
unsafe {
LLVMCreateStringAttribute(
llcx,
@ -60,7 +68,7 @@ pub fn CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &str, value: &str) -
}
}
pub fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute {
pub(crate) fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute {
unsafe {
LLVMCreateStringAttribute(
llcx,
@ -72,39 +80,39 @@ pub fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute {
}
}
pub fn CreateAlignmentAttr(llcx: &Context, bytes: u64) -> &Attribute {
pub(crate) fn CreateAlignmentAttr(llcx: &Context, bytes: u64) -> &Attribute {
unsafe { LLVMRustCreateAlignmentAttr(llcx, bytes) }
}
pub fn CreateDereferenceableAttr(llcx: &Context, bytes: u64) -> &Attribute {
pub(crate) fn CreateDereferenceableAttr(llcx: &Context, bytes: u64) -> &Attribute {
unsafe { LLVMRustCreateDereferenceableAttr(llcx, bytes) }
}
pub fn CreateDereferenceableOrNullAttr(llcx: &Context, bytes: u64) -> &Attribute {
pub(crate) fn CreateDereferenceableOrNullAttr(llcx: &Context, bytes: u64) -> &Attribute {
unsafe { LLVMRustCreateDereferenceableOrNullAttr(llcx, bytes) }
}
pub fn CreateByValAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute {
pub(crate) fn CreateByValAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute {
unsafe { LLVMRustCreateByValAttr(llcx, ty) }
}
pub fn CreateStructRetAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute {
pub(crate) fn CreateStructRetAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute {
unsafe { LLVMRustCreateStructRetAttr(llcx, ty) }
}
pub fn CreateUWTableAttr(llcx: &Context, async_: bool) -> &Attribute {
pub(crate) fn CreateUWTableAttr(llcx: &Context, async_: bool) -> &Attribute {
unsafe { LLVMRustCreateUWTableAttr(llcx, async_) }
}
pub fn CreateAllocSizeAttr(llcx: &Context, size_arg: u32) -> &Attribute {
pub(crate) fn CreateAllocSizeAttr(llcx: &Context, size_arg: u32) -> &Attribute {
unsafe { LLVMRustCreateAllocSizeAttr(llcx, size_arg) }
}
pub fn CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &Attribute {
pub(crate) fn CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &Attribute {
unsafe { LLVMRustCreateAllocKindAttr(llcx, kind_arg.bits()) }
}
pub fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange) -> &Attribute {
pub(crate) fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange) -> &Attribute {
let lower = range.start;
let upper = range.end.wrapping_add(1);
let lower_words = [lower as u64, (lower >> 64) as u64];
@ -127,7 +135,7 @@ pub enum AttributePlace {
}
impl AttributePlace {
pub fn as_uint(self) -> c_uint {
pub(crate) fn as_uint(self) -> c_uint {
match self {
AttributePlace::ReturnValue => 0,
AttributePlace::Argument(i) => 1 + i,
@ -159,12 +167,12 @@ impl FromStr for ArchiveKind {
}
}
pub fn SetInstructionCallConv(instr: &Value, cc: CallConv) {
pub(crate) fn SetInstructionCallConv(instr: &Value, cc: CallConv) {
unsafe {
LLVMSetInstructionCallConv(instr, cc as c_uint);
}
}
pub fn SetFunctionCallConv(fn_: &Value, cc: CallConv) {
pub(crate) fn SetFunctionCallConv(fn_: &Value, cc: CallConv) {
unsafe {
LLVMSetFunctionCallConv(fn_, cc as c_uint);
}
@ -176,20 +184,20 @@ pub fn SetFunctionCallConv(fn_: &Value, cc: CallConv) {
// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
// function.
// For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52
pub fn SetUniqueComdat(llmod: &Module, val: &Value) {
pub(crate) fn SetUniqueComdat(llmod: &Module, val: &Value) {
let name_buf = get_value_name(val).to_vec();
let name =
CString::from_vec_with_nul(name_buf).or_else(|buf| CString::new(buf.into_bytes())).unwrap();
set_comdat(llmod, val, &name);
}
pub fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) {
pub(crate) fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) {
unsafe {
LLVMSetUnnamedAddress(global, unnamed);
}
}
pub fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) {
pub(crate) fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) {
unsafe {
LLVMSetThreadLocalMode(global, mode);
}
@ -197,65 +205,65 @@ pub fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) {
impl AttributeKind {
/// Create an LLVM Attribute with no associated value.
pub fn create_attr(self, llcx: &Context) -> &Attribute {
pub(crate) fn create_attr(self, llcx: &Context) -> &Attribute {
unsafe { LLVMRustCreateAttrNoValue(llcx, self) }
}
}
impl MemoryEffects {
/// Create an LLVM Attribute with these memory effects.
pub fn create_attr(self, llcx: &Context) -> &Attribute {
pub(crate) fn create_attr(self, llcx: &Context) -> &Attribute {
unsafe { LLVMRustCreateMemoryEffectsAttr(llcx, self) }
}
}
pub fn set_section(llglobal: &Value, section_name: &CStr) {
pub(crate) fn set_section(llglobal: &Value, section_name: &CStr) {
unsafe {
LLVMSetSection(llglobal, section_name.as_ptr());
}
}
pub fn add_global<'a>(llmod: &'a Module, ty: &'a Type, name_cstr: &CStr) -> &'a Value {
pub(crate) fn add_global<'a>(llmod: &'a Module, ty: &'a Type, name_cstr: &CStr) -> &'a Value {
unsafe { LLVMAddGlobal(llmod, ty, name_cstr.as_ptr()) }
}
pub fn set_initializer(llglobal: &Value, constant_val: &Value) {
pub(crate) fn set_initializer(llglobal: &Value, constant_val: &Value) {
unsafe {
LLVMSetInitializer(llglobal, constant_val);
}
}
pub fn set_global_constant(llglobal: &Value, is_constant: bool) {
pub(crate) fn set_global_constant(llglobal: &Value, is_constant: bool) {
unsafe {
LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False });
}
}
pub fn get_linkage(llglobal: &Value) -> Linkage {
pub(crate) fn get_linkage(llglobal: &Value) -> Linkage {
unsafe { LLVMGetLinkage(llglobal) }.to_rust()
}
pub fn set_linkage(llglobal: &Value, linkage: Linkage) {
pub(crate) fn set_linkage(llglobal: &Value, linkage: Linkage) {
unsafe {
LLVMSetLinkage(llglobal, linkage);
}
}
pub fn is_declaration(llglobal: &Value) -> bool {
pub(crate) fn is_declaration(llglobal: &Value) -> bool {
unsafe { LLVMIsDeclaration(llglobal) == ffi::True }
}
pub fn get_visibility(llglobal: &Value) -> Visibility {
pub(crate) fn get_visibility(llglobal: &Value) -> Visibility {
unsafe { LLVMGetVisibility(llglobal) }.to_rust()
}
pub fn set_visibility(llglobal: &Value, visibility: Visibility) {
pub(crate) fn set_visibility(llglobal: &Value, visibility: Visibility) {
unsafe {
LLVMSetVisibility(llglobal, visibility);
}
}
pub fn set_alignment(llglobal: &Value, align: Align) {
pub(crate) fn set_alignment(llglobal: &Value, align: Align) {
unsafe {
ffi::LLVMSetAlignment(llglobal, align.bytes() as c_uint);
}
@ -265,7 +273,7 @@ pub fn set_alignment(llglobal: &Value, align: Align) {
///
/// Inserts the comdat into `llmod` if it does not exist.
/// It is an error to call this if the target does not support comdat.
pub fn set_comdat(llmod: &Module, llglobal: &Value, name: &CStr) {
pub(crate) fn set_comdat(llmod: &Module, llglobal: &Value, name: &CStr) {
unsafe {
let comdat = LLVMGetOrInsertComdat(llmod, name.as_ptr());
LLVMSetComdat(llglobal, comdat);
@ -273,7 +281,7 @@ pub fn set_comdat(llmod: &Module, llglobal: &Value, name: &CStr) {
}
/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
pub fn get_param(llfn: &Value, index: c_uint) -> &Value {
pub(crate) fn get_param(llfn: &Value, index: c_uint) -> &Value {
unsafe {
assert!(
index < LLVMCountParams(llfn),
@ -286,7 +294,7 @@ pub fn get_param(llfn: &Value, index: c_uint) -> &Value {
}
/// Safe wrapper for `LLVMGetValueName2` into a byte slice
pub fn get_value_name(value: &Value) -> &[u8] {
pub(crate) fn get_value_name(value: &Value) -> &[u8] {
unsafe {
let mut len = 0;
let data = LLVMGetValueName2(value, &mut len);
@ -295,28 +303,28 @@ pub fn get_value_name(value: &Value) -> &[u8] {
}
/// Safe wrapper for `LLVMSetValueName2` from a byte slice
pub fn set_value_name(value: &Value, name: &[u8]) {
pub(crate) fn set_value_name(value: &Value, name: &[u8]) {
unsafe {
let data = name.as_c_char_ptr();
LLVMSetValueName2(value, data, name.len());
}
}
pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
pub(crate) fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
String::from_utf8(RustString::build_byte_buffer(f))
}
pub fn build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec<u8> {
pub(crate) fn build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec<u8> {
RustString::build_byte_buffer(f)
}
pub fn twine_to_string(tr: &Twine) -> String {
pub(crate) fn twine_to_string(tr: &Twine) -> String {
unsafe {
build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
}
}
pub fn last_error() -> Option<String> {
pub(crate) fn last_error() -> Option<String> {
unsafe {
let cstr = LLVMRustGetLastError();
if cstr.is_null() {

View file

@ -2,11 +2,6 @@ use std::borrow::Borrow;
use std::ops::Deref;
use std::sync::Arc;
// Use our fake Send/Sync traits when on not parallel compiler,
// so that `OwnedSlice` only implements/requires Send/Sync
// for parallel compiler builds.
use crate::sync;
/// An owned slice.
///
/// This is similar to `Arc<[u8]>` but allows slicing and using anything as the
@ -34,7 +29,7 @@ pub struct OwnedSlice {
// \/
// ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
#[expect(dead_code)]
owner: Arc<dyn sync::Send + sync::Sync>,
owner: Arc<dyn Send + Sync>,
}
/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
@ -61,7 +56,7 @@ pub struct OwnedSlice {
/// ```
pub fn slice_owned<O, F>(owner: O, slicer: F) -> OwnedSlice
where
O: sync::Send + sync::Sync + 'static,
O: Send + Sync + 'static,
F: FnOnce(&O) -> &[u8],
{
try_slice_owned(owner, |x| Ok::<_, !>(slicer(x))).into_ok()
@ -72,7 +67,7 @@ where
/// See [`slice_owned`] for the infallible version.
pub fn try_slice_owned<O, F, E>(owner: O, slicer: F) -> Result<OwnedSlice, E>
where
O: sync::Send + sync::Sync + 'static,
O: Send + Sync + 'static,
F: FnOnce(&O) -> Result<&[u8], E>,
{
// We wrap the owner of the bytes in, so it doesn't move.
@ -139,10 +134,10 @@ impl Borrow<[u8]> for OwnedSlice {
}
// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Send`
unsafe impl sync::Send for OwnedSlice {}
unsafe impl Send for OwnedSlice {}
// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Sync`
unsafe impl sync::Sync for OwnedSlice {}
unsafe impl Sync for OwnedSlice {}
#[cfg(test)]
mod tests;

View file

@ -18,14 +18,8 @@
//!
//! | Type | Serial version | Parallel version |
//! | ----------------------- | ------------------- | ------------------------------- |
//! |` Weak<T>` | `rc::Weak<T>` | `sync::Weak<T>` |
//! | `LRef<'a, T>` [^2] | `&'a mut T` | `&'a T` |
//! | | | |
//! | `AtomicBool` | `Cell<bool>` | `atomic::AtomicBool` |
//! | `AtomicU32` | `Cell<u32>` | `atomic::AtomicU32` |
//! | `AtomicU64` | `Cell<u64>` | `atomic::AtomicU64` |
//! | `AtomicUsize` | `Cell<usize>` | `atomic::AtomicUsize` |
//! | | | |
//! | `Lock<T>` | `RefCell<T>` | `RefCell<T>` or |
//! | | | `parking_lot::Mutex<T>` |
//! | `RwLock<T>` | `RefCell<T>` | `parking_lot::RwLock<T>` |
@ -103,18 +97,15 @@ mod mode {
// FIXME(parallel_compiler): Get rid of these aliases across the compiler.
pub use std::marker::{Send, Sync};
pub use std::sync::OnceLock;
// Use portable AtomicU64 for targets without native 64-bit atomics
#[cfg(target_has_atomic = "64")]
pub use std::sync::atomic::AtomicU64;
pub use std::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize};
pub use std::sync::{OnceLock, Weak};
pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
pub use parking_lot::{
MappedMutexGuard as MappedLockGuard, MappedRwLockReadGuard as MappedReadGuard,
MappedRwLockWriteGuard as MappedWriteGuard, RwLockReadGuard as ReadGuard,
RwLockWriteGuard as WriteGuard,
MappedRwLockReadGuard as MappedReadGuard, MappedRwLockWriteGuard as MappedWriteGuard,
RwLockReadGuard as ReadGuard, RwLockWriteGuard as WriteGuard,
};
#[cfg(not(target_has_atomic = "64"))]
pub use portable_atomic::AtomicU64;
@ -203,12 +194,6 @@ impl<T> RwLock<T> {
}
}
#[inline(always)]
#[track_caller]
pub fn with_read_lock<F: FnOnce(&T) -> R, R>(&self, f: F) -> R {
f(&*self.read())
}
#[inline(always)]
pub fn try_write(&self) -> Result<WriteGuard<'_, T>, ()> {
self.0.try_write().ok_or(())
@ -223,12 +208,6 @@ impl<T> RwLock<T> {
}
}
#[inline(always)]
#[track_caller]
pub fn with_write_lock<F: FnOnce(&mut T) -> R, R>(&self, f: F) -> R {
f(&mut *self.write())
}
#[inline(always)]
#[track_caller]
pub fn borrow(&self) -> ReadGuard<'_, T> {
@ -240,20 +219,4 @@ impl<T> RwLock<T> {
pub fn borrow_mut(&self) -> WriteGuard<'_, T> {
self.write()
}
#[inline(always)]
pub fn leak(&self) -> &T {
let guard = self.read();
let ret = unsafe { &*(&raw const *guard) };
std::mem::forget(guard);
ret
}
}
// FIXME: Probably a bad idea
impl<T: Clone> Clone for RwLock<T> {
#[inline]
fn clone(&self) -> Self {
RwLock::new(self.borrow().clone())
}
}

View file

@ -3,9 +3,9 @@ use std::intrinsics::likely;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;
use std::sync::atomic::Ordering;
use std::sync::atomic::{AtomicBool, Ordering};
use crate::sync::{AtomicBool, DynSend, DynSync, ReadGuard, RwLock, WriteGuard};
use crate::sync::{DynSend, DynSync, ReadGuard, RwLock, WriteGuard};
/// A type which allows mutation using a lock until
/// the value is frozen and can be accessed lock-free.

View file

@ -106,12 +106,6 @@ pub struct WorkerLocal<T> {
registry: Registry,
}
// This is safe because the `deref` call will return a reference to a `T` unique to each thread
// or it will panic for threads without an associated local. So there isn't a need for `T` to do
// it's own synchronization. The `verify` method on `RegistryId` has an issue where the id
// can be reused, but `WorkerLocal` has a reference to `Registry` which will prevent any reuse.
unsafe impl<T: Send> Sync for WorkerLocal<T> {}
impl<T> WorkerLocal<T> {
/// Creates a new worker local where the `initial` closure computes the
/// value this worker local should take for each thread in the registry.
@ -138,6 +132,11 @@ impl<T> Deref for WorkerLocal<T> {
fn deref(&self) -> &T {
// This is safe because `verify` will only return values less than
// `self.registry.thread_limit` which is the size of the `self.locals` array.
// The `deref` call will return a reference to a `T` unique to each thread
// or it will panic for threads without an associated local. So there isn't a need for `T` to do
// it's own synchronization. The `verify` method on `RegistryId` has an issue where the id
// can be reused, but `WorkerLocal` has a reference to `Registry` which will prevent any reuse.
unsafe { &self.locals.get_unchecked(self.registry.id().verify()).0 }
}
}

View file

@ -487,9 +487,11 @@ declare_features! (
(unstable, exhaustive_patterns, "1.13.0", Some(51085)),
/// Allows explicit tail calls via `become` expression.
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
/// Allows using `efiapi`, `sysv64` and `win64` as calling convention
/// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions
/// for functions with varargs.
(unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
/// Allows using `system` as a calling convention with varargs.
(unstable, extern_system_varargs, "CURRENT_RUSTC_VERSION", Some(136946)),
/// Allows defining `extern type`s.
(unstable, extern_types, "1.23.0", Some(43467)),
/// Allow using 128-bit (quad precision) floating point numbers.

View file

@ -351,6 +351,7 @@ language_item_table! {
PhantomData, sym::phantom_data, phantom_data, Target::Struct, GenericRequirement::Exact(1);
ManuallyDrop, sym::manually_drop, manually_drop, Target::Struct, GenericRequirement::None;
BikeshedGuaranteedNoDrop, sym::bikeshed_guaranteed_no_drop, bikeshed_guaranteed_no_drop, Target::Trait, GenericRequirement::Exact(0);
MaybeUninit, sym::maybe_uninit, maybe_uninit, Target::Union, GenericRequirement::None;

View file

@ -6,7 +6,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::MultiSpan;
use rustc_errors::codes::*;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::{Node, intravisit};
use rustc_hir::{LangItem, Node, intravisit};
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
use rustc_infer::traits::{Obligation, ObligationCauseCode};
use rustc_lint_defs::builtin::{
@ -27,6 +27,7 @@ use rustc_session::lint::builtin::UNINHABITED_STATIC;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_type_ir::fold::TypeFoldable;
use tracing::{debug, instrument};
use ty::TypingMode;
@ -87,89 +88,76 @@ fn allowed_union_or_unsafe_field<'tcx>(
typing_env: ty::TypingEnv<'tcx>,
span: Span,
) -> bool {
// We don't just accept all !needs_drop fields, due to semver concerns.
let allowed = match ty.kind() {
ty::Ref(..) => true, // references never drop (even mutable refs, which are non-Copy and hence fail the later check)
ty::Tuple(tys) => {
// allow tuples of allowed types
tys.iter().all(|ty| allowed_union_or_unsafe_field(tcx, ty, typing_env, span))
}
ty::Array(elem, _len) => {
// Like `Copy`, we do *not* special-case length 0.
allowed_union_or_unsafe_field(tcx, *elem, typing_env, span)
}
_ => {
// Fallback case: allow `ManuallyDrop` and things that are `Copy`,
// also no need to report an error if the type is unresolved.
ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop())
|| tcx.type_is_copy_modulo_regions(typing_env, ty)
|| ty.references_error()
}
};
if allowed && ty.needs_drop(tcx, typing_env) {
// This should never happen. But we can get here e.g. in case of name resolution errors.
tcx.dcx()
.span_delayed_bug(span, "we should never accept maybe-dropping union or unsafe fields");
// HACK (not that bad of a hack don't worry): Some codegen tests don't even define proper
// impls for `Copy`. Let's short-circuit here for this validity check, since a lot of them
// use unions. We should eventually fix all the tests to define that lang item or use
// minicore stubs.
if ty.is_trivially_pure_clone_copy() {
return true;
}
allowed
// If `BikeshedGuaranteedNoDrop` is not defined in a `#[no_core]` test, fall back to `Copy`.
// This is an underapproximation of `BikeshedGuaranteedNoDrop`,
let def_id = tcx
.lang_items()
.get(LangItem::BikeshedGuaranteedNoDrop)
.unwrap_or_else(|| tcx.require_lang_item(LangItem::Copy, Some(span)));
let Ok(ty) = tcx.try_normalize_erasing_regions(typing_env, ty) else {
tcx.dcx().span_delayed_bug(span, "could not normalize field type");
return true;
};
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
infcx.predicate_must_hold_modulo_regions(&Obligation::new(
tcx,
ObligationCause::dummy_with_span(span),
param_env,
ty::TraitRef::new(tcx, def_id, [ty]),
))
}
/// Check that the fields of the `union` do not need dropping.
fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool {
let item_type = tcx.type_of(item_def_id).instantiate_identity();
if let ty::Adt(def, args) = item_type.kind() {
assert!(def.is_union());
let def = tcx.adt_def(item_def_id);
assert!(def.is_union());
let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
for field in &def.non_enum_variant().fields {
let Ok(field_ty) = tcx.try_normalize_erasing_regions(typing_env, field.ty(tcx, args))
else {
tcx.dcx().span_delayed_bug(span, "could not normalize field type");
continue;
let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
let args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
for field in &def.non_enum_variant().fields {
if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) {
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
// We are currently checking the type this field came from, so it must be local.
Some(Node::Field(field)) => (field.span, field.ty.span),
_ => unreachable!("mir field has to correspond to hir field"),
};
if !allowed_union_or_unsafe_field(tcx, field_ty, typing_env, span) {
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
// We are currently checking the type this field came from, so it must be local.
Some(Node::Field(field)) => (field.span, field.ty.span),
_ => unreachable!("mir field has to correspond to hir field"),
};
tcx.dcx().emit_err(errors::InvalidUnionField {
field_span,
sugg: errors::InvalidUnionFieldSuggestion {
lo: ty_span.shrink_to_lo(),
hi: ty_span.shrink_to_hi(),
},
note: (),
});
return false;
}
tcx.dcx().emit_err(errors::InvalidUnionField {
field_span,
sugg: errors::InvalidUnionFieldSuggestion {
lo: ty_span.shrink_to_lo(),
hi: ty_span.shrink_to_hi(),
},
note: (),
});
return false;
}
} else {
span_bug!(span, "unions must be ty::Adt, but got {:?}", item_type.kind());
}
true
}
/// Check that the unsafe fields do not need dropping.
fn check_unsafe_fields(tcx: TyCtxt<'_>, item_def_id: LocalDefId) {
let span = tcx.def_span(item_def_id);
let item_type = tcx.type_of(item_def_id).instantiate_identity();
let ty::Adt(def, args) = item_type.kind() else {
span_bug!(span, "structs/enums must be ty::Adt, but got {:?}", item_type.kind());
};
let def = tcx.adt_def(item_def_id);
let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
let args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
for field in def.all_fields() {
if !field.safety.is_unsafe() {
continue;
}
let Ok(field_ty) = tcx.try_normalize_erasing_regions(typing_env, field.ty(tcx, args))
else {
tcx.dcx().span_delayed_bug(span, "could not normalize field type");
continue;
};
if !allowed_union_or_unsafe_field(tcx, field_ty, typing_env, span) {
if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) {
let hir::Node::Field(field) = tcx.hir_node_by_def_id(field.did.expect_local()) else {
unreachable!("field has to correspond to hir field")
};

View file

@ -122,28 +122,42 @@ fn require_c_abi_if_c_variadic(
const UNSTABLE_EXPLAIN: &str =
"using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
// ABIs which can stably use varargs
if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) {
return;
}
// ABIs with feature-gated stability
let extended_abi_support = tcx.features().extended_varargs_abi_support();
let conventions = match (extended_abi_support, abi.supports_varargs()) {
// User enabled additional ABI support for varargs and function ABI matches those ones.
(true, true) => return,
let extern_system_varargs = tcx.features().extern_system_varargs();
// Using this ABI would be ok, if the feature for additional ABI support was enabled.
// Return CONVENTIONS_STABLE, because we want the other error to look the same.
(false, true) => {
feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
.emit();
CONVENTIONS_STABLE
}
(false, false) => CONVENTIONS_STABLE,
(true, false) => CONVENTIONS_UNSTABLE,
// If the feature gate has been enabled, we can stop here
if extern_system_varargs && let ExternAbi::System { .. } = abi {
return;
};
if extended_abi_support && abi.supports_varargs() {
return;
};
tcx.dcx().emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions });
// Looks like we need to pick an error to emit.
// Is there any feature which we could have enabled to make this work?
match abi {
ExternAbi::System { .. } => {
feature_err(&tcx.sess, sym::extern_system_varargs, span, UNSTABLE_EXPLAIN)
}
abi if abi.supports_varargs() => {
feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
}
_ => tcx.dcx().create_err(errors::VariadicFunctionCompatibleConvention {
span,
conventions: if tcx.sess.opts.unstable_features.is_nightly_build() {
CONVENTIONS_UNSTABLE
} else {
CONVENTIONS_STABLE
},
}),
}
.emit();
}
pub fn provide(providers: &mut Providers) {

View file

@ -892,57 +892,75 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
let tcx = self.cx.tcx();
self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
if let PatKind::Binding(_, canonical_id, ..) = pat.kind {
debug!("walk_pat: binding place={:?} pat={:?}", place, pat);
if let Some(bm) =
self.cx.typeck_results().extract_binding_mode(tcx.sess, pat.hir_id, pat.span)
{
debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
match pat.kind {
PatKind::Binding(_, canonical_id, ..) => {
debug!("walk_pat: binding place={:?} pat={:?}", place, pat);
if let Some(bm) = self
.cx
.typeck_results()
.extract_binding_mode(tcx.sess, pat.hir_id, pat.span)
{
debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
// pat_ty: the type of the binding being produced.
let pat_ty = self.node_ty(pat.hir_id)?;
debug!("walk_pat: pat_ty={:?}", pat_ty);
// pat_ty: the type of the binding being produced.
let pat_ty = self.node_ty(pat.hir_id)?;
debug!("walk_pat: pat_ty={:?}", pat_ty);
let def = Res::Local(canonical_id);
if let Ok(ref binding_place) = self.cat_res(pat.hir_id, pat.span, pat_ty, def) {
self.delegate.borrow_mut().bind(binding_place, binding_place.hir_id);
}
// Subtle: MIR desugaring introduces immutable borrows for each pattern
// binding when lowering pattern guards to ensure that the guard does not
// modify the scrutinee.
if has_guard {
self.delegate.borrow_mut().borrow(
place,
discr_place.hir_id,
BorrowKind::Immutable,
);
}
// It is also a borrow or copy/move of the value being matched.
// In a cases of pattern like `let pat = upvar`, don't use the span
// of the pattern, as this just looks confusing, instead use the span
// of the discriminant.
match bm.0 {
hir::ByRef::Yes(m) => {
let bk = ty::BorrowKind::from_mutbl(m);
self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
let def = Res::Local(canonical_id);
if let Ok(ref binding_place) =
self.cat_res(pat.hir_id, pat.span, pat_ty, def)
{
self.delegate.borrow_mut().bind(binding_place, binding_place.hir_id);
}
hir::ByRef::No => {
debug!("walk_pat binding consuming pat");
self.consume_or_copy(place, discr_place.hir_id);
// Subtle: MIR desugaring introduces immutable borrows for each pattern
// binding when lowering pattern guards to ensure that the guard does not
// modify the scrutinee.
if has_guard {
self.delegate.borrow_mut().borrow(
place,
discr_place.hir_id,
BorrowKind::Immutable,
);
}
// It is also a borrow or copy/move of the value being matched.
// In a cases of pattern like `let pat = upvar`, don't use the span
// of the pattern, as this just looks confusing, instead use the span
// of the discriminant.
match bm.0 {
hir::ByRef::Yes(m) => {
let bk = ty::BorrowKind::from_mutbl(m);
self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
}
hir::ByRef::No => {
debug!("walk_pat binding consuming pat");
self.consume_or_copy(place, discr_place.hir_id);
}
}
}
}
} else if let PatKind::Deref(subpattern) = pat.kind {
// A deref pattern is a bit special: the binding mode of its inner bindings
// determines whether to borrow *at the level of the deref pattern* rather than
// borrowing the bound place (since that inner place is inside the temporary that
// stores the result of calling `deref()`/`deref_mut()` so can't be captured).
let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpattern);
let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
let bk = ty::BorrowKind::from_mutbl(mutability);
self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
PatKind::Deref(subpattern) => {
// A deref pattern is a bit special: the binding mode of its inner bindings
// determines whether to borrow *at the level of the deref pattern* rather than
// borrowing the bound place (since that inner place is inside the temporary that
// stores the result of calling `deref()`/`deref_mut()` so can't be captured).
let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpattern);
let mutability =
if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
let bk = ty::BorrowKind::from_mutbl(mutability);
self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
}
PatKind::Never => {
// A `!` pattern always counts as an immutable read of the discriminant,
// even in an irrefutable pattern.
self.delegate.borrow_mut().borrow(
place,
discr_place.hir_id,
BorrowKind::Immutable,
);
}
_ => {}
}
Ok(())

View file

@ -1991,17 +1991,18 @@ struct InferBorrowKind<'tcx> {
impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
fn fake_read(
&mut self,
place: &PlaceWithHirId<'tcx>,
place_with_id: &PlaceWithHirId<'tcx>,
cause: FakeReadCause,
diag_expr_id: HirId,
) {
let PlaceBase::Upvar(_) = place.place.base else { return };
let PlaceBase::Upvar(_) = place_with_id.place.base else { return };
// We need to restrict Fake Read precision to avoid fake reading unsafe code,
// such as deref of a raw pointer.
let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::Immutable);
let (place, _) = restrict_capture_precision(place.place.clone(), dummy_capture_kind);
let (place, _) =
restrict_capture_precision(place_with_id.place.clone(), dummy_capture_kind);
let (place, _) = restrict_repr_packed_field_ref_capture(place, dummy_capture_kind);
self.fake_reads.push((place, cause, diag_expr_id));

View file

@ -168,6 +168,8 @@ pub enum SelectionCandidate<'tcx> {
BuiltinObjectCandidate,
BuiltinUnsizeCandidate,
BikeshedGuaranteedNoDropCandidate,
}
/// The result of trait evaluation. The order is important

View file

@ -217,6 +217,10 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
self.is_phantom_data()
}
fn is_manually_drop(self) -> bool {
self.is_manually_drop()
}
fn all_field_tys(
self,
tcx: TyCtxt<'tcx>,

View file

@ -690,6 +690,7 @@ bidirectional_lang_item_map! {
AsyncFnOnce,
AsyncFnOnceOutput,
AsyncIterator,
BikeshedGuaranteedNoDrop,
CallOnceFuture,
CallRefFuture,
Clone,

View file

@ -267,6 +267,11 @@ where
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution>;
fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution>;
/// Consider (possibly several) candidates to upcast or unsize a type to another
/// type, excluding the coercion of a sized type into a `dyn Trait`.
///
@ -478,6 +483,9 @@ where
Some(TraitSolverLangItem::TransmuteTrait) => {
G::consider_builtin_transmute_candidate(self, goal)
}
Some(TraitSolverLangItem::BikeshedGuaranteedNoDrop) => {
G::consider_builtin_bikeshed_guaranteed_no_drop_candidate(self, goal)
}
_ => Err(NoSolution),
}
};

View file

@ -374,6 +374,13 @@ where
unreachable!("TransmuteFrom is not const")
}
fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("BikeshedGuaranteedNoDrop is not const");
}
fn consider_structural_builtin_unsize_candidates(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,

View file

@ -942,6 +942,13 @@ where
) -> Result<Candidate<I>, NoSolution> {
panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
}
fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
_ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("`BikeshedGuaranteedNoDrop` does not have an associated type: {:?}", goal)
}
}
impl<D, I> EvalCtxt<'_, D>

View file

@ -625,6 +625,101 @@ where
})
}
/// NOTE: This is implemented as a built-in goal and not a set of impls like:
///
/// ```rust,ignore (illustrative)
/// impl<T> BikeshedGuaranteedNoDrop for T where T: Copy {}
/// impl<T> BikeshedGuaranteedNoDrop for ManuallyDrop<T> {}
/// ```
///
/// because these impls overlap, and I'd rather not build a coherence hack for
/// this harmless overlap.
fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
return Err(NoSolution);
}
let cx = ecx.cx();
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
let ty = goal.predicate.self_ty();
match ty.kind() {
// `&mut T` and `&T` always implement `BikeshedGuaranteedNoDrop`.
ty::Ref(..) => {}
// `ManuallyDrop<T>` always implements `BikeshedGuaranteedNoDrop`.
ty::Adt(def, _) if def.is_manually_drop() => {}
// Arrays and tuples implement `BikeshedGuaranteedNoDrop` only if
// their constituent types implement `BikeshedGuaranteedNoDrop`.
ty::Tuple(tys) => {
ecx.add_goals(
GoalSource::ImplWhereBound,
tys.iter().map(|elem_ty| {
goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty]))
}),
);
}
ty::Array(elem_ty, _) => {
ecx.add_goal(
GoalSource::ImplWhereBound,
goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])),
);
}
// All other types implement `BikeshedGuaranteedNoDrop` only if
// they implement `Copy`. We could be smart here and short-circuit
// some trivially `Copy`/`!Copy` types, but there's no benefit.
ty::FnDef(..)
| ty::FnPtr(..)
| ty::Error(_)
| ty::Uint(_)
| ty::Int(_)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Bool
| ty::Float(_)
| ty::Char
| ty::RawPtr(..)
| ty::Never
| ty::Pat(..)
| ty::Dynamic(..)
| ty::Str
| ty::Slice(_)
| ty::Foreign(..)
| ty::Adt(..)
| ty::Alias(..)
| ty::Param(_)
| ty::Placeholder(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::UnsafeBinder(_)
| ty::CoroutineWitness(..) => {
ecx.add_goal(
GoalSource::ImplWhereBound,
goal.with(
cx,
ty::TraitRef::new(
cx,
cx.require_lang_item(TraitSolverLangItem::Copy),
[ty],
),
),
);
}
ty::Bound(..)
| ty::Infer(
ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
) => {
panic!("unexpected type `{ty:?}`")
}
}
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
/// ```ignore (builtin impl example)
/// trait Trait {
/// fn foo(&self);

View file

@ -4,14 +4,14 @@ use std::fmt::Debug;
use std::hash::Hash;
use std::marker::PhantomData;
use std::sync::Arc;
use std::sync::atomic::Ordering;
use std::sync::atomic::{AtomicU32, Ordering};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef};
use rustc_data_structures::sharded::{self, Sharded};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock};
use rustc_data_structures::sync::{AtomicU64, Lock};
use rustc_data_structures::unord::UnordMap;
use rustc_index::IndexVec;
use rustc_macros::{Decodable, Encodable};

View file

@ -516,6 +516,7 @@ symbols! {
bang,
begin_panic,
bench,
bikeshed_guaranteed_no_drop,
bin,
binaryheap_iter,
bind_by_move_pattern_guards,
@ -880,6 +881,7 @@ symbols! {
extern_crate_self,
extern_in_paths,
extern_prelude,
extern_system_varargs,
extern_types,
external,
external_doc,

View file

@ -0,0 +1,46 @@
use std::borrow::Cow;
use crate::spec::{Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions, cvs};
pub(crate) fn opts() -> TargetOptions {
let mut pre_link_args = TargetOptions::link_args(
LinkerFlavor::Gnu(Cc::No, Lld::No),
&["--disable-dynamicbase", "--enable-auto-image-base"],
);
crate::spec::add_link_args(
&mut pre_link_args,
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
&["-Wl,--disable-dynamicbase", "-Wl,--enable-auto-image-base"],
);
let cygwin_libs = &["-lcygwin", "-lgcc", "-lcygwin", "-luser32", "-lkernel32", "-lgcc_s"];
let mut late_link_args =
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), cygwin_libs);
crate::spec::add_link_args(
&mut late_link_args,
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
cygwin_libs,
);
TargetOptions {
os: "cygwin".into(),
vendor: "pc".into(),
// FIXME(#13846) this should be enabled for cygwin
function_sections: false,
linker: Some("gcc".into()),
dynamic_linking: true,
dll_prefix: "".into(),
dll_suffix: ".dll".into(),
exe_suffix: ".exe".into(),
families: cvs!["unix"],
is_like_windows: true,
allows_weak_linkage: false,
pre_link_args,
late_link_args,
abi_return_struct_as_int: true,
emit_debug_gdb_scripts: false,
requires_uwtable: true,
eh_frame_header: false,
debuginfo_kind: DebuginfoKind::Dwarf,
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
..Default::default()
}
}

View file

@ -3,6 +3,7 @@ pub(crate) mod android;
pub(crate) mod apple;
pub(crate) mod avr_gnu;
pub(crate) mod bpf;
pub(crate) mod cygwin;
pub(crate) mod dragonfly;
pub(crate) mod freebsd;
pub(crate) mod fuchsia;

View file

@ -2013,6 +2013,7 @@ supported_targets! {
("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
("x86_64-pc-cygwin", x86_64_pc_cygwin),
}
/// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>
@ -2994,8 +2995,8 @@ impl Target {
);
check_eq!(
self.is_like_windows,
self.os == "windows" || self.os == "uefi",
"`is_like_windows` must be set if and only if `os` is `windows` or `uefi`"
self.os == "windows" || self.os == "uefi" || self.os == "cygwin",
"`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
);
check_eq!(
self.is_like_wasm,

View file

@ -0,0 +1,24 @@
use crate::spec::{Cc, LinkerFlavor, Lld, Target, base};
pub(crate) fn target() -> Target {
let mut base = base::cygwin::opts();
base.cpu = "x86-64".into();
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &["-m", "i386pep"]);
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.max_atomic_width = Some(64);
base.linker = Some("x86_64-pc-cygwin-gcc".into());
Target {
llvm_target: "x86_64-pc-cygwin".into(),
pointer_width: 64,
data_layout:
"e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
arch: "x86_64".into(),
options: base,
metadata: crate::spec::TargetMetadata {
description: Some("64-bit x86 Cygwin".into()),
tier: Some(3),
host_tools: Some(false),
std: None,
},
}
}

View file

@ -102,6 +102,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.assemble_candidate_for_tuple(obligation, &mut candidates);
} else if tcx.is_lang_item(def_id, LangItem::FnPtrTrait) {
self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
} else if tcx.is_lang_item(def_id, LangItem::BikeshedGuaranteedNoDrop) {
self.assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
obligation,
&mut candidates,
);
} else {
if tcx.is_lang_item(def_id, LangItem::Clone) {
// Same builtin conditions as `Copy`, i.e., every type which has builtin support
@ -1184,4 +1189,48 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
}
fn assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
match obligation.predicate.self_ty().skip_binder().kind() {
ty::Ref(..)
| ty::Adt(..)
| ty::Tuple(_)
| ty::Array(..)
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::Error(_)
| ty::Uint(_)
| ty::Int(_)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Bool
| ty::Float(_)
| ty::Char
| ty::RawPtr(..)
| ty::Never
| ty::Pat(..)
| ty::Dynamic(..)
| ty::Str
| ty::Slice(_)
| ty::Foreign(..)
| ty::Alias(..)
| ty::Param(_)
| ty::Placeholder(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::UnsafeBinder(_)
| ty::CoroutineWitness(..)
| ty::Bound(..) => {
candidates.vec.push(BikeshedGuaranteedNoDropCandidate);
}
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
candidates.ambiguous = true;
}
}
}
}

View file

@ -20,6 +20,7 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, Upcast};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
use rustc_type_ir::elaborate;
use thin_vec::thin_vec;
use tracing::{debug, instrument};
use super::SelectionCandidate::{self, *};
@ -130,6 +131,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
TraitUpcastingUnsizeCandidate(idx) => {
self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?
}
BikeshedGuaranteedNoDropCandidate => {
self.confirm_bikeshed_guaranteed_no_drop_candidate(obligation)
}
};
// The obligations returned by confirmation are recursively evaluated
@ -1346,6 +1351,93 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => bug!("source: {source}, target: {target}"),
})
}
fn confirm_bikeshed_guaranteed_no_drop_candidate(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
) -> ImplSource<'tcx, PredicateObligation<'tcx>> {
let mut obligations = thin_vec![];
let tcx = self.tcx();
let self_ty = obligation.predicate.self_ty();
match *self_ty.skip_binder().kind() {
// `&mut T` and `&T` always implement `BikeshedGuaranteedNoDrop`.
ty::Ref(..) => {}
// `ManuallyDrop<T>` always implements `BikeshedGuaranteedNoDrop`.
ty::Adt(def, _) if def.is_manually_drop() => {}
// Arrays and tuples implement `BikeshedGuaranteedNoDrop` only if
// their constituent types implement `BikeshedGuaranteedNoDrop`.
ty::Tuple(tys) => {
obligations.extend(tys.iter().map(|elem_ty| {
obligation.with(
tcx,
self_ty.rebind(ty::TraitRef::new(
tcx,
obligation.predicate.def_id(),
[elem_ty],
)),
)
}));
}
ty::Array(elem_ty, _) => {
obligations.push(obligation.with(
tcx,
self_ty.rebind(ty::TraitRef::new(
tcx,
obligation.predicate.def_id(),
[elem_ty],
)),
));
}
// All other types implement `BikeshedGuaranteedNoDrop` only if
// they implement `Copy`. We could be smart here and short-circuit
// some trivially `Copy`/`!Copy` types, but there's no benefit.
ty::FnDef(..)
| ty::FnPtr(..)
| ty::Error(_)
| ty::Uint(_)
| ty::Int(_)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Bool
| ty::Float(_)
| ty::Char
| ty::RawPtr(..)
| ty::Never
| ty::Pat(..)
| ty::Dynamic(..)
| ty::Str
| ty::Slice(_)
| ty::Foreign(..)
| ty::Adt(..)
| ty::Alias(..)
| ty::Param(_)
| ty::Placeholder(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::UnsafeBinder(_)
| ty::CoroutineWitness(..)
| ty::Bound(..) => {
obligations.push(obligation.with(
tcx,
self_ty.map_bound(|ty| {
ty::TraitRef::new(
tcx,
tcx.require_lang_item(LangItem::Copy, Some(obligation.cause.span)),
[ty],
)
}),
));
}
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
panic!("unexpected type `{self_ty:?}`")
}
}
ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
}
}
/// Compute a goal that some RPITIT (right now, only RPITITs corresponding to Futures)

View file

@ -1949,7 +1949,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
| TraitAliasCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinObjectCandidate
| BuiltinUnsizeCandidate => false,
| BuiltinUnsizeCandidate
| BikeshedGuaranteedNoDropCandidate => false,
// Non-global param candidates have already been handled, global
// where-bounds get ignored.
ParamCandidate(_) | ImplCandidate(_) => true,

View file

@ -881,7 +881,10 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
ty.map_bound(|ty| {
ty::TraitRef::new(
self.tcx(),
self.tcx().require_lang_item(LangItem::Copy, Some(self.span)),
self.tcx().require_lang_item(
LangItem::BikeshedGuaranteedNoDrop,
Some(self.span),
),
[ty],
)
}),

View file

@ -540,6 +540,8 @@ pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
fn is_phantom_data(self) -> bool;
fn is_manually_drop(self) -> bool;
// FIXME: perhaps use `all_fields` and expose `FieldDef`.
fn all_field_tys(self, interner: I) -> ty::EarlyBinder<I, impl IntoIterator<Item = I::Ty>>;

View file

@ -10,6 +10,7 @@ pub enum TraitSolverLangItem {
AsyncFnOnce,
AsyncFnOnceOutput,
AsyncIterator,
BikeshedGuaranteedNoDrop,
CallOnceFuture,
CallRefFuture,
Clone,

View file

@ -595,11 +595,6 @@
# Whether to always use incremental compilation when building rustc
#incremental = false
# Build a multi-threaded rustc. This allows users to use parallel rustc
# via the unstable option `-Z threads=n`.
# This option is deprecated and always true.
#parallel-compiler = true
# The default linker that will be hard-coded into the generated
# compiler for targets that don't specify a default linker explicitly
# in their target specifications. Note that this is not the linker

View file

@ -453,6 +453,23 @@ impl Copy for ! {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Copy for &T {}
/// Marker trait for the types that are allowed in union fields, unsafe fields,
/// and unsafe binder types.
///
/// Implemented for:
/// * `&T`, `&mut T` for all `T`,
/// * `ManuallyDrop<T>` for all `T`,
/// * tuples and arrays whose elements implement `BikeshedGuaranteedNoDrop`,
/// * or otherwise, all types that are `Copy`.
///
/// Notably, this doesn't include all trivially-destructible types for semver
/// reasons.
///
/// Bikeshed name for now.
#[unstable(feature = "bikeshed_guaranteed_no_drop", issue = "none")]
#[cfg_attr(not(bootstrap), lang = "bikeshed_guaranteed_no_drop")]
pub trait BikeshedGuaranteedNoDrop {}
/// Types for which it is safe to share references between threads.
///
/// This trait is automatically implemented when the compiler determines

View file

@ -1,5 +1,3 @@
use std::time::Instant;
#[cfg(not(target_arch = "wasm32"))]
use test::{Bencher, black_box};
@ -10,6 +8,7 @@ macro_rules! bench_instant_threaded {
fn $bench_name(b: &mut Bencher) -> std::thread::Result<()> {
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Instant;
let running = Arc::new(AtomicBool::new(true));

View file

@ -245,7 +245,11 @@ impl Cargo {
// flesh out rpath support more fully in the future.
self.rustflags.arg("-Zosx-rpath-install-name");
Some(format!("-Wl,-rpath,@loader_path/../{libdir}"))
} else if !target.is_windows() && !target.contains("aix") && !target.contains("xous") {
} else if !target.is_windows()
&& !target.contains("cygwin")
&& !target.contains("aix")
&& !target.contains("xous")
{
self.rustflags.arg("-Clink-args=-Wl,-z,origin");
Some(format!("-Wl,-rpath,$ORIGIN/../{libdir}"))
} else {

View file

@ -46,8 +46,6 @@ are implemented differently depending on whether `parallel-compiler` is true.
| data structure | parallel | non-parallel |
| -------------------------------- | --------------------------------------------------- | ------------ |
| Weak | std::sync::Weak | std::rc::Weak |
| Atomic{Bool}/{Usize}/{U32}/{U64} | std::sync::atomic::Atomic{Bool}/{Usize}/{U32}/{U64} | (std::cell::Cell<bool/usize/u32/u64>) |
| OnceCell | std::sync::OnceLock | std::cell::OnceCell |
| Lock\<T> | (parking_lot::Mutex\<T>) | (std::cell::RefCell) |
| RwLock\<T> | (parking_lot::RwLock\<T>) | (std::cell::RefCell) |
@ -58,7 +56,6 @@ are implemented differently depending on whether `parallel-compiler` is true.
| WriteGuard | parking_lot::RwLockWriteGuard | std::cell::RefMut |
| MappedWriteGuard | parking_lot::MappedRwLockWriteGuard | std::cell::RefMut |
| LockGuard | parking_lot::MutexGuard | std::cell::RefMut |
| MappedLockGuard | parking_lot::MappedMutexGuard | std::cell::RefMut |
- These thread-safe data structures are interspersed during compilation which
can cause lock contention resulting in degraded performance as the number of
@ -173,12 +170,10 @@ Here are some resources that can be used to learn more:
- [This list of interior mutability in the compiler by nikomatsakis][imlist]
[`rayon`]: https://crates.io/crates/rayon
[Arc]: https://doc.rust-lang.org/std/sync/struct.Arc.html
[imlist]: https://github.com/nikomatsakis/rustc-parallelization/blob/master/interior-mutability-list.md
[irlo0]: https://internals.rust-lang.org/t/parallelizing-rustc-using-rayon/6606
[irlo1]: https://internals.rust-lang.org/t/help-test-parallel-rustc/11503
[monomorphization]: backend/monomorph.md
[parallel-rustdoc]: https://github.com/rust-lang/rust/issues/82741
[Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html
[rustc-rayon]: https://github.com/rust-lang/rustc-rayon
[tracking]: https://github.com/rust-lang/rust/issues/48685

View file

@ -102,6 +102,7 @@
- [\*-win7-windows-gnu](platform-support/win7-windows-gnu.md)
- [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
- [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
- [x86_64-pc-cygwin](platform-support/x86_64-pc-cygwin.md)
- [x86_64-pc-solaris](platform-support/solaris.md)
- [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md)
- [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)

View file

@ -407,6 +407,7 @@ target | std | host | notes
[`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly
[`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS
[`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator
[`x86_64-pc-cygwin`](platform-support/x86_64-pc-cygwin.md) | ? | | 64-bit x86 Cygwin |
[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with default network stack (io-pkt) |
[`x86_64-pc-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with new network stack (io-sock) |
[`x86_64-pc-nto-qnx800`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 8.0 RTOS |

View file

@ -0,0 +1,39 @@
# `x86_64-pc-cygwin`
**Tier: 3**
Windows targets supporting Cygwin.
The `*-cygwin` targets are **not** intended as native target for applications,
a developer writing Windows applications should use the `*-pc-windows-*` targets instead, which are *native* Windows.
Cygwin is only intended as an emulation layer for Unix-only programs which do not support the native Windows targets.
## Target maintainers
- [Berrysoft](https://github.com/Berrysoft)
## Requirements
This target is cross compiled. It needs `x86_64-pc-cygwin-gcc` as linker.
The `target_os` of the target is `cygwin`, and it is `unix`.
## Building the target
For cross-compilation you want LLVM with [llvm/llvm-project#121439 (merged)](https://github.com/llvm/llvm-project/pull/121439) applied to fix the LLVM codegen on importing external global variables from DLLs.
No native builds on Cygwin now. It should be possible theoretically though, but might need a lot of patches.
## Building Rust programs
Rust does not yet ship pre-compiled artifacts for this target. To compile for
this target, you will either need to build Rust with the target enabled (see
"Building the target" above), or build your own copy of `core` by using
`build-std` or similar.
## Testing
Created binaries work fine on Windows with Cygwin.
## Cross-compilation toolchains and C code
Compatible C code can be built with GCC shipped with Cygwin. Clang is untested.

View file

@ -84,6 +84,9 @@
//@ revisions: x86_64_win7_windows_msvc
//@ [x86_64_win7_windows_msvc] compile-flags: --target x86_64-win7-windows-msvc
//@ [x86_64_win7_windows_msvc] needs-llvm-components: x86
//@ revisions: x86_64_pc_cygwin
//@ [x86_64_pc_cygwin] compile-flags: --target x86_64-pc-cygwin
//@ [x86_64_pc_cygwin] needs-llvm-components: x86
// Sanity-check that each target can produce assembly code.

View file

@ -39,6 +39,9 @@ impl<T: ?Sized> LegacyReceiver for &mut T {}
#[lang = "copy"]
pub trait Copy: Sized {}
#[lang = "bikeshed_guaranteed_no_drop"]
pub trait BikeshedGuaranteedNoDrop {}
impl_marker_trait!(
Copy => [
bool, char,

View file

@ -1,18 +1,15 @@
//@ only-x86_64
fn efiapi(f: extern "efiapi" fn(usize, ...)) {
//~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
//~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
//~^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
f(22, 44);
}
fn sysv(f: extern "sysv64" fn(usize, ...)) {
//~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
//~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
//~^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
f(22, 44);
}
fn win(f: extern "win64" fn(usize, ...)) {
//~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
//~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
//~^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
f(22, 44);
}

View file

@ -8,14 +8,8 @@ LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) {
= help: add `#![feature(extended_varargs_abi_support)]` 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[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
--> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14
|
LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
--> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12
--> $DIR/feature-gate-extended_varargs_abi_support.rs:7:12
|
LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -24,14 +18,8 @@ LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
= help: add `#![feature(extended_varargs_abi_support)]` 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[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
--> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12
|
LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
--> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11
--> $DIR/feature-gate-extended_varargs_abi_support.rs:11:11
|
LL | fn win(f: extern "win64" fn(usize, ...)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -40,13 +28,6 @@ LL | fn win(f: extern "win64" fn(usize, ...)) {
= help: add `#![feature(extended_varargs_abi_support)]` 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[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
--> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11
|
LL | fn win(f: extern "win64" fn(usize, ...)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
error: aborting due to 3 previous errors
error: aborting due to 6 previous errors
Some errors have detailed explanations: E0045, E0658.
For more information about an error, try `rustc --explain E0045`.
For more information about this error, try `rustc --explain E0658`.

View file

@ -1,4 +1,4 @@
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`
--> $DIR/variadic-ffi-1.rs:9:5
|
LL | fn printf(_: *const u8, ...);

View file

@ -8,9 +8,6 @@ fn baz(f: extern "stdcall" fn(usize, ...)) {
f(22, 44);
}
fn system(f: extern "system" fn(usize, ...)) {
f(22, 44);
}
#[cfg(target_arch = "x86_64")]
fn sysv(f: extern "sysv64" fn(usize, ...)) {
f(22, 44);

View file

@ -201,7 +201,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
LL | target_os = "_UNEXPECTED_VALUE",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@ -274,7 +274,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
| |
| help: there is a expected value with a similar name: `"linux"`
|
= note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: 28 warnings emitted

View file

@ -39,4 +39,4 @@ type WithTransparentTraitObject =
//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);
//~^ ERROR C-variadic function must have a compatible calling convention, like `C` or `cdecl` [E0045]
//~^ ERROR C-variadic function must have a compatible calling convention, like `C`

View file

@ -69,7 +69,7 @@ LL | extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTranspa
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`
--> $DIR/generics.rs:41:20
|
LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);

View file

@ -1,12 +1,12 @@
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
//@ needs-llvm-components: arm
//@ add-core-stubs
#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items)]
#![no_core]
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
pub trait Copy {}
impl Copy for u32 {}
extern crate minicore;
use minicore::*;
#[repr(C)]
pub struct ReprCU64(u64);

View file

@ -1,13 +1,12 @@
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
//@ needs-llvm-components: arm
//@ add-core-stubs
#![feature(cmse_nonsecure_entry, no_core, lang_items)]
#![no_core]
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
pub trait Copy {}
impl Copy for u32 {}
impl Copy for u8 {}
extern crate minicore;
use minicore::*;
#[repr(C)]
pub struct ReprCU64(u64);

View file

@ -1,5 +1,5 @@
error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:25:48
--> $DIR/return-via-stack.rs:24:48
|
LL | pub extern "C-cmse-nonsecure-entry" fn f1() -> ReprCU64 {
| ^^^^^^^^ this type doesn't fit in the available registers
@ -8,7 +8,7 @@ LL | pub extern "C-cmse-nonsecure-entry" fn f1() -> ReprCU64 {
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:30:48
--> $DIR/return-via-stack.rs:29:48
|
LL | pub extern "C-cmse-nonsecure-entry" fn f2() -> ReprCBytes {
| ^^^^^^^^^^ this type doesn't fit in the available registers
@ -17,7 +17,7 @@ LL | pub extern "C-cmse-nonsecure-entry" fn f2() -> ReprCBytes {
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:35:48
--> $DIR/return-via-stack.rs:34:48
|
LL | pub extern "C-cmse-nonsecure-entry" fn f3() -> U64Compound {
| ^^^^^^^^^^^ this type doesn't fit in the available registers
@ -26,7 +26,7 @@ LL | pub extern "C-cmse-nonsecure-entry" fn f3() -> U64Compound {
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:40:48
--> $DIR/return-via-stack.rs:39:48
|
LL | pub extern "C-cmse-nonsecure-entry" fn f4() -> ReprCAlign16 {
| ^^^^^^^^^^^^ this type doesn't fit in the available registers
@ -35,7 +35,7 @@ LL | pub extern "C-cmse-nonsecure-entry" fn f4() -> ReprCAlign16 {
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:47:48
--> $DIR/return-via-stack.rs:46:48
|
LL | pub extern "C-cmse-nonsecure-entry" fn f5() -> [u8; 5] {
| ^^^^^^^ this type doesn't fit in the available registers
@ -44,7 +44,7 @@ LL | pub extern "C-cmse-nonsecure-entry" fn f5() -> [u8; 5] {
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:53:50
--> $DIR/return-via-stack.rs:52:50
|
LL | pub extern "C-cmse-nonsecure-entry" fn u128() -> u128 {
| ^^^^ this type doesn't fit in the available registers
@ -53,7 +53,7 @@ LL | pub extern "C-cmse-nonsecure-entry" fn u128() -> u128 {
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:59:50
--> $DIR/return-via-stack.rs:58:50
|
LL | pub extern "C-cmse-nonsecure-entry" fn i128() -> i128 {
| ^^^^ this type doesn't fit in the available registers
@ -62,7 +62,7 @@ LL | pub extern "C-cmse-nonsecure-entry" fn i128() -> i128 {
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:76:56
--> $DIR/return-via-stack.rs:75:56
|
LL | pub extern "C-cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 {
| ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
@ -71,7 +71,7 @@ LL | pub extern "C-cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 {
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:81:53
--> $DIR/return-via-stack.rs:80:53
|
LL | pub extern "C-cmse-nonsecure-entry" fn union_c() -> ReprCUnionU64 {
| ^^^^^^^^^^^^^ this type doesn't fit in the available registers

View file

@ -1,4 +1,4 @@
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`
--> $DIR/E0045.rs:1:17
|
LL | extern "Rust" { fn foo(x: u8, ...); }

View file

@ -0,0 +1,7 @@
fn system(f: extern "system" fn(usize, ...)) {
//~^ ERROR using calling conventions other than `C` or `cdecl` for varargs functions is unstable
f(22, 44);
}
fn main() {}

View file

@ -0,0 +1,13 @@
error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
--> $DIR/feature-gate-extern_system_varargs.rs:1:14
|
LL | fn system(f: extern "system" fn(usize, ...)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #136946 <https://github.com/rust-lang/rust/issues/136946> for more information
= help: add `#![feature(extern_system_varargs)]` 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 1 previous error
For more information about this error, try `rustc --explain E0658`.

View file

@ -2,6 +2,7 @@
union W { s: dyn Iterator<Item = Missing> }
//~^ ERROR cannot find type `Missing` in this scope
//~| ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
static ONCE: W = todo!();

View file

@ -4,6 +4,19 @@ error[E0412]: cannot find type `Missing` in this scope
LL | union W { s: dyn Iterator<Item = Missing> }
| ^^^^^^^ not found in this scope
error: aborting due to 1 previous error
error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
--> $DIR/malformed-unsized-type-in-union.rs:3:11
|
LL | union W { s: dyn Iterator<Item = Missing> }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
help: wrap the field type in `ManuallyDrop<...>`
|
LL | union W { s: std::mem::ManuallyDrop<dyn Iterator<Item = Missing>> }
| +++++++++++++++++++++++ +
For more information about this error, try `rustc --explain E0412`.
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0412, E0740.
For more information about an error, try `rustc --explain E0412`.

View file

@ -23,16 +23,20 @@ LL | | T: Anything<'b, 'c>,
|
= note: defining type: no_relationships_late::<'?1, '?2, T>
error[E0309]: the associated type `<T as Anything<'?5, '?6>>::AssocType` may not live long enough
error[E0309]: the associated type `<T as Anything<'b/#0, 'c/#1>>::AssocType` may not live long enough
--> $DIR/projection-two-region-trait-bound-closure.rs:38:39
|
LL | fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
| -- the associated type `<T as Anything<'?5, '?6>>::AssocType` must be valid for the lifetime `'a` as defined here...
| -- the associated type `<T as Anything<'b/#0, 'c/#1>>::AssocType` must be valid for the lifetime `'a` as defined here...
...
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^ ...so that the type `<T as Anything<'?5, '?6>>::AssocType` will meet its required lifetime bounds
| ^^^^^^^^^^^^^^^^ ...so that the type `<T as Anything<'b/#0, 'c/#1>>::AssocType` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
LL - T: Anything<'b, 'c>,
LL + T: Anything<'b, 'c>, <T as Anything<'b/#0, 'c/#1>>::AssocType: 'a
|
= help: consider adding an explicit lifetime bound `<T as Anything<'?5, '?6>>::AssocType: 'a`...
note: external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:48:29
@ -59,16 +63,20 @@ LL | | 'a: 'a,
|
= note: defining type: no_relationships_early::<'?1, '?2, '?3, T>
error[E0309]: the associated type `<T as Anything<'?6, '?7>>::AssocType` may not live long enough
error[E0309]: the associated type `<T as Anything<'b/#1, 'c/#2>>::AssocType` may not live long enough
--> $DIR/projection-two-region-trait-bound-closure.rs:48:39
|
LL | fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
| -- the associated type `<T as Anything<'?6, '?7>>::AssocType` must be valid for the lifetime `'a` as defined here...
| -- the associated type `<T as Anything<'b/#1, 'c/#2>>::AssocType` must be valid for the lifetime `'a` as defined here...
...
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^ ...so that the type `<T as Anything<'?6, '?7>>::AssocType` will meet its required lifetime bounds
| ^^^^^^^^^^^^^^^^ ...so that the type `<T as Anything<'b/#1, 'c/#2>>::AssocType` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
LL - 'a: 'a,
LL + 'a: 'a, <T as Anything<'b/#1, 'c/#2>>::AssocType: 'a
|
= help: consider adding an explicit lifetime bound `<T as Anything<'?6, '?7>>::AssocType: 'a`...
note: external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:61:29

View file

@ -1,13 +1,17 @@
error[E0309]: the associated type `<T as MyTrait<'_>>::Output` may not live long enough
error[E0309]: the associated type `<T as MyTrait<'a>>::Output` may not live long enough
--> $DIR/projection-where-clause-env-wrong-bound.rs:15:5
|
LL | fn foo1<'a, 'b, T>() -> &'a ()
| -- the associated type `<T as MyTrait<'_>>::Output` must be valid for the lifetime `'a` as defined here...
| -- the associated type `<T as MyTrait<'a>>::Output` must be valid for the lifetime `'a` as defined here...
...
LL | bar::<T::Output>()
| ^^^^^^^^^^^^^^^^ ...so that the type `<T as MyTrait<'_>>::Output` will meet its required lifetime bounds
| ^^^^^^^^^^^^^^^^ ...so that the type `<T as MyTrait<'a>>::Output` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
LL - <T as MyTrait<'a>>::Output: 'b,
LL + <T as MyTrait<'a>>::Output: 'b, <T as MyTrait<'a>>::Output: 'a
|
= help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
error: aborting due to 1 previous error

View file

@ -12,7 +12,7 @@ where
<T as MyTrait<'b>>::Output: 'a,
{
bar::<<T as MyTrait<'a>>::Output>()
//~^ ERROR the associated type `<T as MyTrait<'_>>::Output` may not live long enough
//~^ ERROR the associated type `<T as MyTrait<'a>>::Output` may not live long enough
}
fn bar<'a, T>() -> &'a ()

View file

@ -1,13 +1,17 @@
error[E0309]: the associated type `<T as MyTrait<'_>>::Output` may not live long enough
error[E0309]: the associated type `<T as MyTrait<'a>>::Output` may not live long enough
--> $DIR/projection-where-clause-env-wrong-lifetime.rs:14:5
|
LL | fn foo1<'a, 'b, T>() -> &'a ()
| -- the associated type `<T as MyTrait<'_>>::Output` must be valid for the lifetime `'a` as defined here...
| -- the associated type `<T as MyTrait<'a>>::Output` must be valid for the lifetime `'a` as defined here...
...
LL | bar::<<T as MyTrait<'a>>::Output>()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `<T as MyTrait<'_>>::Output` will meet its required lifetime bounds
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `<T as MyTrait<'a>>::Output` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
LL - <T as MyTrait<'b>>::Output: 'a,
LL + <T as MyTrait<'b>>::Output: 'a, <T as MyTrait<'a>>::Output: 'a
|
= help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
error: aborting due to 1 previous error

View file

@ -0,0 +1,16 @@
//@ check-pass
// Make sure that the closure captures `s` so it can perform a read of `s`.
#![feature(never_patterns)]
#![allow(incomplete_features)]
enum Void {}
fn by_value(s: Void) {
move || {
let ! = s;
};
}
fn main() {}

View file

@ -1,40 +1,40 @@
//@ known-bug: unknown
#![feature(unsafe_binders)]
// FIXME(unsafe_binders) ~^ WARN the feature `unsafe_binders` is incomplete
//~^ WARN the feature `unsafe_binders` is incomplete
use std::unsafe_binder::{wrap_binder, unwrap_binder};
use std::mem::{drop, ManuallyDrop};
use std::mem::{ManuallyDrop, drop};
use std::unsafe_binder::{unwrap_binder, wrap_binder};
#[derive(Default)]
struct NotCopyInner;
type NotCopy = ManuallyDrop<NotCopyInner>;
fn use_after_wrap() {
unsafe {
let base = NotCopy;
let base = NotCopy::default();
let binder: unsafe<> NotCopy = wrap_binder!(base);
drop(base);
// FIXME(unsafe_binders) ~^ ERROR use of moved value: `base`
//~^ ERROR use of moved value: `base`
}
}
fn move_out_of_wrap() {
unsafe {
let binder: unsafe<> NotCopy = wrap_binder!(NotCopy);
let binder: unsafe<> NotCopy = wrap_binder!(NotCopy::default());
drop(unwrap_binder!(binder));
drop(unwrap_binder!(binder));
// FIXME(unsafe_binders) ~^ ERROR use of moved value: `binder`
//~^ ERROR use of moved value: `binder`
}
}
fn not_conflicting() {
unsafe {
let binder: unsafe<> (NotCopy, NotCopy) = wrap_binder!((NotCopy, NotCopy));
let binder: unsafe<> (NotCopy, NotCopy) =
wrap_binder!((NotCopy::default(), NotCopy::default()));
drop(unwrap_binder!(binder).0);
drop(unwrap_binder!(binder).1);
// ^ NOT a problem.
// ^ NOT a problem, since the moves are disjoint.
drop(unwrap_binder!(binder).0);
// FIXME(unsafe_binders) ~^ ERROR use of moved value: `binder.0`
//~^ ERROR use of moved value: `binder.0`
}
}

View file

@ -1,37 +1,5 @@
error[E0423]: expected value, found type alias `NotCopy`
--> $DIR/moves.rs:14:20
|
LL | let base = NotCopy;
| ^^^^^^^
|
= note: can't use a type alias as a constructor
error[E0423]: expected value, found type alias `NotCopy`
--> $DIR/moves.rs:23:53
|
LL | let binder: unsafe<> NotCopy = wrap_binder!(NotCopy);
| ^^^^^^^
|
= note: can't use a type alias as a constructor
error[E0423]: expected value, found type alias `NotCopy`
--> $DIR/moves.rs:32:65
|
LL | let binder: unsafe<> (NotCopy, NotCopy) = wrap_binder!((NotCopy, NotCopy));
| ^^^^^^^
|
= note: can't use a type alias as a constructor
error[E0423]: expected value, found type alias `NotCopy`
--> $DIR/moves.rs:32:74
|
LL | let binder: unsafe<> (NotCopy, NotCopy) = wrap_binder!((NotCopy, NotCopy));
| ^^^^^^^
|
= note: can't use a type alias as a constructor
warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/moves.rs:3:12
--> $DIR/moves.rs:1:12
|
LL | #![feature(unsafe_binders)]
| ^^^^^^^^^^^^^^
@ -39,47 +7,38 @@ LL | #![feature(unsafe_binders)]
= note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0277]: the trait bound `NotCopyInner: Copy` is not satisfied
--> $DIR/moves.rs:15:21
error[E0382]: use of moved value: `base`
--> $DIR/moves.rs:15:14
|
LL | let base = NotCopy::default();
| ---- move occurs because `base` has type `ManuallyDrop<NotCopyInner>`, which does not implement the `Copy` trait
LL | let binder: unsafe<> NotCopy = wrap_binder!(base);
| ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopyInner`
|
= note: required for `ManuallyDrop<NotCopyInner>` to implement `Copy`
help: consider annotating `NotCopyInner` with `#[derive(Copy)]`
|
LL + #[derive(Copy)]
LL | struct NotCopyInner;
|
| ---- value moved here
LL | drop(base);
| ^^^^ value used here after move
error[E0277]: the trait bound `NotCopyInner: Copy` is not satisfied
--> $DIR/moves.rs:23:21
error[E0382]: use of moved value: `binder`
--> $DIR/moves.rs:24:14
|
LL | let binder: unsafe<> NotCopy = wrap_binder!(NotCopy);
| ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopyInner`
|
= note: required for `ManuallyDrop<NotCopyInner>` to implement `Copy`
help: consider annotating `NotCopyInner` with `#[derive(Copy)]`
|
LL + #[derive(Copy)]
LL | struct NotCopyInner;
LL | drop(unwrap_binder!(binder));
| ---------------------- value moved here
LL | drop(unwrap_binder!(binder));
| ^^^^^^^^^^^^^^^^^^^^^^ value used here after move
|
= note: move occurs because `binder` has type `ManuallyDrop<NotCopyInner>`, which does not implement the `Copy` trait
= note: this error originates in the macro `unwrap_binder` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `NotCopyInner: Copy` is not satisfied
--> $DIR/moves.rs:32:21
error[E0382]: use of moved value: `binder.0`
--> $DIR/moves.rs:36:14
|
LL | let binder: unsafe<> (NotCopy, NotCopy) = wrap_binder!((NotCopy, NotCopy));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopyInner`
|
= note: required for `ManuallyDrop<NotCopyInner>` to implement `Copy`
= note: required because it appears within the type `(ManuallyDrop<NotCopyInner>, ManuallyDrop<NotCopyInner>)`
help: consider annotating `NotCopyInner` with `#[derive(Copy)]`
|
LL + #[derive(Copy)]
LL | struct NotCopyInner;
LL | drop(unwrap_binder!(binder).0);
| ------------------------ value moved here
...
LL | drop(unwrap_binder!(binder).0);
| ^^^^^^^^^^^^^^^^^^^^^^^^ value used here after move
|
= note: move occurs because `binder.0` has type `ManuallyDrop<NotCopyInner>`, which does not implement the `Copy` trait
error: aborting due to 7 previous errors; 1 warning emitted
error: aborting due to 3 previous errors; 1 warning emitted
Some errors have detailed explanations: E0277, E0423.
For more information about an error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0382`.