| #![deny(clippy::declare_interior_mutable_const)] | |
| #![expect(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 cast_to_cell_ptr() -> *const Cell<u32> { | |
| const VALUE: u32 = 0; | |
| &VALUE as *const _ as *const Cell<u32> | |
| } | |
| const TRANSMUTED_PTR: *const Cell<u32> = cast_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)); |