mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 16:54:01 +00:00
Auto merge of #97729 - Dylan-DPC:rollup-dv43xo9, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #96642 (Avoid zero-sized allocs in ThinBox if T and H are both ZSTs.) - #97647 (Lazily allocate and initialize pthread locks.) - #97715 (Support the `#[expect]` attribute on fn parameters (RFC-2383)) - #97716 (Fix reachability analysis for const methods) - #97722 (Tighten spans for bad fields in struct deriving `Copy`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c7b0452ece
@ -420,7 +420,15 @@ impl<'a> AstValidator<'a> {
|
||||
.iter()
|
||||
.flat_map(|i| i.attrs.as_ref())
|
||||
.filter(|attr| {
|
||||
let arr = [sym::allow, sym::cfg, sym::cfg_attr, sym::deny, sym::forbid, sym::warn];
|
||||
let arr = [
|
||||
sym::allow,
|
||||
sym::cfg,
|
||||
sym::cfg_attr,
|
||||
sym::deny,
|
||||
sym::expect,
|
||||
sym::forbid,
|
||||
sym::warn,
|
||||
];
|
||||
!arr.contains(&attr.name_or_empty()) && rustc_attr::is_builtin_attr(attr)
|
||||
})
|
||||
.for_each(|attr| {
|
||||
@ -435,7 +443,7 @@ impl<'a> AstValidator<'a> {
|
||||
} else {
|
||||
self.err_handler().span_err(
|
||||
attr.span,
|
||||
"allow, cfg, cfg_attr, deny, \
|
||||
"allow, cfg, cfg_attr, deny, expect, \
|
||||
forbid, and warn are the only allowed built-in attributes in function parameters",
|
||||
);
|
||||
}
|
||||
|
@ -148,32 +148,15 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||
hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_))
|
||||
| hir::TraitItemKind::Type(..) => false,
|
||||
},
|
||||
Some(Node::ImplItem(impl_item)) => {
|
||||
match impl_item.kind {
|
||||
hir::ImplItemKind::Const(..) => true,
|
||||
hir::ImplItemKind::Fn(..) => {
|
||||
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
if generics.requires_monomorphization(self.tcx) || attrs.requests_inline() {
|
||||
true
|
||||
} else {
|
||||
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let impl_did = self.tcx.hir().get_parent_item(hir_id);
|
||||
// Check the impl. If the generics on the self
|
||||
// type of the impl require inlining, this method
|
||||
// does too.
|
||||
match self.tcx.hir().expect_item(impl_did).kind {
|
||||
hir::ItemKind::Impl { .. } => {
|
||||
let generics = self.tcx.generics_of(impl_did);
|
||||
generics.requires_monomorphization(self.tcx)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::ImplItemKind::TyAlias(_) => false,
|
||||
Some(Node::ImplItem(impl_item)) => match impl_item.kind {
|
||||
hir::ImplItemKind::Const(..) => true,
|
||||
hir::ImplItemKind::Fn(..) => {
|
||||
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let impl_did = self.tcx.hir().get_parent_item(hir_id);
|
||||
method_might_be_inlined(self.tcx, impl_item, impl_did)
|
||||
}
|
||||
}
|
||||
hir::ImplItemKind::TyAlias(_) => false,
|
||||
},
|
||||
Some(_) => false,
|
||||
None => false, // This will happen for default methods.
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ pub fn can_type_implement_copy<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
self_type: Ty<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
parent_cause: ObligationCause<'tcx>,
|
||||
) -> Result<(), CopyImplementationError<'tcx>> {
|
||||
// FIXME: (@jroesch) float this code up
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
@ -59,7 +59,7 @@ pub fn can_type_implement_copy<'tcx>(
|
||||
.ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did()))
|
||||
.has_param_types_or_consts()
|
||||
{
|
||||
cause.clone()
|
||||
parent_cause.clone()
|
||||
} else {
|
||||
ObligationCause::dummy_with_span(span)
|
||||
};
|
||||
|
@ -107,6 +107,10 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
||||
|
||||
for (field, ty) in fields {
|
||||
let field_span = tcx.def_span(field.did);
|
||||
let field_ty_span = match tcx.hir().get_if_local(field.did) {
|
||||
Some(hir::Node::Field(field_def)) => field_def.ty.span,
|
||||
_ => field_span,
|
||||
};
|
||||
err.span_label(field_span, "this field does not implement `Copy`");
|
||||
// Spin up a new FulfillmentContext, so we can get the _precise_ reason
|
||||
// why this field does not implement Copy. This is useful because sometimes
|
||||
@ -119,7 +123,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
||||
param_env,
|
||||
ty,
|
||||
tcx.lang_items().copy_trait().unwrap(),
|
||||
traits::ObligationCause::dummy_with_span(field_span),
|
||||
traits::ObligationCause::dummy_with_span(field_ty_span),
|
||||
);
|
||||
for error in fulfill_cx.select_all_or_error(&infcx) {
|
||||
let error_predicate = error.obligation.predicate;
|
||||
|
@ -138,7 +138,11 @@ impl<T: ?Sized> ThinBox<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A pointer to type-erased data, guaranteed to have a header `H` before the pointed-to location.
|
||||
/// A pointer to type-erased data, guaranteed to either be:
|
||||
/// 1. `NonNull::dangling()`, in the case where both the pointee (`T`) and
|
||||
/// metadata (`H`) are ZSTs.
|
||||
/// 2. A pointer to a valid `T` that has a header `H` directly before the
|
||||
/// pointed-to location.
|
||||
struct WithHeader<H>(NonNull<u8>, PhantomData<H>);
|
||||
|
||||
impl<H> WithHeader<H> {
|
||||
@ -156,16 +160,27 @@ impl<H> WithHeader<H> {
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let ptr = alloc::alloc(layout);
|
||||
// Note: It's UB to pass a layout with a zero size to `alloc::alloc`, so
|
||||
// we use `layout.dangling()` for this case, which should have a valid
|
||||
// alignment for both `T` and `H`.
|
||||
let ptr = if layout.size() == 0 {
|
||||
// Some paranoia checking, mostly so that the ThinBox tests are
|
||||
// more able to catch issues.
|
||||
debug_assert!(
|
||||
value_offset == 0 && mem::size_of::<T>() == 0 && mem::size_of::<H>() == 0
|
||||
);
|
||||
layout.dangling()
|
||||
} else {
|
||||
let ptr = alloc::alloc(layout);
|
||||
if ptr.is_null() {
|
||||
alloc::handle_alloc_error(layout);
|
||||
}
|
||||
// Safety:
|
||||
// - The size is at least `aligned_header_size`.
|
||||
let ptr = ptr.add(value_offset) as *mut _;
|
||||
|
||||
if ptr.is_null() {
|
||||
alloc::handle_alloc_error(layout);
|
||||
}
|
||||
// Safety:
|
||||
// - The size is at least `aligned_header_size`.
|
||||
let ptr = ptr.add(value_offset) as *mut _;
|
||||
|
||||
let ptr = NonNull::new_unchecked(ptr);
|
||||
NonNull::new_unchecked(ptr)
|
||||
};
|
||||
|
||||
let result = WithHeader(ptr, PhantomData);
|
||||
ptr::write(result.header(), header);
|
||||
@ -175,18 +190,28 @@ impl<H> WithHeader<H> {
|
||||
}
|
||||
}
|
||||
|
||||
// Safety:
|
||||
// - Assumes that `value` can be dereferenced.
|
||||
// Safety:
|
||||
// - Assumes that either `value` can be dereferenced, or is the
|
||||
// `NonNull::dangling()` we use when both `T` and `H` are ZSTs.
|
||||
unsafe fn drop<T: ?Sized>(&self, value: *mut T) {
|
||||
unsafe {
|
||||
let value_layout = Layout::for_value_raw(value);
|
||||
// SAFETY: Layout must have been computable if we're in drop
|
||||
let (layout, value_offset) =
|
||||
Self::alloc_layout(Layout::for_value_raw(value)).unwrap_unchecked();
|
||||
let (layout, value_offset) = Self::alloc_layout(value_layout).unwrap_unchecked();
|
||||
|
||||
ptr::drop_in_place::<T>(value);
|
||||
// We only drop the value because the Pointee trait requires that the metadata is copy
|
||||
// aka trivially droppable
|
||||
alloc::dealloc(self.0.as_ptr().sub(value_offset), layout);
|
||||
// aka trivially droppable.
|
||||
ptr::drop_in_place::<T>(value);
|
||||
|
||||
// Note: Don't deallocate if the layout size is zero, because the pointer
|
||||
// didn't come from the allocator.
|
||||
if layout.size() != 0 {
|
||||
alloc::dealloc(self.0.as_ptr().sub(value_offset), layout);
|
||||
} else {
|
||||
debug_assert!(
|
||||
value_offset == 0 && mem::size_of::<H>() == 0 && value_layout.size() == 0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,7 +223,9 @@ impl<H> WithHeader<H> {
|
||||
// needed to align the header. Subtracting the header size from the aligned data pointer
|
||||
// will always result in an aligned header pointer, it just may not point to the
|
||||
// beginning of the allocation.
|
||||
unsafe { self.0.as_ptr().sub(Self::header_size()) as *mut H }
|
||||
let hp = unsafe { self.0.as_ptr().sub(Self::header_size()) as *mut H };
|
||||
debug_assert!(hp.is_aligned());
|
||||
hp
|
||||
}
|
||||
|
||||
fn value(&self) -> *mut u8 {
|
||||
|
@ -169,6 +169,7 @@
|
||||
#![feature(nll)] // Not necessary, but here to test the `nll` feature.
|
||||
#![feature(rustc_allow_const_fn_unstable)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(pointer_is_aligned)]
|
||||
#![feature(slice_internals)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
|
@ -42,6 +42,9 @@
|
||||
#![feature(panic_update_hook)]
|
||||
#![feature(slice_flatten)]
|
||||
#![feature(thin_box)]
|
||||
#![feature(bench_black_box)]
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(once_cell)]
|
||||
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
@ -1,3 +1,4 @@
|
||||
use core::fmt::Debug;
|
||||
use core::mem::size_of;
|
||||
use std::boxed::ThinBox;
|
||||
|
||||
@ -24,3 +25,231 @@ fn want_thin() {
|
||||
assert!(is_thin::<[i32]>());
|
||||
assert!(is_thin::<i32>());
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn verify_aligned<T>(ptr: *const T) {
|
||||
// Use `black_box` to attempt to obscure the fact that we're calling this
|
||||
// function on pointers that come from box/references, which the compiler
|
||||
// would otherwise realize is impossible (because it would mean we've
|
||||
// already executed UB).
|
||||
//
|
||||
// That is, we'd *like* it to be possible for the asserts in this function
|
||||
// to detect brokenness in the ThinBox impl.
|
||||
//
|
||||
// It would probably be better if we instead had these as debug_asserts
|
||||
// inside `ThinBox`, prior to the point where we do the UB. Anyway, in
|
||||
// practice these checks are mostly just smoke-detectors for an extremely
|
||||
// broken `ThinBox` impl, since it's an extremely subtle piece of code.
|
||||
let ptr = core::hint::black_box(ptr);
|
||||
let align = core::mem::align_of::<T>();
|
||||
assert!(
|
||||
(ptr.addr() & (align - 1)) == 0 && !ptr.is_null(),
|
||||
"misaligned ThinBox data; valid pointers to `{}` should be aligned to {align}: {ptr:p}",
|
||||
core::any::type_name::<T>(),
|
||||
);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn check_thin_sized<T: Debug + PartialEq + Clone>(make: impl FnOnce() -> T) {
|
||||
let value = make();
|
||||
let boxed = ThinBox::new(value.clone());
|
||||
let val = &*boxed;
|
||||
verify_aligned(val as *const T);
|
||||
assert_eq!(val, &value);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn check_thin_dyn<T: Debug + PartialEq + Clone>(make: impl FnOnce() -> T) {
|
||||
let value = make();
|
||||
let wanted_debug = format!("{value:?}");
|
||||
let boxed: ThinBox<dyn Debug> = ThinBox::new_unsize(value.clone());
|
||||
let val = &*boxed;
|
||||
// wide reference -> wide pointer -> thin pointer
|
||||
verify_aligned(val as *const dyn Debug as *const T);
|
||||
let got_debug = format!("{val:?}");
|
||||
assert_eq!(wanted_debug, got_debug);
|
||||
}
|
||||
|
||||
macro_rules! define_test {
|
||||
(
|
||||
@test_name: $testname:ident;
|
||||
|
||||
$(#[$m:meta])*
|
||||
struct $Type:ident($inner:ty);
|
||||
|
||||
$($test_stmts:tt)*
|
||||
) => {
|
||||
#[test]
|
||||
fn $testname() {
|
||||
use core::sync::atomic::{AtomicIsize, Ordering};
|
||||
// Define the type, and implement new/clone/drop in such a way that
|
||||
// the number of live instances will be counted.
|
||||
$(#[$m])*
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct $Type {
|
||||
_priv: $inner,
|
||||
}
|
||||
|
||||
impl Clone for $Type {
|
||||
fn clone(&self) -> Self {
|
||||
verify_aligned(self);
|
||||
Self::new(self._priv.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for $Type {
|
||||
fn drop(&mut self) {
|
||||
verify_aligned(self);
|
||||
Self::modify_live(-1);
|
||||
}
|
||||
}
|
||||
|
||||
impl $Type {
|
||||
fn new(i: $inner) -> Self {
|
||||
Self::modify_live(1);
|
||||
Self { _priv: i }
|
||||
}
|
||||
|
||||
fn modify_live(n: isize) -> isize {
|
||||
static COUNTER: AtomicIsize = AtomicIsize::new(0);
|
||||
COUNTER.fetch_add(n, Ordering::Relaxed) + n
|
||||
}
|
||||
|
||||
fn live_objects() -> isize {
|
||||
Self::modify_live(0)
|
||||
}
|
||||
}
|
||||
// Run the test statements
|
||||
let _: () = { $($test_stmts)* };
|
||||
// Check that we didn't leak anything, or call drop too many times.
|
||||
assert_eq!(
|
||||
$Type::live_objects(), 0,
|
||||
"Wrong number of drops of {}, `initializations - drops` should be 0.",
|
||||
stringify!($Type),
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align1zst;
|
||||
struct Align1Zst(());
|
||||
|
||||
check_thin_sized(|| Align1Zst::new(()));
|
||||
check_thin_dyn(|| Align1Zst::new(()));
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align1small;
|
||||
struct Align1Small(u8);
|
||||
|
||||
check_thin_sized(|| Align1Small::new(50));
|
||||
check_thin_dyn(|| Align1Small::new(50));
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align1_size_not_pow2;
|
||||
struct Align64NotPow2Size([u8; 79]);
|
||||
|
||||
check_thin_sized(|| Align64NotPow2Size::new([100; 79]));
|
||||
check_thin_dyn(|| Align64NotPow2Size::new([100; 79]));
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align1big;
|
||||
struct Align1Big([u8; 256]);
|
||||
|
||||
check_thin_sized(|| Align1Big::new([5u8; 256]));
|
||||
check_thin_dyn(|| Align1Big::new([5u8; 256]));
|
||||
}
|
||||
|
||||
// Note: `#[repr(align(2))]` is worth testing because
|
||||
// - can have pointers which are misaligned, unlike align(1)
|
||||
// - is still expected to have an alignment less than the alignment of a vtable.
|
||||
define_test! {
|
||||
@test_name: align2zst;
|
||||
#[repr(align(2))]
|
||||
struct Align2Zst(());
|
||||
|
||||
check_thin_sized(|| Align2Zst::new(()));
|
||||
check_thin_dyn(|| Align2Zst::new(()));
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align2small;
|
||||
#[repr(align(2))]
|
||||
struct Align2Small(u8);
|
||||
|
||||
check_thin_sized(|| Align2Small::new(60));
|
||||
check_thin_dyn(|| Align2Small::new(60));
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align2full;
|
||||
#[repr(align(2))]
|
||||
struct Align2Full([u8; 2]);
|
||||
check_thin_sized(|| Align2Full::new([3u8; 2]));
|
||||
check_thin_dyn(|| Align2Full::new([3u8; 2]));
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align2_size_not_pow2;
|
||||
#[repr(align(2))]
|
||||
struct Align2NotPower2Size([u8; 6]);
|
||||
|
||||
check_thin_sized(|| Align2NotPower2Size::new([3; 6]));
|
||||
check_thin_dyn(|| Align2NotPower2Size::new([3; 6]));
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align2big;
|
||||
#[repr(align(2))]
|
||||
struct Align2Big([u8; 256]);
|
||||
|
||||
check_thin_sized(|| Align2Big::new([5u8; 256]));
|
||||
check_thin_dyn(|| Align2Big::new([5u8; 256]));
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align64zst;
|
||||
#[repr(align(64))]
|
||||
struct Align64Zst(());
|
||||
|
||||
check_thin_sized(|| Align64Zst::new(()));
|
||||
check_thin_dyn(|| Align64Zst::new(()));
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align64small;
|
||||
#[repr(align(64))]
|
||||
struct Align64Small(u8);
|
||||
|
||||
check_thin_sized(|| Align64Small::new(50));
|
||||
check_thin_dyn(|| Align64Small::new(50));
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align64med;
|
||||
#[repr(align(64))]
|
||||
struct Align64Med([u8; 64]);
|
||||
check_thin_sized(|| Align64Med::new([10; 64]));
|
||||
check_thin_dyn(|| Align64Med::new([10; 64]));
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align64_size_not_pow2;
|
||||
#[repr(align(64))]
|
||||
struct Align64NotPow2Size([u8; 192]);
|
||||
|
||||
check_thin_sized(|| Align64NotPow2Size::new([10; 192]));
|
||||
check_thin_dyn(|| Align64NotPow2Size::new([10; 192]));
|
||||
}
|
||||
|
||||
define_test! {
|
||||
@test_name: align64big;
|
||||
#[repr(align(64))]
|
||||
struct Align64Big([u8; 256]);
|
||||
|
||||
check_thin_sized(|| Align64Big::new([10; 256]));
|
||||
check_thin_dyn(|| Align64Big::new([10; 256]));
|
||||
}
|
||||
|
@ -70,9 +70,13 @@ impl Condvar {
|
||||
mutex.lock();
|
||||
res == 0
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn destroy(&self) {
|
||||
let _ = abi::sem_destroy(self.sem1);
|
||||
let _ = abi::sem_destroy(self.sem2);
|
||||
impl Drop for Condvar {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let _ = abi::sem_destroy(self.sem1);
|
||||
let _ = abi::sem_destroy(self.sem2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -215,7 +215,4 @@ impl Mutex {
|
||||
}
|
||||
guard.locked
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {}
|
||||
}
|
||||
|
@ -84,12 +84,6 @@ impl RwLock {
|
||||
// FIXME: should only wake up one of these some of the time
|
||||
self.cond.notify_all();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {
|
||||
self.lock.destroy();
|
||||
self.cond.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
|
@ -117,8 +117,6 @@ impl Condvar {
|
||||
unsafe { mutex.lock() };
|
||||
success
|
||||
}
|
||||
|
||||
pub unsafe fn destroy(&self) {}
|
||||
}
|
||||
|
||||
mod waiter_queue {
|
||||
|
@ -64,8 +64,10 @@ impl Mutex {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn destroy(&self) {
|
||||
impl Drop for Mutex {
|
||||
fn drop(&mut self) {
|
||||
if let Some(mtx) = self.mtx.get().map(|x| x.0) {
|
||||
expect_success_aborting(unsafe { abi::del_mtx(mtx) }, &"del_mtx");
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::sys::locks::Mutex;
|
||||
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
|
||||
use crate::time::Duration;
|
||||
|
||||
use super::waitqueue::{SpinMutex, WaitQueue, WaitVariable};
|
||||
@ -7,16 +8,19 @@ pub struct Condvar {
|
||||
inner: SpinMutex<WaitVariable<()>>,
|
||||
}
|
||||
|
||||
pub type MovableCondvar = Box<Condvar>;
|
||||
pub(crate) type MovableCondvar = LazyBox<Condvar>;
|
||||
|
||||
impl LazyInit for Condvar {
|
||||
fn init() -> Box<Self> {
|
||||
Box::new(Self::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl Condvar {
|
||||
pub const fn new() -> Condvar {
|
||||
Condvar { inner: SpinMutex::new(WaitVariable::new(())) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn init(&mut self) {}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn notify_one(&self) {
|
||||
let _ = WaitQueue::notify_one(self.inner.lock());
|
||||
@ -38,7 +42,4 @@ impl Condvar {
|
||||
unsafe { mutex.lock() };
|
||||
success
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {}
|
||||
}
|
||||
|
@ -1,11 +1,18 @@
|
||||
use super::waitqueue::{try_lock_or_false, SpinMutex, WaitQueue, WaitVariable};
|
||||
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
|
||||
|
||||
pub struct Mutex {
|
||||
inner: SpinMutex<WaitVariable<bool>>,
|
||||
}
|
||||
|
||||
// not movable: see UnsafeList implementation
|
||||
pub type MovableMutex = Box<Mutex>;
|
||||
pub(crate) type MovableMutex = LazyBox<Mutex>;
|
||||
|
||||
impl LazyInit for Mutex {
|
||||
fn init() -> Box<Self> {
|
||||
Box::new(Self::new())
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
|
||||
impl Mutex {
|
||||
@ -52,7 +59,4 @@ impl Mutex {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
mod tests;
|
||||
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
|
||||
|
||||
use super::waitqueue::{
|
||||
try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable,
|
||||
@ -13,7 +14,13 @@ pub struct RwLock {
|
||||
writer: SpinMutex<WaitVariable<bool>>,
|
||||
}
|
||||
|
||||
pub type MovableRwLock = Box<RwLock>;
|
||||
pub(crate) type MovableRwLock = LazyBox<RwLock>;
|
||||
|
||||
impl LazyInit for RwLock {
|
||||
fn init() -> Box<Self> {
|
||||
Box::new(Self::new())
|
||||
}
|
||||
}
|
||||
|
||||
// Check at compile time that RwLock size matches C definition (see test_c_rwlock_initializer below)
|
||||
//
|
||||
@ -168,9 +175,6 @@ impl RwLock {
|
||||
unsafe { self.__read_unlock(rguard, wguard) };
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {}
|
||||
}
|
||||
|
||||
// The following functions are needed by libunwind. These symbols are named
|
||||
|
@ -82,9 +82,11 @@ impl RwLock {
|
||||
let rwl = self.raw();
|
||||
expect_success_aborting(unsafe { abi::rwl_unl_rwl(rwl) }, &"rwl_unl_rwl");
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for RwLock {
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {
|
||||
fn drop(&mut self) {
|
||||
if let Some(rwl) = self.rwl.get().map(|x| x.0) {
|
||||
expect_success_aborting(unsafe { abi::rwl_del_rwl(rwl) }, &"rwl_del_rwl");
|
||||
}
|
||||
|
@ -24,9 +24,6 @@ impl Mutex {
|
||||
#[inline]
|
||||
pub unsafe fn init(&mut self) {}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn try_lock(&self) -> bool {
|
||||
self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_ok()
|
||||
@ -118,12 +115,6 @@ impl Condvar {
|
||||
Self { futex: AtomicU32::new(0) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn init(&mut self) {}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {}
|
||||
|
||||
// All the memory orderings here are `Relaxed`,
|
||||
// because synchronization is done by unlocking and locking the mutex.
|
||||
|
||||
|
@ -63,9 +63,6 @@ impl RwLock {
|
||||
Self { state: AtomicU32::new(0), writer_notify: AtomicU32::new(0) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn try_read(&self) -> bool {
|
||||
self.state
|
||||
|
@ -9,14 +9,14 @@ cfg_if::cfg_if! {
|
||||
))] {
|
||||
mod futex;
|
||||
mod futex_rwlock;
|
||||
pub use futex::{Mutex, MovableMutex, Condvar, MovableCondvar};
|
||||
pub use futex_rwlock::{RwLock, MovableRwLock};
|
||||
pub(crate) use futex::{Mutex, MovableMutex, MovableCondvar};
|
||||
pub(crate) use futex_rwlock::{RwLock, MovableRwLock};
|
||||
} else {
|
||||
mod pthread_mutex;
|
||||
mod pthread_rwlock;
|
||||
mod pthread_condvar;
|
||||
pub use pthread_mutex::{Mutex, MovableMutex};
|
||||
pub use pthread_rwlock::{RwLock, MovableRwLock};
|
||||
pub use pthread_condvar::{Condvar, MovableCondvar};
|
||||
pub(crate) use pthread_mutex::{Mutex, MovableMutex};
|
||||
pub(crate) use pthread_rwlock::{RwLock, MovableRwLock};
|
||||
pub(crate) use pthread_condvar::MovableCondvar;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::sys::locks::{pthread_mutex, Mutex};
|
||||
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
|
||||
use crate::time::Duration;
|
||||
|
||||
pub struct Condvar {
|
||||
inner: UnsafeCell<libc::pthread_cond_t>,
|
||||
}
|
||||
|
||||
pub type MovableCondvar = Box<Condvar>;
|
||||
pub(crate) type MovableCondvar = LazyBox<Condvar>;
|
||||
|
||||
unsafe impl Send for Condvar {}
|
||||
unsafe impl Sync for Condvar {}
|
||||
@ -18,6 +19,14 @@ fn saturating_cast_to_time_t(value: u64) -> libc::time_t {
|
||||
if value > <libc::time_t>::MAX as u64 { <libc::time_t>::MAX } else { value as libc::time_t }
|
||||
}
|
||||
|
||||
impl LazyInit for Condvar {
|
||||
fn init() -> Box<Self> {
|
||||
let mut condvar = Box::new(Self::new());
|
||||
unsafe { condvar.init() };
|
||||
condvar
|
||||
}
|
||||
}
|
||||
|
||||
impl Condvar {
|
||||
pub const fn new() -> Condvar {
|
||||
// Might be moved and address is changing it is better to avoid
|
||||
@ -32,14 +41,14 @@ impl Condvar {
|
||||
target_os = "android",
|
||||
target_os = "redox"
|
||||
))]
|
||||
pub unsafe fn init(&mut self) {}
|
||||
unsafe fn init(&mut self) {}
|
||||
|
||||
// NOTE: ESP-IDF's PTHREAD_COND_INITIALIZER support is not released yet
|
||||
// So on that platform, init() should always be called
|
||||
// Moreover, that platform does not have pthread_condattr_setclock support,
|
||||
// hence that initialization should be skipped as well
|
||||
#[cfg(target_os = "espidf")]
|
||||
pub unsafe fn init(&mut self) {
|
||||
unsafe fn init(&mut self) {
|
||||
let r = libc::pthread_cond_init(self.inner.get(), crate::ptr::null());
|
||||
assert_eq!(r, 0);
|
||||
}
|
||||
@ -52,7 +61,7 @@ impl Condvar {
|
||||
target_os = "redox",
|
||||
target_os = "espidf"
|
||||
)))]
|
||||
pub unsafe fn init(&mut self) {
|
||||
unsafe fn init(&mut self) {
|
||||
use crate::mem::MaybeUninit;
|
||||
let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit();
|
||||
let r = libc::pthread_condattr_init(attr.as_mut_ptr());
|
||||
@ -179,14 +188,14 @@ impl Condvar {
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(target_os = "dragonfly"))]
|
||||
pub unsafe fn destroy(&self) {
|
||||
unsafe fn destroy(&mut self) {
|
||||
let r = libc::pthread_cond_destroy(self.inner.get());
|
||||
debug_assert_eq!(r, 0);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub unsafe fn destroy(&self) {
|
||||
unsafe fn destroy(&mut self) {
|
||||
let r = libc::pthread_cond_destroy(self.inner.get());
|
||||
// On DragonFly pthread_cond_destroy() returns EINVAL if called on
|
||||
// a condvar that was just initialized with
|
||||
@ -195,3 +204,10 @@ impl Condvar {
|
||||
debug_assert!(r == 0 || r == libc::EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Condvar {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.destroy() };
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::sys::cvt_nz;
|
||||
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
|
||||
|
||||
pub struct Mutex {
|
||||
inner: UnsafeCell<libc::pthread_mutex_t>,
|
||||
}
|
||||
|
||||
pub type MovableMutex = Box<Mutex>;
|
||||
pub(crate) type MovableMutex = LazyBox<Mutex>;
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn raw(m: &Mutex) -> *mut libc::pthread_mutex_t {
|
||||
@ -16,6 +17,14 @@ pub unsafe fn raw(m: &Mutex) -> *mut libc::pthread_mutex_t {
|
||||
unsafe impl Send for Mutex {}
|
||||
unsafe impl Sync for Mutex {}
|
||||
|
||||
impl LazyInit for Mutex {
|
||||
fn init() -> Box<Self> {
|
||||
let mut mutex = Box::new(Self::new());
|
||||
unsafe { mutex.init() };
|
||||
mutex
|
||||
}
|
||||
}
|
||||
|
||||
impl Mutex {
|
||||
pub const fn new() -> Mutex {
|
||||
// Might be moved to a different address, so it is better to avoid
|
||||
@ -73,13 +82,13 @@ impl Mutex {
|
||||
}
|
||||
#[inline]
|
||||
#[cfg(not(target_os = "dragonfly"))]
|
||||
pub unsafe fn destroy(&self) {
|
||||
unsafe fn destroy(&mut self) {
|
||||
let r = libc::pthread_mutex_destroy(self.inner.get());
|
||||
debug_assert_eq!(r, 0);
|
||||
}
|
||||
#[inline]
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub unsafe fn destroy(&self) {
|
||||
unsafe fn destroy(&mut self) {
|
||||
let r = libc::pthread_mutex_destroy(self.inner.get());
|
||||
// On DragonFly pthread_mutex_destroy() returns EINVAL if called on a
|
||||
// mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER.
|
||||
@ -89,6 +98,13 @@ impl Mutex {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Mutex {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.destroy() };
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct PthreadMutexAttr<'a>(pub &'a mut MaybeUninit<libc::pthread_mutexattr_t>);
|
||||
|
||||
impl Drop for PthreadMutexAttr<'_> {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::sync::atomic::{AtomicUsize, Ordering};
|
||||
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
|
||||
|
||||
pub struct RwLock {
|
||||
inner: UnsafeCell<libc::pthread_rwlock_t>,
|
||||
@ -7,11 +8,17 @@ pub struct RwLock {
|
||||
num_readers: AtomicUsize,
|
||||
}
|
||||
|
||||
pub type MovableRwLock = Box<RwLock>;
|
||||
pub(crate) type MovableRwLock = LazyBox<RwLock>;
|
||||
|
||||
unsafe impl Send for RwLock {}
|
||||
unsafe impl Sync for RwLock {}
|
||||
|
||||
impl LazyInit for RwLock {
|
||||
fn init() -> Box<Self> {
|
||||
Box::new(Self::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl RwLock {
|
||||
pub const fn new() -> RwLock {
|
||||
RwLock {
|
||||
@ -128,7 +135,7 @@ impl RwLock {
|
||||
self.raw_unlock();
|
||||
}
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {
|
||||
unsafe fn destroy(&mut self) {
|
||||
let r = libc::pthread_rwlock_destroy(self.inner.get());
|
||||
// On DragonFly pthread_rwlock_destroy() returns EINVAL if called on a
|
||||
// rwlock that was just initialized with
|
||||
@ -141,3 +148,10 @@ impl RwLock {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for RwLock {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.destroy() };
|
||||
}
|
||||
}
|
||||
|
@ -10,9 +10,6 @@ impl Condvar {
|
||||
Condvar {}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn init(&mut self) {}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn notify_one(&self) {}
|
||||
|
||||
@ -26,7 +23,4 @@ impl Condvar {
|
||||
pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
|
||||
panic!("condvar wait not supported");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {}
|
||||
}
|
||||
|
@ -32,7 +32,4 @@ impl Mutex {
|
||||
pub unsafe fn try_lock(&self) -> bool {
|
||||
self.locked.replace(true) == false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {}
|
||||
}
|
||||
|
@ -62,7 +62,4 @@ impl RwLock {
|
||||
pub unsafe fn write_unlock(&self) {
|
||||
assert_eq!(self.mode.replace(0), -1);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {}
|
||||
}
|
||||
|
@ -54,8 +54,8 @@ cfg_if::cfg_if! {
|
||||
#![allow(unsafe_op_in_unsafe_fn)]
|
||||
mod futex;
|
||||
mod futex_rwlock;
|
||||
pub use futex::{Mutex, MovableMutex, Condvar, MovableCondvar};
|
||||
pub use futex_rwlock::{RwLock, MovableRwLock};
|
||||
pub(crate) use futex::{Mutex, MovableMutex, Condvar, MovableCondvar};
|
||||
pub(crate) use futex_rwlock::{RwLock, MovableRwLock};
|
||||
}
|
||||
#[path = "atomics/futex.rs"]
|
||||
pub mod futex;
|
||||
|
@ -18,9 +18,6 @@ impl Condvar {
|
||||
Condvar { inner: UnsafeCell::new(c::CONDITION_VARIABLE_INIT) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn init(&mut self) {}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn wait(&self, mutex: &Mutex) {
|
||||
let r = c::SleepConditionVariableSRW(self.inner.get(), mutex::raw(mutex), c::INFINITE, 0);
|
||||
@ -51,8 +48,4 @@ impl Condvar {
|
||||
pub unsafe fn notify_all(&self) {
|
||||
c::WakeAllConditionVariable(self.inner.get())
|
||||
}
|
||||
|
||||
pub unsafe fn destroy(&self) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
@ -53,9 +53,4 @@ impl Mutex {
|
||||
pub unsafe fn unlock(&self) {
|
||||
c::ReleaseSRWLockExclusive(raw(self));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {
|
||||
// SRWLock does not need to be destroyed.
|
||||
}
|
||||
}
|
||||
|
@ -38,9 +38,4 @@ impl RwLock {
|
||||
pub unsafe fn write_unlock(&self) {
|
||||
c::ReleaseSRWLockExclusive(self.inner.get())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,7 @@ pub struct Condvar {
|
||||
impl Condvar {
|
||||
/// Creates a new condition variable for use.
|
||||
pub fn new() -> Self {
|
||||
let mut c = imp::MovableCondvar::from(imp::Condvar::new());
|
||||
unsafe { c.init() };
|
||||
Self { inner: c, check: CondvarCheck::new() }
|
||||
Self { inner: imp::MovableCondvar::new(), check: CondvarCheck::new() }
|
||||
}
|
||||
|
||||
/// Signals one waiter on this condition variable to wake up.
|
||||
@ -55,9 +53,3 @@ impl Condvar {
|
||||
self.inner.wait_timeout(mutex.raw(), dur)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Condvar {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.inner.destroy() };
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::ptr;
|
||||
use crate::sync::atomic::{AtomicPtr, Ordering};
|
||||
use crate::sys::locks as imp;
|
||||
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
|
||||
use crate::sys_common::mutex::MovableMutex;
|
||||
|
||||
pub trait CondvarCheck {
|
||||
@ -9,7 +10,7 @@ pub trait CondvarCheck {
|
||||
|
||||
/// For boxed mutexes, a `Condvar` will check it's only ever used with the same
|
||||
/// mutex, based on its (stable) address.
|
||||
impl CondvarCheck for Box<imp::Mutex> {
|
||||
impl<T: LazyInit> CondvarCheck for LazyBox<T> {
|
||||
type Check = SameMutexCheck;
|
||||
}
|
||||
|
||||
|
77
library/std/src/sys_common/lazy_box.rs
Normal file
77
library/std/src/sys_common/lazy_box.rs
Normal file
@ -0,0 +1,77 @@
|
||||
#![allow(dead_code)] // Only used on some platforms.
|
||||
|
||||
// This is used to wrap pthread {Mutex, Condvar, RwLock} in.
|
||||
|
||||
use crate::marker::PhantomData;
|
||||
use crate::ops::{Deref, DerefMut};
|
||||
use crate::ptr::null_mut;
|
||||
use crate::sync::atomic::{
|
||||
AtomicPtr,
|
||||
Ordering::{AcqRel, Acquire},
|
||||
};
|
||||
|
||||
pub(crate) struct LazyBox<T: LazyInit> {
|
||||
ptr: AtomicPtr<T>,
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
pub(crate) trait LazyInit {
|
||||
/// This is called before the box is allocated, to provide the value to
|
||||
/// move into the new box.
|
||||
///
|
||||
/// It might be called more than once per LazyBox, as multiple threads
|
||||
/// might race to initialize it concurrently, each constructing and initializing
|
||||
/// their own box. (All but one of them will be destroyed right after.)
|
||||
fn init() -> Box<Self>;
|
||||
}
|
||||
|
||||
impl<T: LazyInit> LazyBox<T> {
|
||||
#[inline]
|
||||
pub const fn new() -> Self {
|
||||
Self { ptr: AtomicPtr::new(null_mut()), _phantom: PhantomData }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_pointer(&self) -> *mut T {
|
||||
let ptr = self.ptr.load(Acquire);
|
||||
if ptr.is_null() { self.initialize() } else { ptr }
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn initialize(&self) -> *mut T {
|
||||
let new_ptr = Box::into_raw(T::init());
|
||||
match self.ptr.compare_exchange(null_mut(), new_ptr, AcqRel, Acquire) {
|
||||
Ok(_) => new_ptr,
|
||||
Err(ptr) => {
|
||||
// Lost the race to another thread.
|
||||
// Drop the box we created, and use the one from the other thread instead.
|
||||
drop(unsafe { Box::from_raw(new_ptr) });
|
||||
ptr
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: LazyInit> Deref for LazyBox<T> {
|
||||
type Target = T;
|
||||
#[inline]
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { &*self.get_pointer() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: LazyInit> DerefMut for LazyBox<T> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { &mut *self.get_pointer() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: LazyInit> Drop for LazyBox<T> {
|
||||
fn drop(&mut self) {
|
||||
let ptr = *self.ptr.get_mut();
|
||||
if !ptr.is_null() {
|
||||
drop(unsafe { Box::from_raw(ptr) });
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ pub mod backtrace;
|
||||
pub mod condvar;
|
||||
pub mod fs;
|
||||
pub mod io;
|
||||
pub mod lazy_box;
|
||||
pub mod memchr;
|
||||
pub mod mutex;
|
||||
pub mod process;
|
||||
|
@ -61,9 +61,7 @@ unsafe impl Sync for MovableMutex {}
|
||||
impl MovableMutex {
|
||||
/// Creates a new mutex.
|
||||
pub fn new() -> Self {
|
||||
let mut mutex = imp::MovableMutex::from(imp::Mutex::new());
|
||||
unsafe { mutex.init() };
|
||||
Self(mutex)
|
||||
Self(imp::MovableMutex::new())
|
||||
}
|
||||
|
||||
pub(super) fn raw(&self) -> &imp::Mutex {
|
||||
@ -92,9 +90,3 @@ impl MovableMutex {
|
||||
self.0.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MovableMutex {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.0.destroy() };
|
||||
}
|
||||
}
|
||||
|
@ -168,13 +168,6 @@ impl<T> ReentrantMutex<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for ReentrantMutex<T> {
|
||||
fn drop(&mut self) {
|
||||
// Safety: We're the unique owner of this mutex and not going to use it afterwards.
|
||||
unsafe { self.mutex.destroy() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for ReentrantMutexGuard<'_, T> {
|
||||
type Target = T;
|
||||
|
||||
|
@ -74,7 +74,7 @@ pub struct MovableRwLock(imp::MovableRwLock);
|
||||
impl MovableRwLock {
|
||||
/// Creates a new reader-writer lock for use.
|
||||
pub fn new() -> Self {
|
||||
Self(imp::MovableRwLock::from(imp::RwLock::new()))
|
||||
Self(imp::MovableRwLock::new())
|
||||
}
|
||||
|
||||
/// Acquires shared access to the underlying lock, blocking the current
|
||||
@ -126,9 +126,3 @@ impl MovableRwLock {
|
||||
self.0.write_unlock()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MovableRwLock {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.0.destroy() };
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
fn function(#[inline] param: u32) {
|
||||
//~^ ERROR attribute should be applied to function or closure
|
||||
//~| ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes
|
||||
//~| ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/attrs-on-params.rs:3:13
|
||||
|
|
||||
LL | fn function(#[inline] param: u32) {
|
||||
|
41
src/test/ui/codegen/auxiliary/issue-97708-aux.rs
Normal file
41
src/test/ui/codegen/auxiliary/issue-97708-aux.rs
Normal file
@ -0,0 +1,41 @@
|
||||
use std::{ptr::NonNull, task::Poll};
|
||||
|
||||
struct TaskRef;
|
||||
|
||||
struct Header {
|
||||
vtable: &'static Vtable,
|
||||
}
|
||||
|
||||
struct Vtable {
|
||||
poll: unsafe fn(TaskRef) -> Poll<()>,
|
||||
deallocate: unsafe fn(NonNull<Header>),
|
||||
}
|
||||
|
||||
// in the "Header" type, which is a private type in maitake
|
||||
impl Header {
|
||||
pub(crate) const fn new_stub() -> Self {
|
||||
unsafe fn nop(_ptr: TaskRef) -> Poll<()> {
|
||||
Poll::Pending
|
||||
}
|
||||
|
||||
unsafe fn nop_deallocate(ptr: NonNull<Header>) {
|
||||
unreachable!("stub task ({ptr:p}) should never be deallocated!");
|
||||
}
|
||||
|
||||
Self { vtable: &Vtable { poll: nop, deallocate: nop_deallocate } }
|
||||
}
|
||||
}
|
||||
|
||||
// This is a public type in `maitake`
|
||||
#[repr(transparent)]
|
||||
#[cfg_attr(loom, allow(dead_code))]
|
||||
pub struct TaskStub {
|
||||
hdr: Header,
|
||||
}
|
||||
|
||||
impl TaskStub {
|
||||
/// Create a new unique stub [`Task`].
|
||||
pub const fn new() -> Self {
|
||||
Self { hdr: Header::new_stub() }
|
||||
}
|
||||
}
|
9
src/test/ui/codegen/issue-97708.rs
Normal file
9
src/test/ui/codegen/issue-97708.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// build-pass
|
||||
// aux-build:issue-97708-aux.rs
|
||||
|
||||
extern crate issue_97708_aux;
|
||||
use issue_97708_aux::TaskStub;
|
||||
|
||||
static TASK_STUB: TaskStub = TaskStub::new();
|
||||
|
||||
fn main() {}
|
15
src/test/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs
Normal file
15
src/test/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// check-pass
|
||||
#![feature(lint_reasons)]
|
||||
|
||||
#[warn(unused_variables)]
|
||||
|
||||
/// This should catch the unused_variables lint and not emit anything
|
||||
fn check_fulfilled_expectation(#[expect(unused_variables)] unused_value: u32) {}
|
||||
|
||||
fn check_unfulfilled_expectation(#[expect(unused_variables)] used_value: u32) {
|
||||
//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
|
||||
//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default
|
||||
println!("I use the value {used_value}");
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,10 @@
|
||||
warning: this lint expectation is unfulfilled
|
||||
--> $DIR/expect_on_fn_params.rs:9:43
|
||||
|
|
||||
LL | fn check_unfulfilled_expectation(#[expect(unused_variables)] used_value: u32) {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(unfulfilled_lint_expectations)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -7,11 +7,11 @@ extern "C" {
|
||||
/// Bar
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[must_use]
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
/// Baz
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[no_mangle] b: i32,
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
);
|
||||
}
|
||||
|
||||
@ -23,11 +23,11 @@ type FnType = fn(
|
||||
/// Bar
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[must_use]
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
/// Baz
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[no_mangle] b: i32,
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
);
|
||||
|
||||
pub fn foo(
|
||||
@ -38,11 +38,11 @@ pub fn foo(
|
||||
/// Bar
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[must_use]
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
/// Baz
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[no_mangle] b: i32,
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
) {}
|
||||
|
||||
struct SelfStruct {}
|
||||
@ -58,11 +58,11 @@ impl SelfStruct {
|
||||
/// Baz
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[must_use]
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
/// Qux
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[no_mangle] b: i32,
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
) {}
|
||||
|
||||
fn issue_64682_associated_fn(
|
||||
@ -73,11 +73,11 @@ impl SelfStruct {
|
||||
/// Baz
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[must_use]
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
/// Qux
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[no_mangle] b: i32,
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
) {}
|
||||
}
|
||||
|
||||
@ -94,11 +94,11 @@ impl RefStruct {
|
||||
/// Baz
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[must_use]
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
/// Qux
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[no_mangle] b: i32,
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
) {}
|
||||
}
|
||||
trait RefTrait {
|
||||
@ -113,11 +113,11 @@ trait RefTrait {
|
||||
/// Baz
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[must_use]
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
/// Qux
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[no_mangle] b: i32,
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
) {}
|
||||
|
||||
fn issue_64682_associated_fn(
|
||||
@ -128,11 +128,11 @@ trait RefTrait {
|
||||
/// Baz
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[must_use]
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
/// Qux
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[no_mangle] b: i32,
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
) {}
|
||||
}
|
||||
|
||||
@ -148,11 +148,11 @@ impl RefTrait for RefStruct {
|
||||
/// Baz
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[must_use]
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
/// Qux
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[no_mangle] b: i32,
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
) {}
|
||||
}
|
||||
|
||||
@ -165,10 +165,10 @@ fn main() {
|
||||
/// Bar
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[must_use]
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
/// Baz
|
||||
//~^ ERROR documentation comments cannot be applied to function
|
||||
#[no_mangle] b: i32
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
|
||||
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
| {};
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Bar
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:9:9
|
||||
|
|
||||
LL | #[must_use]
|
||||
@ -82,7 +82,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Baz
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:13:9
|
||||
|
|
||||
LL | #[no_mangle] b: i32,
|
||||
@ -100,7 +100,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Bar
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:25:5
|
||||
|
|
||||
LL | #[must_use]
|
||||
@ -112,7 +112,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Baz
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:29:5
|
||||
|
|
||||
LL | #[no_mangle] b: i32,
|
||||
@ -130,7 +130,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Bar
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:40:5
|
||||
|
|
||||
LL | #[must_use]
|
||||
@ -142,7 +142,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Baz
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:44:5
|
||||
|
|
||||
LL | #[no_mangle] b: i32,
|
||||
@ -166,7 +166,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Baz
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:60:9
|
||||
|
|
||||
LL | #[must_use]
|
||||
@ -178,7 +178,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Qux
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:64:9
|
||||
|
|
||||
LL | #[no_mangle] b: i32,
|
||||
@ -196,7 +196,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Baz
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:75:9
|
||||
|
|
||||
LL | #[must_use]
|
||||
@ -208,7 +208,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Qux
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:79:9
|
||||
|
|
||||
LL | #[no_mangle] b: i32,
|
||||
@ -232,7 +232,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Baz
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:96:9
|
||||
|
|
||||
LL | #[must_use]
|
||||
@ -244,7 +244,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Qux
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:100:9
|
||||
|
|
||||
LL | #[no_mangle] b: i32,
|
||||
@ -268,7 +268,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Baz
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:115:9
|
||||
|
|
||||
LL | #[must_use]
|
||||
@ -280,7 +280,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Qux
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:119:9
|
||||
|
|
||||
LL | #[no_mangle] b: i32,
|
||||
@ -298,7 +298,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Baz
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:130:9
|
||||
|
|
||||
LL | #[must_use]
|
||||
@ -310,7 +310,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Qux
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:134:9
|
||||
|
|
||||
LL | #[no_mangle] b: i32,
|
||||
@ -334,7 +334,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Baz
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:150:9
|
||||
|
|
||||
LL | #[must_use]
|
||||
@ -346,7 +346,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Qux
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:154:9
|
||||
|
|
||||
LL | #[no_mangle] b: i32,
|
||||
@ -364,7 +364,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Bar
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:167:9
|
||||
|
|
||||
LL | #[must_use]
|
||||
@ -376,7 +376,7 @@ error: documentation comments cannot be applied to function parameters
|
||||
LL | /// Baz
|
||||
| ^^^^^^^ doc comments are not allowed here
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/param-attrs-builtin-attrs.rs:171:9
|
||||
|
|
||||
LL | #[no_mangle] b: i32
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/check-doc-alias-attr-location.rs:22:12
|
||||
|
|
||||
LL | fn foo(#[doc(alias = "qux")] _x: u32) -> Self::X {
|
||||
|
@ -10,12 +10,12 @@ LL | pub size: Vector2<K>
|
||||
| -------------------- this field does not implement `Copy`
|
||||
|
|
||||
note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
|
||||
--> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:5
|
||||
--> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:14
|
||||
|
|
||||
LL | pub loc: Vector2<K>,
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^
|
||||
LL | pub size: Vector2<K>
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^
|
||||
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
|
@ -10,12 +10,12 @@ LL | pub size: Vector2<K>
|
||||
| -------------------- this field does not implement `Copy`
|
||||
|
|
||||
note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
|
||||
--> $DIR/missing-bound-in-derive-copy-impl.rs:11:5
|
||||
--> $DIR/missing-bound-in-derive-copy-impl.rs:11:14
|
||||
|
|
||||
LL | pub loc: Vector2<K>,
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^
|
||||
LL | pub size: Vector2<K>
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^
|
||||
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: consider restricting type parameter `K`
|
||||
|
|
||||
|
@ -8,10 +8,10 @@ LL | impl Copy for W {}
|
||||
| ^^^^
|
||||
|
|
||||
note: the `Copy` impl for `ManuallyDrop<String>` requires that `String: Copy`
|
||||
--> $DIR/union-copy.rs:8:5
|
||||
--> $DIR/union-copy.rs:8:8
|
||||
|
|
||||
LL | a: std::mem::ManuallyDrop<String>
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user