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:
commit
54cdc751df
71 changed files with 1231 additions and 790 deletions
|
@ -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 { .. }
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {}
|
||||||
|
|
|
@ -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 {}
|
||||||
|
|
|
@ -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) }
|
||||||
|
|
|
@ -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(()))
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
};
|
};
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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(())
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -690,6 +690,7 @@ bidirectional_lang_item_map! {
|
||||||
AsyncFnOnce,
|
AsyncFnOnce,
|
||||||
AsyncFnOnceOutput,
|
AsyncFnOnceOutput,
|
||||||
AsyncIterator,
|
AsyncIterator,
|
||||||
|
BikeshedGuaranteedNoDrop,
|
||||||
CallOnceFuture,
|
CallOnceFuture,
|
||||||
CallRefFuture,
|
CallRefFuture,
|
||||||
Clone,
|
Clone,
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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,
|
||||||
|
|
46
compiler/rustc_target/src/spec/base/cygwin.rs
Normal file
46
compiler/rustc_target/src/spec/base/cygwin.rs
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
24
compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs
Normal file
24
compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs
Normal 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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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],
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -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>>;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ pub enum TraitSolverLangItem {
|
||||||
AsyncFnOnce,
|
AsyncFnOnce,
|
||||||
AsyncFnOnceOutput,
|
AsyncFnOnceOutput,
|
||||||
AsyncIterator,
|
AsyncIterator,
|
||||||
|
BikeshedGuaranteedNoDrop,
|
||||||
CallOnceFuture,
|
CallOnceFuture,
|
||||||
CallRefFuture,
|
CallRefFuture,
|
||||||
Clone,
|
Clone,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 |
|
||||||
|
|
39
src/doc/rustc/src/platform-support/x86_64-pc-cygwin.md
Normal file
39
src/doc/rustc/src/platform-support/x86_64-pc-cygwin.md
Normal 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.
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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`.
|
|
||||||
|
|
|
@ -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, ...);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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`
|
||||||
|
|
|
@ -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, ...);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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, ...); }
|
||||||
|
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -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!();
|
||||||
|
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 ()
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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() {}
|
|
@ -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`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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`.
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue