| 
 | 1 | +//@aux-build:interior_mutable_const.rs  | 
 | 2 | + | 
 | 3 | +#![deny(clippy::borrow_interior_mutable_const)]  | 
 | 4 | +#![allow(  | 
 | 5 | +    clippy::declare_interior_mutable_const,  | 
 | 6 | +    clippy::out_of_bounds_indexing,  | 
 | 7 | +    const_item_mutation,  | 
 | 8 | +    unconditional_panic  | 
 | 9 | +)]  | 
 | 10 | + | 
 | 11 | +use core::cell::{Cell, UnsafeCell};  | 
 | 12 | +use core::ops::{Deref, Index};  | 
 | 13 | + | 
 | 14 | +trait ConstDefault {  | 
 | 15 | +    const DEFAULT: Self;  | 
 | 16 | +}  | 
 | 17 | +impl ConstDefault for u32 {  | 
 | 18 | +    const DEFAULT: Self = 0;  | 
 | 19 | +}  | 
 | 20 | +impl<T: ConstDefault> ConstDefault for Cell<T> {  | 
 | 21 | +    const DEFAULT: Self = Cell::new(T::DEFAULT);  | 
 | 22 | +}  | 
 | 23 | + | 
 | 24 | +fn main() {  | 
 | 25 | +    {  | 
 | 26 | +        const C: String = String::new();  | 
 | 27 | +        let _ = C;  | 
 | 28 | +        let _ = &C;  | 
 | 29 | +        let _ = C.len();  | 
 | 30 | +        let _ = &*C;  | 
 | 31 | +    }  | 
 | 32 | +    {  | 
 | 33 | +        const C: UnsafeCell<u32> = UnsafeCell::new(0);  | 
 | 34 | +        let _ = C;  | 
 | 35 | +        let _ = &C; //~ borrow_interior_mutable_const  | 
 | 36 | +        let _ = C.into_inner();  | 
 | 37 | +        let _ = C.get(); //~ borrow_interior_mutable_const  | 
 | 38 | +    }  | 
 | 39 | +    {  | 
 | 40 | +        const C: Cell<u32> = Cell::new(0);  | 
 | 41 | +        let _ = C;  | 
 | 42 | +        let _ = &C; //~ borrow_interior_mutable_const  | 
 | 43 | +        let _ = &mut C; //~ borrow_interior_mutable_const  | 
 | 44 | +        let _ = C.into_inner();  | 
 | 45 | + | 
 | 46 | +        let local = C;  | 
 | 47 | +        C.swap(&local) //~ borrow_interior_mutable_const  | 
 | 48 | +    }  | 
 | 49 | +    {  | 
 | 50 | +        const C: [(Cell<u32>,); 1] = [(Cell::new(0),)];  | 
 | 51 | +        let _ = C;  | 
 | 52 | +        let _ = &C; //~ borrow_interior_mutable_const  | 
 | 53 | +        let _ = &C[0]; //~ borrow_interior_mutable_const  | 
 | 54 | +        let _ = &C[0].0; //~ borrow_interior_mutable_const  | 
 | 55 | +        C[0].0.set(1); //~ borrow_interior_mutable_const  | 
 | 56 | +    }  | 
 | 57 | +    {  | 
 | 58 | +        struct S(Cell<u32>);  | 
 | 59 | +        impl S {  | 
 | 60 | +            const C: Self = Self(Cell::new(0));  | 
 | 61 | +        }  | 
 | 62 | +        impl Deref for S {  | 
 | 63 | +            type Target = Cell<u32>;  | 
 | 64 | +            fn deref(&self) -> &Self::Target {  | 
 | 65 | +                &self.0  | 
 | 66 | +            }  | 
 | 67 | +        }  | 
 | 68 | +        let _ = S::C;  | 
 | 69 | +        let _ = S::C.0;  | 
 | 70 | +        let _ = &S::C; //~ borrow_interior_mutable_const  | 
 | 71 | +        let _ = &S::C.0; //~ borrow_interior_mutable_const  | 
 | 72 | +        S::C.set(1); //~ borrow_interior_mutable_const  | 
 | 73 | +        let _ = &*S::C; //~ borrow_interior_mutable_const  | 
 | 74 | +        (*S::C).set(1); //~ borrow_interior_mutable_const  | 
 | 75 | +    }  | 
 | 76 | +    {  | 
 | 77 | +        enum E {  | 
 | 78 | +            Cell(Cell<u32>),  | 
 | 79 | +            Other,  | 
 | 80 | +        }  | 
 | 81 | +        const CELL: E = E::Cell(Cell::new(0));  | 
 | 82 | +        const OTHER: E = E::Other;  | 
 | 83 | + | 
 | 84 | +        let _ = CELL;  | 
 | 85 | +        let _ = &CELL; //~ borrow_interior_mutable_const  | 
 | 86 | +        let E::Cell(_) = CELL else {  | 
 | 87 | +            return;  | 
 | 88 | +        };  | 
 | 89 | + | 
 | 90 | +        let _ = OTHER;  | 
 | 91 | +        let _ = &OTHER;  | 
 | 92 | +        let E::Cell(ref _x) = OTHER else {  | 
 | 93 | +            return;  | 
 | 94 | +        };  | 
 | 95 | +    }  | 
 | 96 | +    {  | 
 | 97 | +        struct S<T> {  | 
 | 98 | +            cell: (Cell<T>, u32),  | 
 | 99 | +            other: Option<T>,  | 
 | 100 | +        }  | 
 | 101 | +        impl<T: ConstDefault + Copy> S<T> {  | 
 | 102 | +            const C: Self = Self {  | 
 | 103 | +                cell: (Cell::<T>::DEFAULT, 0),  | 
 | 104 | +                other: Some(T::DEFAULT),  | 
 | 105 | +            };  | 
 | 106 | + | 
 | 107 | +            fn f() {  | 
 | 108 | +                let _ = Self::C;  | 
 | 109 | +                let _ = &Self::C; //~ borrow_interior_mutable_const  | 
 | 110 | +                let _ = Self::C.other;  | 
 | 111 | +                let _ = &Self::C.other;  | 
 | 112 | +                let _ = &Self::C.cell; //~ borrow_interior_mutable_const  | 
 | 113 | +                let _ = &Self::C.cell.0; //~ borrow_interior_mutable_const  | 
 | 114 | +                Self::C.cell.0.set(T::DEFAULT); //~ borrow_interior_mutable_const  | 
 | 115 | +                let _ = &Self::C.cell.1;  | 
 | 116 | +            }  | 
 | 117 | +        }  | 
 | 118 | +    }  | 
 | 119 | +    {  | 
 | 120 | +        trait T {  | 
 | 121 | +            const VALUE: Option<Cell<u32>> = Some(Cell::new(0));  | 
 | 122 | +        }  | 
 | 123 | +        impl T for u32 {}  | 
 | 124 | +        impl T for i32 {  | 
 | 125 | +            const VALUE: Option<Cell<u32>> = None;  | 
 | 126 | +        }  | 
 | 127 | + | 
 | 128 | +        let _ = &u32::VALUE; //~ borrow_interior_mutable_const  | 
 | 129 | +        let _ = &i32::VALUE;  | 
 | 130 | +    }  | 
 | 131 | +    {  | 
 | 132 | +        trait Trait<T: ConstDefault> {  | 
 | 133 | +            type T<U: ConstDefault>: ConstDefault;  | 
 | 134 | +            const VALUE: Option<Self::T<T>> = Some(Self::T::<T>::DEFAULT);  | 
 | 135 | +        }  | 
 | 136 | +        impl<T: ConstDefault> Trait<T> for u32 {  | 
 | 137 | +            type T<U: ConstDefault> = Cell<U>;  | 
 | 138 | +        }  | 
 | 139 | +        impl<T: ConstDefault> Trait<T> for i32 {  | 
 | 140 | +            type T<U: ConstDefault> = Cell<U>;  | 
 | 141 | +            const VALUE: Option<Cell<T>> = None;  | 
 | 142 | +        }  | 
 | 143 | + | 
 | 144 | +        fn f<T: ConstDefault>() {  | 
 | 145 | +            let _ = &<u32 as Trait<T>>::VALUE; //~ borrow_interior_mutable_const  | 
 | 146 | +            let _ = &<i32 as Trait<T>>::VALUE;  | 
 | 147 | +        }  | 
 | 148 | +    }  | 
 | 149 | +    {  | 
 | 150 | +        trait Trait {  | 
 | 151 | +            const UNFROZEN: Option<Cell<u32>> = Some(Cell::new(0));  | 
 | 152 | +            const FROZEN: Option<Cell<u32>> = None;  | 
 | 153 | +            const NON_FREEZE: u32 = 0;  | 
 | 154 | +        }  | 
 | 155 | +        fn f<T: Trait>() {  | 
 | 156 | +            // None of these are guaranteed to be frozen, so don't lint.  | 
 | 157 | +            let _ = &T::UNFROZEN;  | 
 | 158 | +            let _ = &T::FROZEN;  | 
 | 159 | +            let _ = &T::NON_FREEZE;  | 
 | 160 | +        }  | 
 | 161 | +    }  | 
 | 162 | +    {  | 
 | 163 | +        struct S([Option<Cell<u32>>; 2]);  | 
 | 164 | +        impl Index<usize> for S {  | 
 | 165 | +            type Output = Option<Cell<u32>>;  | 
 | 166 | +            fn index(&self, idx: usize) -> &Self::Output {  | 
 | 167 | +                &self.0[idx]  | 
 | 168 | +            }  | 
 | 169 | +        }  | 
 | 170 | + | 
 | 171 | +        const C: S = S([Some(Cell::new(0)), None]);  | 
 | 172 | +        let _ = &C; //~ borrow_interior_mutable_const  | 
 | 173 | +        let _ = &C[0]; //~ borrow_interior_mutable_const  | 
 | 174 | +        let _ = &C.0[0]; //~ borrow_interior_mutable_const  | 
 | 175 | +        let _ = &C.0[1];  | 
 | 176 | +    }  | 
 | 177 | +    {  | 
 | 178 | +        const C: [Option<Cell<u32>>; 2] = [None, None];  | 
 | 179 | +        let _ = &C[0];  | 
 | 180 | +        let _ = &C[1];  | 
 | 181 | +        let _ = &C[2];  | 
 | 182 | + | 
 | 183 | +        fn f(i: usize) {  | 
 | 184 | +            let _ = &C[i];  | 
 | 185 | +        }  | 
 | 186 | +    }  | 
 | 187 | +    {  | 
 | 188 | +        const C: [Option<Cell<u32>>; 2] = [None, Some(Cell::new(0))];  | 
 | 189 | +        let _ = &C[0];  | 
 | 190 | +        let _ = &C[1]; //~ borrow_interior_mutable_const  | 
 | 191 | +        let _ = &C[2];  | 
 | 192 | + | 
 | 193 | +        fn f(i: usize) {  | 
 | 194 | +            let _ = &C[i]; //~ borrow_interior_mutable_const  | 
 | 195 | +        }  | 
 | 196 | +    }  | 
 | 197 | +    {  | 
 | 198 | +        let _ = &interior_mutable_const::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ borrow_interior_mutable_const  | 
 | 199 | +        let _ = &interior_mutable_const::WRAPPED_PRIVATE_FROZEN_VARIANT;  | 
 | 200 | +    }  | 
 | 201 | +    {  | 
 | 202 | +        type Cell2<T> = Cell<T>;  | 
 | 203 | +        type MyCell = Cell2<u32>;  | 
 | 204 | +        struct S(Option<MyCell>);  | 
 | 205 | +        trait T {  | 
 | 206 | +            type Assoc;  | 
 | 207 | +        }  | 
 | 208 | +        struct S2<T>(T, T, u32);  | 
 | 209 | +        impl T for S {  | 
 | 210 | +            type Assoc = S2<Self>;  | 
 | 211 | +        }  | 
 | 212 | +        type Assoc<X> = <X as T>::Assoc;  | 
 | 213 | +        impl S {  | 
 | 214 | +            const VALUE: Assoc<Self> = S2(Self(None), Self(Some(Cell::new(0))), 0);  | 
 | 215 | +        }  | 
 | 216 | +        let _ = &S::VALUE; //~ borrow_interior_mutable_const  | 
 | 217 | +        let _ = &S::VALUE.0;  | 
 | 218 | +        let _ = &S::VALUE.1; //~ borrow_interior_mutable_const  | 
 | 219 | +        let _ = &S::VALUE.2;  | 
 | 220 | +    }  | 
 | 221 | +}  | 
0 commit comments