blob: c65df275038dc9f2439c12a864317a1c533bbec9 [file] [log] [blame]
#![deny(clippy::declare_interior_mutable_const)]
#![allow(clippy::missing_const_for_thread_local)]
use core::cell::{Cell, RefCell, UnsafeCell};
use core::mem::{ManuallyDrop, MaybeUninit};
use core::ptr;
use core::sync::atomic::AtomicUsize;
fn main() {}
const _: Cell<u32> = Cell::new(0);
const UNSAFE_CELL: UnsafeCell<u32> = UnsafeCell::new(0); //~ declare_interior_mutable_const
const REF_CELL: RefCell<u32> = RefCell::new(0); //~ declare_interior_mutable_const
const CELL: Cell<u32> = Cell::new(0); //~ declare_interior_mutable_const
// Constants can't contain pointers or references to type with interior mutability.
const fn make_ptr() -> *const Cell<u32> {
ptr::null()
}
const PTR: *const Cell<u32> = make_ptr();
const fn casted_to_cell_ptr() -> *const Cell<u32> {
const VALUE: u32 = 0;
&VALUE as *const _ as *const Cell<u32>
}
const TRANSMUTED_PTR: *const Cell<u32> = casted_to_cell_ptr();
const CELL_TUPLE: (bool, Cell<u32>) = (true, Cell::new(0)); //~ declare_interior_mutable_const
const CELL_ARRAY: [Cell<u32>; 2] = [Cell::new(0), Cell::new(0)]; //~ declare_interior_mutable_const
const UNINIT_CELL: MaybeUninit<Cell<&'static ()>> = MaybeUninit::uninit();
struct CellStruct {
x: u32,
cell: Cell<u32>,
}
//~v declare_interior_mutable_const
const CELL_STRUCT: CellStruct = CellStruct {
x: 0,
cell: Cell::new(0),
};
enum CellEnum {
Cell(Cell<u32>),
}
const CELL_ENUM: CellEnum = CellEnum::Cell(Cell::new(0)); //~ declare_interior_mutable_const
const NONE_CELL: Option<Cell<u32>> = None;
const SOME_CELL: Option<Cell<u32>> = Some(Cell::new(0)); //~ declare_interior_mutable_const
struct NestedCell([(Option<Cell<u32>>,); 1]);
const NONE_NESTED_CELL: NestedCell = NestedCell([(None,)]);
const SOME_NESTED_CELL: NestedCell = NestedCell([(Some(Cell::new(0)),)]); //~ declare_interior_mutable_const
union UnionCell {
cell: ManuallyDrop<Cell<u32>>,
x: u32,
}
//~v declare_interior_mutable_const
const UNION_CELL: UnionCell = UnionCell {
cell: ManuallyDrop::new(Cell::new(0)),
};
// Access to either union field is valid so we have to be conservative here.
const UNION_U32: UnionCell = UnionCell { x: 0 }; //~ declare_interior_mutable_const
struct Assoc;
impl Assoc {
const SELF: Self = Self;
const CELL: Cell<u32> = Cell::new(0); //~ declare_interior_mutable_const
}
struct AssocCell(Cell<u32>);
impl AssocCell {
const SELF: Self = Self(Cell::new(0)); //~ declare_interior_mutable_const
const NONE_SELF: Option<Self> = None;
const SOME_SELF: Option<Self> = Some(Self(Cell::new(0))); //~ declare_interior_mutable_const
}
trait ConstDefault {
// May or may not be `Freeze`
const DEFAULT: Self;
}
impl ConstDefault for u32 {
const DEFAULT: Self = 0;
}
impl<T: ConstDefault> ConstDefault for Cell<T> {
// Interior mutability is forced by the trait.
const DEFAULT: Self = Cell::new(T::DEFAULT);
}
impl<T: ConstDefault> ConstDefault for Option<Cell<T>> {
// Could have been `None`
const DEFAULT: Self = Some(Cell::new(T::DEFAULT)); //~ declare_interior_mutable_const
}
enum GenericEnumCell<T> {
Cell(Cell<T>),
Other(T),
}
impl<T: ConstDefault> ConstDefault for GenericEnumCell<T> {
const DEFAULT: Self = Self::Cell(Cell::new(T::DEFAULT)); //~ declare_interior_mutable_const
}
impl<T: ConstDefault> GenericEnumCell<T> {
const CELL: Self = Self::DEFAULT; //~ declare_interior_mutable_const
const CELL_BY_DEFAULT: Self = Self::Cell(Cell::DEFAULT); //~ declare_interior_mutable_const
const OTHER: Self = Self::Other(T::DEFAULT);
const FROM_OTHER: Self = Self::OTHER;
}
enum GenericNestedEnumCell<T> {
GenericEnumCell(GenericEnumCell<T>),
EnumCell(GenericEnumCell<u32>),
Other(T),
}
impl<T: ConstDefault> GenericNestedEnumCell<T> {
const GENERIC_OTHER: Self = Self::GenericEnumCell(GenericEnumCell::<T>::FROM_OTHER);
const GENERIC_CELL: Self = Self::GenericEnumCell(GenericEnumCell::<T>::CELL); //~ declare_interior_mutable_const
const ENUM_OTHER: Self = Self::EnumCell(GenericEnumCell::<u32>::FROM_OTHER);
const ENUM_CELL: Self = Self::EnumCell(GenericEnumCell::<u32>::CELL); //~ declare_interior_mutable_const
}
trait CellTrait: ConstDefault + Sized {
// Must be non-`Freeze` due to the type
const CELL: Cell<Self>; //~ declare_interior_mutable_const
// May be non-`Freeze`, but may not be
const OPTION_CELL: Option<Cell<Self>>;
// May get redefined by the impl, but the default is non-`Freeze`.
const SOME_CELL: Option<Cell<Self>> = Some(Cell::new(Self::DEFAULT)); //~ declare_interior_mutable_const
// May get redefined by the impl, but the default is `Freeze`.
const NONE_CELL: Option<Cell<Self>> = None;
}
trait CellWithAssoc {
type T;
const DEFAULT: Self::T;
// Must be non-`Freeze` due to the type
const CELL: Cell<Self::T>; //~ declare_interior_mutable_const
// May be non-`Freeze`, but may not be
const OPTION_CELL: Option<Cell<Self::T>>;
// May get redefined by the impl, but the default is non-`Freeze`.
const SOME_CELL: Option<Cell<Self::T>> = Some(Cell::new(Self::DEFAULT)); //~ declare_interior_mutable_const
// May get redefined by the impl, but the default is `Freeze`.
const NONE_CELL: Option<Cell<Self::T>> = None;
}
impl CellWithAssoc for () {
type T = u32;
const DEFAULT: Self::T = 0;
const CELL: Cell<Self::T> = Cell::new(0);
const OPTION_CELL: Option<Cell<Self::T>> = None;
}
trait WithAssoc {
type T;
const VALUE: Self::T;
}
impl WithAssoc for u32 {
type T = Cell<u32>;
// The cell comes from the impl block, not the trait.
const VALUE: Self::T = Cell::new(0); //~ declare_interior_mutable_const
}
trait WithLayeredAssoc {
type T: WithAssoc;
const VALUE: <Self::T as WithAssoc>::T;
}
impl WithLayeredAssoc for u32 {
type T = u32;
// The cell comes from the impl block, not the trait.
const VALUE: <Self::T as WithAssoc>::T = Cell::new(0); //~ declare_interior_mutable_const
}
trait WithGenericAssoc {
type T<U>;
const VALUE: Self::T<u32>;
}
impl WithGenericAssoc for u32 {
type T<U> = Cell<U>;
const VALUE: Self::T<u32> = Cell::new(0); //~ declare_interior_mutable_const
}
trait WithGenericAssocCell {
type T<U>;
const VALUE: Self::T<Cell<u32>>;
}
impl WithGenericAssocCell for u32 {
type T<U> = Option<U>;
const VALUE: Self::T<Cell<u32>> = None;
}
impl WithGenericAssocCell for i32 {
type T<U> = Option<U>;
const VALUE: Self::T<Cell<u32>> = Some(Cell::new(0)); //~ declare_interior_mutable_const
}
thread_local!(static THREAD_LOCAL_CELL: Cell<u32> = const { Cell::new(0) });
thread_local!(static THREAD_LOCAL_CELL2: Cell<u32> = Cell::new(0));