Skip to content

Commit 94cfebb

Browse files
authored
Rewrite non_copy_const (#13207)
fixes #12979 fixes #12951 fixes #13233 Tests still need to be finished and the docs still need to be updated, but this should otherwise ready. changelog: Lint `declare_interior_mutable_const` and `borrow_interior_mutable_const` more precisely
2 parents 5cb7e40 + 318ba60 commit 94cfebb

27 files changed

+1691
-1856
lines changed

clippy_lints/src/non_copy_const.rs

+788-365
Large diffs are not rendered by default.

clippy_utils/src/ty/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1361,3 +1361,14 @@ pub fn is_slice_like<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
13611361
|| ty.is_array()
13621362
|| matches!(ty.kind(), ty::Adt(adt_def, _) if cx.tcx.is_diagnostic_item(sym::Vec, adt_def.did()))
13631363
}
1364+
1365+
/// Gets the index of a field by name.
1366+
pub fn get_field_idx_by_name(ty: Ty<'_>, name: Symbol) -> Option<usize> {
1367+
match *ty.kind() {
1368+
ty::Adt(def, _) if def.is_union() || def.is_struct() => {
1369+
def.non_enum_variant().fields.iter().position(|f| f.name == name)
1370+
},
1371+
ty::Tuple(_) => name.as_str().parse::<usize>().ok(),
1372+
_ => None,
1373+
}
1374+
}
+221
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
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

Comments
 (0)