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 and Cdecl obviously support varargs.
// * C can be based on Aapcs, SysV64 or Win64, so they must 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. // * 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 // * 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) // up the arguments. (callee doesn't know how many arguments are there)
@ -204,7 +203,6 @@ impl ExternAbi {
match self { match self {
Self::C { .. } Self::C { .. }
| Self::Cdecl { .. } | Self::Cdecl { .. }
| Self::System { .. }
| Self::Aapcs { .. } | Self::Aapcs { .. }
| Self::Win64 { .. } | Self::Win64 { .. }
| Self::SysV64 { .. } | Self::SysV64 { .. }

View file

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

View file

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

View file

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

View file

@ -710,10 +710,6 @@ pub struct ThinBuffer {
context: Arc<SyncContext>, 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 { impl ThinBuffer {
pub(crate) fn new(context: &Arc<SyncContext>) -> Self { pub(crate) fn new(context: &Arc<SyncContext>) -> Self {
Self { context: Arc::clone(context) } 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 { impl LlvmCodegenBackend {
pub fn new() -> Box<dyn CodegenBackend> { pub fn new() -> Box<dyn CodegenBackend> {
Box::new(LlvmCodegenBackend(())) 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 /// If this archive is used with a mutable method, then an error will be
/// raised. /// raised.
pub fn open(dst: &Path) -> Result<ArchiveRO, String> { pub(crate) fn open(dst: &Path) -> Result<ArchiveRO, String> {
unsafe { unsafe {
let s = path_to_c_string(dst); let s = path_to_c_string(dst);
let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| { 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) } } unsafe { Iter { raw: super::LLVMRustArchiveIteratorNew(self.raw) } }
} }
} }
@ -71,7 +71,7 @@ impl<'a> Drop for Iter<'a> {
} }
impl<'a> Child<'a> { impl<'a> Child<'a> {
pub fn name(&self) -> Option<&'a str> { pub(crate) fn name(&self) -> Option<&'a str> {
unsafe { unsafe {
let mut name_len = 0; let mut name_len = 0;
let name_ptr = super::LLVMRustArchiveChildName(self.raw, &mut name_len); let name_ptr = super::LLVMRustArchiveChildName(self.raw, &mut name_len);

View file

@ -1,4 +1,5 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
#![expect(dead_code)]
use libc::{c_char, c_uint}; use libc::{c_char, c_uint};
@ -8,23 +9,23 @@ use crate::llvm::Bool;
#[link(name = "llvm-wrapper", kind = "static")] #[link(name = "llvm-wrapper", kind = "static")]
extern "C" { extern "C" {
// Enzyme // Enzyme
pub fn LLVMRustHasMetadata(I: &Value, KindID: c_uint) -> bool; pub(crate) fn LLVMRustHasMetadata(I: &Value, KindID: c_uint) -> bool;
pub fn LLVMRustEraseInstUntilInclusive(BB: &BasicBlock, I: &Value); pub(crate) fn LLVMRustEraseInstUntilInclusive(BB: &BasicBlock, I: &Value);
pub fn LLVMRustGetLastInstruction<'a>(BB: &BasicBlock) -> Option<&'a Value>; pub(crate) fn LLVMRustGetLastInstruction<'a>(BB: &BasicBlock) -> Option<&'a Value>;
pub fn LLVMRustDIGetInstMetadata(I: &Value) -> Option<&Metadata>; pub(crate) fn LLVMRustDIGetInstMetadata(I: &Value) -> Option<&Metadata>;
pub fn LLVMRustEraseInstFromParent(V: &Value); pub(crate) fn LLVMRustEraseInstFromParent(V: &Value);
pub fn LLVMRustGetTerminator<'a>(B: &BasicBlock) -> &'a Value; pub(crate) fn LLVMRustGetTerminator<'a>(B: &BasicBlock) -> &'a Value;
pub fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool; pub(crate) fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool;
} }
extern "C" { extern "C" {
// Enzyme // Enzyme
pub fn LLVMDumpModule(M: &Module); pub(crate) fn LLVMDumpModule(M: &Module);
pub fn LLVMDumpValue(V: &Value); pub(crate) fn LLVMDumpValue(V: &Value);
pub fn LLVMGetFunctionCallConv(F: &Value) -> c_uint; pub(crate) fn LLVMGetFunctionCallConv(F: &Value) -> c_uint;
pub fn LLVMGetReturnType(T: &Type) -> &Type; pub(crate) fn LLVMGetReturnType(T: &Type) -> &Type;
pub fn LLVMGetParams(Fnc: &Value, parms: *mut &Value); pub(crate) fn LLVMGetParams(Fnc: &Value, parms: *mut &Value);
pub fn LLVMGetNamedFunction(M: &Module, Name: *const c_char) -> Option<&Value>; pub(crate) fn LLVMGetNamedFunction(M: &Module, Name: *const c_char) -> Option<&Value>;
} }
#[repr(C)] #[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::*; pub use self::enzyme_ffi::*;
impl LLVMRustResult { impl LLVMRustResult {
pub fn into_result(self) -> Result<(), ()> { pub(crate) fn into_result(self) -> Result<(), ()> {
match self { match self {
LLVMRustResult::Success => Ok(()), LLVMRustResult::Success => Ok(()),
LLVMRustResult::Failure => Err(()), 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 { unsafe {
LLVMRustAddFunctionAttributes(llfn, idx.as_uint(), attrs.as_ptr(), attrs.len()); LLVMRustAddFunctionAttributes(llfn, idx.as_uint(), attrs.as_ptr(), attrs.len());
} }
} }
pub fn AddCallSiteAttributes<'ll>( pub(crate) fn AddCallSiteAttributes<'ll>(
callsite: &'ll Value, callsite: &'ll Value,
idx: AttributePlace, idx: AttributePlace,
attrs: &[&'ll Attribute], 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 { unsafe {
LLVMCreateStringAttribute( LLVMCreateStringAttribute(
llcx, 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 { unsafe {
LLVMCreateStringAttribute( LLVMCreateStringAttribute(
llcx, 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) } 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) } 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) } 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) } 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) } 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_) } 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) } 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()) } 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 lower = range.start;
let upper = range.end.wrapping_add(1); let upper = range.end.wrapping_add(1);
let lower_words = [lower as u64, (lower >> 64) as u64]; let lower_words = [lower as u64, (lower >> 64) as u64];
@ -127,7 +135,7 @@ pub enum AttributePlace {
} }
impl AttributePlace { impl AttributePlace {
pub fn as_uint(self) -> c_uint { pub(crate) fn as_uint(self) -> c_uint {
match self { match self {
AttributePlace::ReturnValue => 0, AttributePlace::ReturnValue => 0,
AttributePlace::Argument(i) => 1 + i, 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 { unsafe {
LLVMSetInstructionCallConv(instr, cc as c_uint); LLVMSetInstructionCallConv(instr, cc as c_uint);
} }
} }
pub fn SetFunctionCallConv(fn_: &Value, cc: CallConv) { pub(crate) fn SetFunctionCallConv(fn_: &Value, cc: CallConv) {
unsafe { unsafe {
LLVMSetFunctionCallConv(fn_, cc as c_uint); 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 // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
// function. // function.
// For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52 // 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_buf = get_value_name(val).to_vec();
let name = let name =
CString::from_vec_with_nul(name_buf).or_else(|buf| CString::new(buf.into_bytes())).unwrap(); CString::from_vec_with_nul(name_buf).or_else(|buf| CString::new(buf.into_bytes())).unwrap();
set_comdat(llmod, val, &name); set_comdat(llmod, val, &name);
} }
pub fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) { pub(crate) fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) {
unsafe { unsafe {
LLVMSetUnnamedAddress(global, unnamed); 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 { unsafe {
LLVMSetThreadLocalMode(global, mode); LLVMSetThreadLocalMode(global, mode);
} }
@ -197,65 +205,65 @@ pub fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) {
impl AttributeKind { impl AttributeKind {
/// Create an LLVM Attribute with no associated value. /// 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) } unsafe { LLVMRustCreateAttrNoValue(llcx, self) }
} }
} }
impl MemoryEffects { impl MemoryEffects {
/// Create an LLVM Attribute with these memory effects. /// 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) } unsafe { LLVMRustCreateMemoryEffectsAttr(llcx, self) }
} }
} }
pub fn set_section(llglobal: &Value, section_name: &CStr) { pub(crate) fn set_section(llglobal: &Value, section_name: &CStr) {
unsafe { unsafe {
LLVMSetSection(llglobal, section_name.as_ptr()); 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()) } 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 { unsafe {
LLVMSetInitializer(llglobal, constant_val); 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 { unsafe {
LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False }); 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() unsafe { LLVMGetLinkage(llglobal) }.to_rust()
} }
pub fn set_linkage(llglobal: &Value, linkage: Linkage) { pub(crate) fn set_linkage(llglobal: &Value, linkage: Linkage) {
unsafe { unsafe {
LLVMSetLinkage(llglobal, linkage); LLVMSetLinkage(llglobal, linkage);
} }
} }
pub fn is_declaration(llglobal: &Value) -> bool { pub(crate) fn is_declaration(llglobal: &Value) -> bool {
unsafe { LLVMIsDeclaration(llglobal) == ffi::True } 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() unsafe { LLVMGetVisibility(llglobal) }.to_rust()
} }
pub fn set_visibility(llglobal: &Value, visibility: Visibility) { pub(crate) fn set_visibility(llglobal: &Value, visibility: Visibility) {
unsafe { unsafe {
LLVMSetVisibility(llglobal, visibility); LLVMSetVisibility(llglobal, visibility);
} }
} }
pub fn set_alignment(llglobal: &Value, align: Align) { pub(crate) fn set_alignment(llglobal: &Value, align: Align) {
unsafe { unsafe {
ffi::LLVMSetAlignment(llglobal, align.bytes() as c_uint); 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. /// Inserts the comdat into `llmod` if it does not exist.
/// It is an error to call this if the target does not support comdat. /// 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 { unsafe {
let comdat = LLVMGetOrInsertComdat(llmod, name.as_ptr()); let comdat = LLVMGetOrInsertComdat(llmod, name.as_ptr());
LLVMSetComdat(llglobal, comdat); 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. /// 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 { unsafe {
assert!( assert!(
index < LLVMCountParams(llfn), 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 /// 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 { unsafe {
let mut len = 0; let mut len = 0;
let data = LLVMGetValueName2(value, &mut len); 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 /// 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 { unsafe {
let data = name.as_c_char_ptr(); let data = name.as_c_char_ptr();
LLVMSetValueName2(value, data, name.len()); 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)) 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) RustString::build_byte_buffer(f)
} }
pub fn twine_to_string(tr: &Twine) -> String { pub(crate) fn twine_to_string(tr: &Twine) -> String {
unsafe { unsafe {
build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM") 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 { unsafe {
let cstr = LLVMRustGetLastError(); let cstr = LLVMRustGetLastError();
if cstr.is_null() { if cstr.is_null() {

View file

@ -2,11 +2,6 @@ use std::borrow::Borrow;
use std::ops::Deref; use std::ops::Deref;
use std::sync::Arc; 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. /// An owned slice.
/// ///
/// This is similar to `Arc<[u8]>` but allows slicing and using anything as the /// 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) // ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
#[expect(dead_code)] #[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. /// 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 pub fn slice_owned<O, F>(owner: O, slicer: F) -> OwnedSlice
where where
O: sync::Send + sync::Sync + 'static, O: Send + Sync + 'static,
F: FnOnce(&O) -> &[u8], F: FnOnce(&O) -> &[u8],
{ {
try_slice_owned(owner, |x| Ok::<_, !>(slicer(x))).into_ok() try_slice_owned(owner, |x| Ok::<_, !>(slicer(x))).into_ok()
@ -72,7 +67,7 @@ where
/// See [`slice_owned`] for the infallible version. /// See [`slice_owned`] for the infallible version.
pub fn try_slice_owned<O, F, E>(owner: O, slicer: F) -> Result<OwnedSlice, E> pub fn try_slice_owned<O, F, E>(owner: O, slicer: F) -> Result<OwnedSlice, E>
where where
O: sync::Send + sync::Sync + 'static, O: Send + Sync + 'static,
F: FnOnce(&O) -> Result<&[u8], E>, F: FnOnce(&O) -> Result<&[u8], E>,
{ {
// We wrap the owner of the bytes in, so it doesn't move. // 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` // 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` // 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)] #[cfg(test)]
mod tests; mod tests;

View file

@ -18,14 +18,8 @@
//! //!
//! | Type | Serial version | Parallel version | //! | Type | Serial version | Parallel version |
//! | ----------------------- | ------------------- | ------------------------------- | //! | ----------------------- | ------------------- | ------------------------------- |
//! |` Weak<T>` | `rc::Weak<T>` | `sync::Weak<T>` |
//! | `LRef<'a, T>` [^2] | `&'a mut T` | `&'a 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 | //! | `Lock<T>` | `RefCell<T>` | `RefCell<T>` or |
//! | | | `parking_lot::Mutex<T>` | //! | | | `parking_lot::Mutex<T>` |
//! | `RwLock<T>` | `RefCell<T>` | `parking_lot::RwLock<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. // 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 // Use portable AtomicU64 for targets without native 64-bit atomics
#[cfg(target_has_atomic = "64")] #[cfg(target_has_atomic = "64")]
pub use std::sync::atomic::AtomicU64; 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 mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
pub use parking_lot::{ pub use parking_lot::{
MappedMutexGuard as MappedLockGuard, MappedRwLockReadGuard as MappedReadGuard, MappedRwLockReadGuard as MappedReadGuard, MappedRwLockWriteGuard as MappedWriteGuard,
MappedRwLockWriteGuard as MappedWriteGuard, RwLockReadGuard as ReadGuard, RwLockReadGuard as ReadGuard, RwLockWriteGuard as WriteGuard,
RwLockWriteGuard as WriteGuard,
}; };
#[cfg(not(target_has_atomic = "64"))] #[cfg(not(target_has_atomic = "64"))]
pub use portable_atomic::AtomicU64; 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)] #[inline(always)]
pub fn try_write(&self) -> Result<WriteGuard<'_, T>, ()> { pub fn try_write(&self) -> Result<WriteGuard<'_, T>, ()> {
self.0.try_write().ok_or(()) 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)] #[inline(always)]
#[track_caller] #[track_caller]
pub fn borrow(&self) -> ReadGuard<'_, T> { pub fn borrow(&self) -> ReadGuard<'_, T> {
@ -240,20 +219,4 @@ impl<T> RwLock<T> {
pub fn borrow_mut(&self) -> WriteGuard<'_, T> { pub fn borrow_mut(&self) -> WriteGuard<'_, T> {
self.write() 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::marker::PhantomData;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::ptr::NonNull; 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 /// A type which allows mutation using a lock until
/// the value is frozen and can be accessed lock-free. /// the value is frozen and can be accessed lock-free.

View file

@ -106,12 +106,6 @@ pub struct WorkerLocal<T> {
registry: Registry, 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> { impl<T> WorkerLocal<T> {
/// Creates a new worker local where the `initial` closure computes the /// Creates a new worker local where the `initial` closure computes the
/// value this worker local should take for each thread in the registry. /// 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 { fn deref(&self) -> &T {
// This is safe because `verify` will only return values less than // This is safe because `verify` will only return values less than
// `self.registry.thread_limit` which is the size of the `self.locals` array. // `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 } 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)), (unstable, exhaustive_patterns, "1.13.0", Some(51085)),
/// Allows explicit tail calls via `become` expression. /// Allows explicit tail calls via `become` expression.
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)), (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. /// for functions with varargs.
(unstable, extended_varargs_abi_support, "1.65.0", Some(100189)), (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. /// Allows defining `extern type`s.
(unstable, extern_types, "1.23.0", Some(43467)), (unstable, extern_types, "1.23.0", Some(43467)),
/// Allow using 128-bit (quad precision) floating point numbers. /// 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); PhantomData, sym::phantom_data, phantom_data, Target::Struct, GenericRequirement::Exact(1);
ManuallyDrop, sym::manually_drop, manually_drop, Target::Struct, GenericRequirement::None; 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; 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::MultiSpan;
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_hir::def::{CtorKind, DefKind}; 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::infer::{RegionVariableOrigin, TyCtxtInferExt};
use rustc_infer::traits::{Obligation, ObligationCauseCode}; use rustc_infer::traits::{Obligation, ObligationCauseCode};
use rustc_lint_defs::builtin::{ 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::InferCtxtErrorExt;
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective; use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::fold::TypeFoldable;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
use ty::TypingMode; use ty::TypingMode;
@ -87,89 +88,76 @@ fn allowed_union_or_unsafe_field<'tcx>(
typing_env: ty::TypingEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
span: Span, span: Span,
) -> bool { ) -> bool {
// We don't just accept all !needs_drop fields, due to semver concerns. // HACK (not that bad of a hack don't worry): Some codegen tests don't even define proper
let allowed = match ty.kind() { // impls for `Copy`. Let's short-circuit here for this validity check, since a lot of them
ty::Ref(..) => true, // references never drop (even mutable refs, which are non-Copy and hence fail the later check) // use unions. We should eventually fix all the tests to define that lang item or use
ty::Tuple(tys) => { // minicore stubs.
// allow tuples of allowed types if ty.is_trivially_pure_clone_copy() {
tys.iter().all(|ty| allowed_union_or_unsafe_field(tcx, ty, typing_env, span)) return true;
}
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");
} }
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. /// Check that the fields of the `union` do not need dropping.
fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool { fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool {
let item_type = tcx.type_of(item_def_id).instantiate_identity(); let def = tcx.adt_def(item_def_id);
if let ty::Adt(def, args) = item_type.kind() { assert!(def.is_union());
assert!(def.is_union());
let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
for field in &def.non_enum_variant().fields { let args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
let Ok(field_ty) = tcx.try_normalize_erasing_regions(typing_env, field.ty(tcx, args))
else { for field in &def.non_enum_variant().fields {
tcx.dcx().span_delayed_bug(span, "could not normalize field type"); if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) {
continue; 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 {
if !allowed_union_or_unsafe_field(tcx, field_ty, typing_env, span) { field_span,
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) { sugg: errors::InvalidUnionFieldSuggestion {
// We are currently checking the type this field came from, so it must be local. lo: ty_span.shrink_to_lo(),
Some(Node::Field(field)) => (field.span, field.ty.span), hi: ty_span.shrink_to_hi(),
_ => unreachable!("mir field has to correspond to hir field"), },
}; note: (),
tcx.dcx().emit_err(errors::InvalidUnionField { });
field_span, return false;
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 true
} }
/// Check that the unsafe fields do not need dropping. /// Check that the unsafe fields do not need dropping.
fn check_unsafe_fields(tcx: TyCtxt<'_>, item_def_id: LocalDefId) { fn check_unsafe_fields(tcx: TyCtxt<'_>, item_def_id: LocalDefId) {
let span = tcx.def_span(item_def_id); let span = tcx.def_span(item_def_id);
let item_type = tcx.type_of(item_def_id).instantiate_identity(); let def = tcx.adt_def(item_def_id);
let ty::Adt(def, args) = item_type.kind() else {
span_bug!(span, "structs/enums must be ty::Adt, but got {:?}", item_type.kind());
};
let typing_env = ty::TypingEnv::non_body_analysis(tcx, 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() { for field in def.all_fields() {
if !field.safety.is_unsafe() { if !field.safety.is_unsafe() {
continue; 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 { let hir::Node::Field(field) = tcx.hir_node_by_def_id(field.did.expect_local()) else {
unreachable!("field has to correspond to hir field") 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 = const UNSTABLE_EXPLAIN: &str =
"using calling conventions other than `C` or `cdecl` for varargs functions is unstable"; "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 { .. }) { if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) {
return; return;
} }
// ABIs with feature-gated stability
let extended_abi_support = tcx.features().extended_varargs_abi_support(); let extended_abi_support = tcx.features().extended_varargs_abi_support();
let conventions = match (extended_abi_support, abi.supports_varargs()) { let extern_system_varargs = tcx.features().extern_system_varargs();
// User enabled additional ABI support for varargs and function ABI matches those ones.
(true, true) => return,
// Using this ABI would be ok, if the feature for additional ABI support was enabled. // If the feature gate has been enabled, we can stop here
// Return CONVENTIONS_STABLE, because we want the other error to look the same. if extern_system_varargs && let ExternAbi::System { .. } = abi {
(false, true) => { return;
feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN) };
.emit(); if extended_abi_support && abi.supports_varargs() {
CONVENTIONS_STABLE return;
}
(false, false) => CONVENTIONS_STABLE,
(true, false) => CONVENTIONS_UNSTABLE,
}; };
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) { 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(); let tcx = self.cx.tcx();
self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| { self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
if let PatKind::Binding(_, canonical_id, ..) = pat.kind { match pat.kind {
debug!("walk_pat: binding place={:?} pat={:?}", place, pat); PatKind::Binding(_, canonical_id, ..) => {
if let Some(bm) = debug!("walk_pat: binding place={:?} pat={:?}", place, pat);
self.cx.typeck_results().extract_binding_mode(tcx.sess, pat.hir_id, pat.span) if let Some(bm) = self
{ .cx
debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); .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. // pat_ty: the type of the binding being produced.
let pat_ty = self.node_ty(pat.hir_id)?; let pat_ty = self.node_ty(pat.hir_id)?;
debug!("walk_pat: pat_ty={:?}", pat_ty); debug!("walk_pat: pat_ty={:?}", pat_ty);
let def = Res::Local(canonical_id); let def = Res::Local(canonical_id);
if let Ok(ref binding_place) = self.cat_res(pat.hir_id, pat.span, pat_ty, def) { if let Ok(ref binding_place) =
self.delegate.borrow_mut().bind(binding_place, binding_place.hir_id); 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);
} }
hir::ByRef::No => {
debug!("walk_pat binding consuming pat"); // Subtle: MIR desugaring introduces immutable borrows for each pattern
self.consume_or_copy(place, discr_place.hir_id); // 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 { PatKind::Deref(subpattern) => {
// A deref pattern is a bit special: the binding mode of its inner bindings // 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 // 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 // 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). // 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 mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpattern);
let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not }; let mutability =
let bk = ty::BorrowKind::from_mutbl(mutability); if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk); 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(()) Ok(())

View file

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

View file

@ -168,6 +168,8 @@ pub enum SelectionCandidate<'tcx> {
BuiltinObjectCandidate, BuiltinObjectCandidate,
BuiltinUnsizeCandidate, BuiltinUnsizeCandidate,
BikeshedGuaranteedNoDropCandidate,
} }
/// The result of trait evaluation. The order is important /// 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() self.is_phantom_data()
} }
fn is_manually_drop(self) -> bool {
self.is_manually_drop()
}
fn all_field_tys( fn all_field_tys(
self, self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,

View file

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

View file

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

View file

@ -374,6 +374,13 @@ where
unreachable!("TransmuteFrom is not const") 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( fn consider_structural_builtin_unsize_candidates(
_ecx: &mut EvalCtxt<'_, D>, _ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>, _goal: Goal<I, Self>,

View file

@ -942,6 +942,13 @@ where
) -> Result<Candidate<I>, NoSolution> { ) -> Result<Candidate<I>, NoSolution> {
panic!("`TransmuteFrom` does not have an associated type: {:?}", goal) 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> 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) /// ```ignore (builtin impl example)
/// trait Trait { /// trait Trait {
/// fn foo(&self); /// fn foo(&self);

View file

@ -4,14 +4,14 @@ use std::fmt::Debug;
use std::hash::Hash; use std::hash::Hash;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::sync::Arc; 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::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef}; use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef};
use rustc_data_structures::sharded::{self, Sharded}; use rustc_data_structures::sharded::{self, Sharded};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; 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_data_structures::unord::UnordMap;
use rustc_index::IndexVec; use rustc_index::IndexVec;
use rustc_macros::{Decodable, Encodable}; use rustc_macros::{Decodable, Encodable};

View file

@ -516,6 +516,7 @@ symbols! {
bang, bang,
begin_panic, begin_panic,
bench, bench,
bikeshed_guaranteed_no_drop,
bin, bin,
binaryheap_iter, binaryheap_iter,
bind_by_move_pattern_guards, bind_by_move_pattern_guards,
@ -880,6 +881,7 @@ symbols! {
extern_crate_self, extern_crate_self,
extern_in_paths, extern_in_paths,
extern_prelude, extern_prelude,
extern_system_varargs,
extern_types, extern_types,
external, external,
external_doc, 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 apple;
pub(crate) mod avr_gnu; pub(crate) mod avr_gnu;
pub(crate) mod bpf; pub(crate) mod bpf;
pub(crate) mod cygwin;
pub(crate) mod dragonfly; pub(crate) mod dragonfly;
pub(crate) mod freebsd; pub(crate) mod freebsd;
pub(crate) mod fuchsia; pub(crate) mod fuchsia;

View file

@ -2013,6 +2013,7 @@ supported_targets! {
("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf), ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
("riscv64gc-unknown-nuttx-elf", riscv64gc_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>]> /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>
@ -2994,8 +2995,8 @@ impl Target {
); );
check_eq!( check_eq!(
self.is_like_windows, self.is_like_windows,
self.os == "windows" || self.os == "uefi", self.os == "windows" || self.os == "uefi" || self.os == "cygwin",
"`is_like_windows` must be set if and only if `os` is `windows` or `uefi`" "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
); );
check_eq!( check_eq!(
self.is_like_wasm, 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); self.assemble_candidate_for_tuple(obligation, &mut candidates);
} else if tcx.is_lang_item(def_id, LangItem::FnPtrTrait) { } else if tcx.is_lang_item(def_id, LangItem::FnPtrTrait) {
self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates); 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 { } else {
if tcx.is_lang_item(def_id, LangItem::Clone) { if tcx.is_lang_item(def_id, LangItem::Clone) {
// Same builtin conditions as `Copy`, i.e., every type which has builtin support // 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_middle::{bug, span_bug};
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
use rustc_type_ir::elaborate; use rustc_type_ir::elaborate;
use thin_vec::thin_vec;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
use super::SelectionCandidate::{self, *}; use super::SelectionCandidate::{self, *};
@ -130,6 +131,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
TraitUpcastingUnsizeCandidate(idx) => { TraitUpcastingUnsizeCandidate(idx) => {
self.confirm_trait_upcasting_unsize_candidate(obligation, 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 // The obligations returned by confirmation are recursively evaluated
@ -1346,6 +1351,93 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => bug!("source: {source}, target: {target}"), _ => 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) /// Compute a goal that some RPITIT (right now, only RPITITs corresponding to Futures)

View file

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

View file

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

View file

@ -540,6 +540,8 @@ pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
fn is_phantom_data(self) -> bool; fn is_phantom_data(self) -> bool;
fn is_manually_drop(self) -> bool;
// FIXME: perhaps use `all_fields` and expose `FieldDef`. // FIXME: perhaps use `all_fields` and expose `FieldDef`.
fn all_field_tys(self, interner: I) -> ty::EarlyBinder<I, impl IntoIterator<Item = I::Ty>>; 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, AsyncFnOnce,
AsyncFnOnceOutput, AsyncFnOnceOutput,
AsyncIterator, AsyncIterator,
BikeshedGuaranteedNoDrop,
CallOnceFuture, CallOnceFuture,
CallRefFuture, CallRefFuture,
Clone, Clone,

View file

@ -595,11 +595,6 @@
# Whether to always use incremental compilation when building rustc # Whether to always use incremental compilation when building rustc
#incremental = false #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 # The default linker that will be hard-coded into the generated
# compiler for targets that don't specify a default linker explicitly # compiler for targets that don't specify a default linker explicitly
# in their target specifications. Note that this is not the linker # 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")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Copy for &T {} 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. /// Types for which it is safe to share references between threads.
/// ///
/// This trait is automatically implemented when the compiler determines /// This trait is automatically implemented when the compiler determines

View file

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

View file

@ -245,7 +245,11 @@ impl Cargo {
// flesh out rpath support more fully in the future. // flesh out rpath support more fully in the future.
self.rustflags.arg("-Zosx-rpath-install-name"); self.rustflags.arg("-Zosx-rpath-install-name");
Some(format!("-Wl,-rpath,@loader_path/../{libdir}")) 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"); self.rustflags.arg("-Clink-args=-Wl,-z,origin");
Some(format!("-Wl,-rpath,$ORIGIN/../{libdir}")) Some(format!("-Wl,-rpath,$ORIGIN/../{libdir}"))
} else { } else {

View file

@ -46,8 +46,6 @@ are implemented differently depending on whether `parallel-compiler` is true.
| data structure | parallel | non-parallel | | 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 | | OnceCell | std::sync::OnceLock | std::cell::OnceCell |
| Lock\<T> | (parking_lot::Mutex\<T>) | (std::cell::RefCell) | | Lock\<T> | (parking_lot::Mutex\<T>) | (std::cell::RefCell) |
| RwLock\<T> | (parking_lot::RwLock\<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 | | WriteGuard | parking_lot::RwLockWriteGuard | std::cell::RefMut |
| MappedWriteGuard | parking_lot::MappedRwLockWriteGuard | std::cell::RefMut | | MappedWriteGuard | parking_lot::MappedRwLockWriteGuard | std::cell::RefMut |
| LockGuard | parking_lot::MutexGuard | 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 - These thread-safe data structures are interspersed during compilation which
can cause lock contention resulting in degraded performance as the number of 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] - [This list of interior mutability in the compiler by nikomatsakis][imlist]
[`rayon`]: https://crates.io/crates/rayon [`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 [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 [irlo0]: https://internals.rust-lang.org/t/parallelizing-rustc-using-rayon/6606
[irlo1]: https://internals.rust-lang.org/t/help-test-parallel-rustc/11503 [irlo1]: https://internals.rust-lang.org/t/help-test-parallel-rustc/11503
[monomorphization]: backend/monomorph.md [monomorphization]: backend/monomorph.md
[parallel-rustdoc]: https://github.com/rust-lang/rust/issues/82741 [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 [rustc-rayon]: https://github.com/rust-lang/rustc-rayon
[tracking]: https://github.com/rust-lang/rust/issues/48685 [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-gnu](platform-support/win7-windows-gnu.md)
- [\*-win7-windows-msvc](platform-support/win7-windows-msvc.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-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-pc-solaris](platform-support/solaris.md)
- [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.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) - [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 [`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-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-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`](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-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 | [`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 //@ revisions: x86_64_win7_windows_msvc
//@ [x86_64_win7_windows_msvc] compile-flags: --target 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 //@ [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. // Sanity-check that each target can produce assembly code.

View file

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

View file

@ -1,18 +1,15 @@
//@ only-x86_64 //@ only-x86_64
fn efiapi(f: extern "efiapi" fn(usize, ...)) { 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); f(22, 44);
} }
fn sysv(f: extern "sysv64" fn(usize, ...)) { 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); f(22, 44);
} }
fn win(f: extern "win64" fn(usize, ...)) { 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); 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 = 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 = 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 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, ...)) { 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 = 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 = 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 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, ...)) { 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 = 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 = 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` error: aborting due to 3 previous errors
--> $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 6 previous errors For more information about this error, try `rustc --explain E0658`.
Some errors have detailed explanations: E0045, E0658.
For more information about an error, try `rustc --explain E0045`.

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 --> $DIR/variadic-ffi-1.rs:9:5
| |
LL | fn printf(_: *const u8, ...); LL | fn printf(_: *const u8, ...);

View file

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

View file

@ -201,7 +201,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
LL | target_os = "_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 = 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` 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"` | 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 = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: 28 warnings emitted 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] //~^ 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, ...); 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: 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 = 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 --> $DIR/generics.rs:41:20
| |
LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...); 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 //@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
//@ needs-llvm-components: arm //@ needs-llvm-components: arm
//@ add-core-stubs
#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items)] #![feature(abi_c_cmse_nonsecure_call, no_core, lang_items)]
#![no_core] #![no_core]
#[lang = "sized"]
pub trait Sized {} extern crate minicore;
#[lang = "copy"] use minicore::*;
pub trait Copy {}
impl Copy for u32 {}
#[repr(C)] #[repr(C)]
pub struct ReprCU64(u64); pub struct ReprCU64(u64);

View file

@ -1,13 +1,12 @@
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib //@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
//@ needs-llvm-components: arm //@ needs-llvm-components: arm
//@ add-core-stubs
#![feature(cmse_nonsecure_entry, no_core, lang_items)] #![feature(cmse_nonsecure_entry, no_core, lang_items)]
#![no_core] #![no_core]
#[lang = "sized"]
pub trait Sized {} extern crate minicore;
#[lang = "copy"] use minicore::*;
pub trait Copy {}
impl Copy for u32 {}
impl Copy for u8 {}
#[repr(C)] #[repr(C)]
pub struct ReprCU64(u64); 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 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 { LL | pub extern "C-cmse-nonsecure-entry" fn f1() -> ReprCU64 {
| ^^^^^^^^ this type doesn't fit in the available registers | ^^^^^^^^ 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 = 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 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 { LL | pub extern "C-cmse-nonsecure-entry" fn f2() -> ReprCBytes {
| ^^^^^^^^^^ this type doesn't fit in the available registers | ^^^^^^^^^^ 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 = 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 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 { LL | pub extern "C-cmse-nonsecure-entry" fn f3() -> U64Compound {
| ^^^^^^^^^^^ this type doesn't fit in the available registers | ^^^^^^^^^^^ 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 = 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 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 { LL | pub extern "C-cmse-nonsecure-entry" fn f4() -> ReprCAlign16 {
| ^^^^^^^^^^^^ this type doesn't fit in the available registers | ^^^^^^^^^^^^ 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 = 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 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] { LL | pub extern "C-cmse-nonsecure-entry" fn f5() -> [u8; 5] {
| ^^^^^^^ this type doesn't fit in the available registers | ^^^^^^^ 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 = 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 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 { LL | pub extern "C-cmse-nonsecure-entry" fn u128() -> u128 {
| ^^^^ this type doesn't fit in the available registers | ^^^^ 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 = 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 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 { LL | pub extern "C-cmse-nonsecure-entry" fn i128() -> i128 {
| ^^^^ this type doesn't fit in the available registers | ^^^^ 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 = 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 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 { LL | pub extern "C-cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 {
| ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers | ^^^^^^^^^^^^^^^^ 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 = 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 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 { LL | pub extern "C-cmse-nonsecure-entry" fn union_c() -> ReprCUnionU64 {
| ^^^^^^^^^^^^^ this type doesn't fit in the available registers | ^^^^^^^^^^^^^ 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 --> $DIR/E0045.rs:1:17
| |
LL | extern "Rust" { fn foo(x: u8, ...); } 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> } union W { s: dyn Iterator<Item = Missing> }
//~^ ERROR cannot find type `Missing` in this scope //~^ 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!(); 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> } LL | union W { s: dyn Iterator<Item = Missing> }
| ^^^^^^^ not found in this scope | ^^^^^^^ 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> = 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 --> $DIR/projection-two-region-trait-bound-closure.rs:38:39
| |
LL | fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) 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)); 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 note: external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:48:29 --> $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> = 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 --> $DIR/projection-two-region-trait-bound-closure.rs:48:39
| |
LL | fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) 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)); 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 note: external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:61:29 --> $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 --> $DIR/projection-where-clause-env-wrong-bound.rs:15:5
| |
LL | fn foo1<'a, 'b, T>() -> &'a () 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>() 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 error: aborting due to 1 previous error

View file

@ -12,7 +12,7 @@ where
<T as MyTrait<'b>>::Output: 'a, <T as MyTrait<'b>>::Output: 'a,
{ {
bar::<<T as MyTrait<'a>>::Output>() 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 () 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 --> $DIR/projection-where-clause-env-wrong-lifetime.rs:14:5
| |
LL | fn foo1<'a, 'b, T>() -> &'a () 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>() 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 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)] #![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::{ManuallyDrop, drop};
use std::mem::{drop, ManuallyDrop}; use std::unsafe_binder::{unwrap_binder, wrap_binder};
#[derive(Default)]
struct NotCopyInner; struct NotCopyInner;
type NotCopy = ManuallyDrop<NotCopyInner>; type NotCopy = ManuallyDrop<NotCopyInner>;
fn use_after_wrap() { fn use_after_wrap() {
unsafe { unsafe {
let base = NotCopy; let base = NotCopy::default();
let binder: unsafe<> NotCopy = wrap_binder!(base); let binder: unsafe<> NotCopy = wrap_binder!(base);
drop(base); drop(base);
// FIXME(unsafe_binders) ~^ ERROR use of moved value: `base` //~^ ERROR use of moved value: `base`
} }
} }
fn move_out_of_wrap() { fn move_out_of_wrap() {
unsafe { unsafe {
let binder: unsafe<> NotCopy = wrap_binder!(NotCopy); let binder: unsafe<> NotCopy = wrap_binder!(NotCopy::default());
drop(unwrap_binder!(binder)); drop(unwrap_binder!(binder));
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() { fn not_conflicting() {
unsafe { 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).0);
drop(unwrap_binder!(binder).1); drop(unwrap_binder!(binder).1);
// ^ NOT a problem. // ^ NOT a problem, since the moves are disjoint.
drop(unwrap_binder!(binder).0); 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 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)] 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: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
= note: `#[warn(incomplete_features)]` on by default = note: `#[warn(incomplete_features)]` on by default
error[E0277]: the trait bound `NotCopyInner: Copy` is not satisfied error[E0382]: use of moved value: `base`
--> $DIR/moves.rs:15:21 --> $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); LL | let binder: unsafe<> NotCopy = wrap_binder!(base);
| ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopyInner` | ---- value moved here
| LL | drop(base);
= note: required for `ManuallyDrop<NotCopyInner>` to implement `Copy` | ^^^^ value used here after move
help: consider annotating `NotCopyInner` with `#[derive(Copy)]`
|
LL + #[derive(Copy)]
LL | struct NotCopyInner;
|
error[E0277]: the trait bound `NotCopyInner: Copy` is not satisfied error[E0382]: use of moved value: `binder`
--> $DIR/moves.rs:23:21 --> $DIR/moves.rs:24:14
| |
LL | let binder: unsafe<> NotCopy = wrap_binder!(NotCopy); LL | drop(unwrap_binder!(binder));
| ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopyInner` | ---------------------- value moved here
| LL | drop(unwrap_binder!(binder));
= note: required for `ManuallyDrop<NotCopyInner>` to implement `Copy` | ^^^^^^^^^^^^^^^^^^^^^^ value used here after move
help: consider annotating `NotCopyInner` with `#[derive(Copy)]`
|
LL + #[derive(Copy)]
LL | struct NotCopyInner;
| |
= 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 error[E0382]: use of moved value: `binder.0`
--> $DIR/moves.rs:32:21 --> $DIR/moves.rs:36:14
| |
LL | let binder: unsafe<> (NotCopy, NotCopy) = wrap_binder!((NotCopy, NotCopy)); LL | drop(unwrap_binder!(binder).0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopyInner` | ------------------------ value moved here
| ...
= note: required for `ManuallyDrop<NotCopyInner>` to implement `Copy` LL | drop(unwrap_binder!(binder).0);
= note: required because it appears within the type `(ManuallyDrop<NotCopyInner>, ManuallyDrop<NotCopyInner>)` | ^^^^^^^^^^^^^^^^^^^^^^^^ value used here after move
help: consider annotating `NotCopyInner` with `#[derive(Copy)]`
|
LL + #[derive(Copy)]
LL | struct NotCopyInner;
| |
= 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 this error, try `rustc --explain E0382`.
For more information about an error, try `rustc --explain E0277`.