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
This commit is contained in:
llogiq 2025-05-16 15:05:36 +00:00 committed by GitHub
commit 94cfebb397
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 1715 additions and 1880 deletions

View file

@ -0,0 +1,221 @@
//@aux-build:interior_mutable_const.rs
#![deny(clippy::borrow_interior_mutable_const)]
#![allow(
clippy::declare_interior_mutable_const,
clippy::out_of_bounds_indexing,
const_item_mutation,
unconditional_panic
)]
use core::cell::{Cell, UnsafeCell};
use core::ops::{Deref, Index};
trait ConstDefault {
const DEFAULT: Self;
}
impl ConstDefault for u32 {
const DEFAULT: Self = 0;
}
impl<T: ConstDefault> ConstDefault for Cell<T> {
const DEFAULT: Self = Cell::new(T::DEFAULT);
}
fn main() {
{
const C: String = String::new();
let _ = C;
let _ = &C;
let _ = C.len();
let _ = &*C;
}
{
const C: UnsafeCell<u32> = UnsafeCell::new(0);
let _ = C;
let _ = &C; //~ borrow_interior_mutable_const
let _ = C.into_inner();
let _ = C.get(); //~ borrow_interior_mutable_const
}
{
const C: Cell<u32> = Cell::new(0);
let _ = C;
let _ = &C; //~ borrow_interior_mutable_const
let _ = &mut C; //~ borrow_interior_mutable_const
let _ = C.into_inner();
let local = C;
C.swap(&local) //~ borrow_interior_mutable_const
}
{
const C: [(Cell<u32>,); 1] = [(Cell::new(0),)];
let _ = C;
let _ = &C; //~ borrow_interior_mutable_const
let _ = &C[0]; //~ borrow_interior_mutable_const
let _ = &C[0].0; //~ borrow_interior_mutable_const
C[0].0.set(1); //~ borrow_interior_mutable_const
}
{
struct S(Cell<u32>);
impl S {
const C: Self = Self(Cell::new(0));
}
impl Deref for S {
type Target = Cell<u32>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
let _ = S::C;
let _ = S::C.0;
let _ = &S::C; //~ borrow_interior_mutable_const
let _ = &S::C.0; //~ borrow_interior_mutable_const
S::C.set(1); //~ borrow_interior_mutable_const
let _ = &*S::C; //~ borrow_interior_mutable_const
(*S::C).set(1); //~ borrow_interior_mutable_const
}
{
enum E {
Cell(Cell<u32>),
Other,
}
const CELL: E = E::Cell(Cell::new(0));
const OTHER: E = E::Other;
let _ = CELL;
let _ = &CELL; //~ borrow_interior_mutable_const
let E::Cell(_) = CELL else {
return;
};
let _ = OTHER;
let _ = &OTHER;
let E::Cell(ref _x) = OTHER else {
return;
};
}
{
struct S<T> {
cell: (Cell<T>, u32),
other: Option<T>,
}
impl<T: ConstDefault + Copy> S<T> {
const C: Self = Self {
cell: (Cell::<T>::DEFAULT, 0),
other: Some(T::DEFAULT),
};
fn f() {
let _ = Self::C;
let _ = &Self::C; //~ borrow_interior_mutable_const
let _ = Self::C.other;
let _ = &Self::C.other;
let _ = &Self::C.cell; //~ borrow_interior_mutable_const
let _ = &Self::C.cell.0; //~ borrow_interior_mutable_const
Self::C.cell.0.set(T::DEFAULT); //~ borrow_interior_mutable_const
let _ = &Self::C.cell.1;
}
}
}
{
trait T {
const VALUE: Option<Cell<u32>> = Some(Cell::new(0));
}
impl T for u32 {}
impl T for i32 {
const VALUE: Option<Cell<u32>> = None;
}
let _ = &u32::VALUE; //~ borrow_interior_mutable_const
let _ = &i32::VALUE;
}
{
trait Trait<T: ConstDefault> {
type T<U: ConstDefault>: ConstDefault;
const VALUE: Option<Self::T<T>> = Some(Self::T::<T>::DEFAULT);
}
impl<T: ConstDefault> Trait<T> for u32 {
type T<U: ConstDefault> = Cell<U>;
}
impl<T: ConstDefault> Trait<T> for i32 {
type T<U: ConstDefault> = Cell<U>;
const VALUE: Option<Cell<T>> = None;
}
fn f<T: ConstDefault>() {
let _ = &<u32 as Trait<T>>::VALUE; //~ borrow_interior_mutable_const
let _ = &<i32 as Trait<T>>::VALUE;
}
}
{
trait Trait {
const UNFROZEN: Option<Cell<u32>> = Some(Cell::new(0));
const FROZEN: Option<Cell<u32>> = None;
const NON_FREEZE: u32 = 0;
}
fn f<T: Trait>() {
// None of these are guaranteed to be frozen, so don't lint.
let _ = &T::UNFROZEN;
let _ = &T::FROZEN;
let _ = &T::NON_FREEZE;
}
}
{
struct S([Option<Cell<u32>>; 2]);
impl Index<usize> for S {
type Output = Option<Cell<u32>>;
fn index(&self, idx: usize) -> &Self::Output {
&self.0[idx]
}
}
const C: S = S([Some(Cell::new(0)), None]);
let _ = &C; //~ borrow_interior_mutable_const
let _ = &C[0]; //~ borrow_interior_mutable_const
let _ = &C.0[0]; //~ borrow_interior_mutable_const
let _ = &C.0[1];
}
{
const C: [Option<Cell<u32>>; 2] = [None, None];
let _ = &C[0];
let _ = &C[1];
let _ = &C[2];
fn f(i: usize) {
let _ = &C[i];
}
}
{
const C: [Option<Cell<u32>>; 2] = [None, Some(Cell::new(0))];
let _ = &C[0];
let _ = &C[1]; //~ borrow_interior_mutable_const
let _ = &C[2];
fn f(i: usize) {
let _ = &C[i]; //~ borrow_interior_mutable_const
}
}
{
let _ = &interior_mutable_const::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ borrow_interior_mutable_const
let _ = &interior_mutable_const::WRAPPED_PRIVATE_FROZEN_VARIANT;
}
{
type Cell2<T> = Cell<T>;
type MyCell = Cell2<u32>;
struct S(Option<MyCell>);
trait T {
type Assoc;
}
struct S2<T>(T, T, u32);
impl T for S {
type Assoc = S2<Self>;
}
type Assoc<X> = <X as T>::Assoc;
impl S {
const VALUE: Assoc<Self> = S2(Self(None), Self(Some(Cell::new(0))), 0);
}
let _ = &S::VALUE; //~ borrow_interior_mutable_const
let _ = &S::VALUE.0;
let _ = &S::VALUE.1; //~ borrow_interior_mutable_const
let _ = &S::VALUE.2;
}
}

View file

@ -0,0 +1,247 @@
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:35:17
|
LL | let _ = &C;
| ^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
note: the lint level is defined here
--> tests/ui/borrow_interior_mutable_const.rs:3:9
|
LL | #![deny(clippy::borrow_interior_mutable_const)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:37:17
|
LL | let _ = C.get();
| ^
|
= note: there is a compiler inserted borrow here
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:42:17
|
LL | let _ = &C;
| ^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:43:17
|
LL | let _ = &mut C;
| ^^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:47:9
|
LL | C.swap(&local)
| ^
|
= note: there is a compiler inserted borrow here
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:52:17
|
LL | let _ = &C;
| ^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:53:17
|
LL | let _ = &C[0];
| ^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:54:17
|
LL | let _ = &C[0].0;
| ^^^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:55:9
|
LL | C[0].0.set(1);
| ^^^^^^
|
= note: there is a compiler inserted borrow here
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:70:17
|
LL | let _ = &S::C;
| ^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:71:17
|
LL | let _ = &S::C.0;
| ^^^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:72:9
|
LL | S::C.set(1);
| ^^^^
|
= note: there is a compiler inserted call to `Deref::deref` here
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:73:18
|
LL | let _ = &*S::C;
| ^^^^^
|
= note: this deref expression is a call to `Deref::deref`
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:74:9
|
LL | (*S::C).set(1);
| ^^^^^^^
|
= note: this deref expression is a call to `Deref::deref`
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:85:17
|
LL | let _ = &CELL;
| ^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:109:25
|
LL | let _ = &Self::C;
| ^^^^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:112:25
|
LL | let _ = &Self::C.cell;
| ^^^^^^^^^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:113:25
|
LL | let _ = &Self::C.cell.0;
| ^^^^^^^^^^^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:114:17
|
LL | Self::C.cell.0.set(T::DEFAULT);
| ^^^^^^^^^^^^^^
|
= note: there is a compiler inserted borrow here
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:128:17
|
LL | let _ = &u32::VALUE;
| ^^^^^^^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:145:21
|
LL | let _ = &<u32 as Trait<T>>::VALUE;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:172:17
|
LL | let _ = &C;
| ^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:173:18
|
LL | let _ = &C[0];
| ^^^^
|
= note: this index expression is a call to `Index::index`
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:174:17
|
LL | let _ = &C.0[0];
| ^^^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:190:17
|
LL | let _ = &C[1];
| ^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:194:21
|
LL | let _ = &C[i];
| ^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:198:17
|
LL | let _ = &interior_mutable_const::WRAPPED_PRIVATE_UNFROZEN_VARIANT;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:216:17
|
LL | let _ = &S::VALUE;
| ^^^^^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: borrow of a named constant with interior mutability
--> tests/ui/borrow_interior_mutable_const.rs:218:17
|
LL | let _ = &S::VALUE.1;
| ^^^^^^^^^^^
|
= help: this lint can be silenced by assigning the value to a local variable before borrowing
error: aborting due to 29 previous errors

View file

@ -1,101 +0,0 @@
//@aux-build:helper.rs
#![deny(clippy::borrow_interior_mutable_const)]
#![allow(clippy::declare_interior_mutable_const)]
// this file (mostly) replicates its `declare` counterpart. Please see it for more discussions.
extern crate helper;
use std::cell::Cell;
use std::sync::atomic::AtomicUsize;
enum OptionalCell {
Unfrozen(Cell<bool>),
Frozen,
}
const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true));
const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
fn borrow_optional_cell() {
let _ = &UNFROZEN_VARIANT; //~ ERROR: interior mutability
let _ = &FROZEN_VARIANT;
}
trait AssocConsts {
const TO_BE_UNFROZEN_VARIANT: OptionalCell;
const TO_BE_FROZEN_VARIANT: OptionalCell;
const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
const DEFAULTED_ON_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
fn function() {
// This is the "suboptimal behavior" mentioned in `is_value_unfrozen`
// caused by a similar reason to unfrozen types without any default values
// get linted even if it has frozen variants'.
let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR: interior mutability
// The lint ignores default values because an impl of this trait can set
// an unfrozen variant to `DEFAULTED_ON_FROZEN_VARIANT` and use the default impl for `function`.
let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR: interior mutability
}
}
impl AssocConsts for u64 {
const TO_BE_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
const TO_BE_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
fn function() {
let _ = &<Self as AssocConsts>::TO_BE_UNFROZEN_VARIANT; //~ ERROR: interior mutability
let _ = &<Self as AssocConsts>::TO_BE_FROZEN_VARIANT;
let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR: interior mutability
let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT;
}
}
trait AssocTypes {
type ToBeUnfrozen;
const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen>;
const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen>;
// there's no need to test here because it's the exactly same as `trait::AssocTypes`
fn function();
}
impl AssocTypes for u64 {
type ToBeUnfrozen = AtomicUsize;
const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4));
const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen> = None;
fn function() {
let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT; //~ ERROR: interior mutability
let _ = &<Self as AssocTypes>::TO_BE_FROZEN_VARIANT;
}
}
enum BothOfCellAndGeneric<T> {
Unfrozen(Cell<*const T>),
Generic(*const T),
Frozen(usize),
}
impl<T> BothOfCellAndGeneric<T> {
const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null()));
const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null());
const FROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Frozen(5);
fn function() {
let _ = &Self::UNFROZEN_VARIANT; //~ ERROR: interior mutability
let _ = &Self::GENERIC_VARIANT; //~ ERROR: interior mutability
let _ = &Self::FROZEN_VARIANT;
}
}
fn main() {
// constants defined in foreign crates
let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR: interior mutability
let _ = &helper::WRAPPED_PRIVATE_FROZEN_VARIANT;
}

View file

@ -1,79 +0,0 @@
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/enums.rs:22:14
|
LL | let _ = &UNFROZEN_VARIANT;
| ^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
note: the lint level is defined here
--> tests/ui/borrow_interior_mutable_const/enums.rs:3:9
|
LL | #![deny(clippy::borrow_interior_mutable_const)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/enums.rs:37:18
|
LL | let _ = &Self::TO_BE_FROZEN_VARIANT;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/enums.rs:41:18
|
LL | let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/enums.rs:50:18
|
LL | let _ = &<Self as AssocConsts>::TO_BE_UNFROZEN_VARIANT;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/enums.rs:52:18
|
LL | let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/enums.rs:74:18
|
LL | let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/enums.rs:91:18
|
LL | let _ = &Self::UNFROZEN_VARIANT;
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/enums.rs:92:18
|
LL | let _ = &Self::GENERIC_VARIANT;
| ^^^^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/enums.rs:99:14
|
LL | let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: aborting due to 9 previous errors

View file

@ -1,128 +0,0 @@
#![deny(clippy::borrow_interior_mutable_const)]
#![allow(clippy::declare_interior_mutable_const, clippy::needless_borrow)]
#![allow(const_item_mutation)]
use std::borrow::Cow;
use std::cell::{Cell, UnsafeCell};
use std::fmt::Display;
use std::sync::Once;
use std::sync::atomic::{AtomicUsize, Ordering};
const ATOMIC: AtomicUsize = AtomicUsize::new(5);
const CELL: Cell<usize> = Cell::new(6);
const ATOMIC_TUPLE: ([AtomicUsize; 1], Option<Box<AtomicUsize>>, u8) = ([ATOMIC], None, 7);
const INTEGER: u8 = 8;
const STRING: String = String::new();
const STR: &str = "012345";
const COW: Cow<str> = Cow::Borrowed("abcdef");
const NO_ANN: &dyn Display = &70;
static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING);
const ONCE_INIT: Once = Once::new();
// This is just a pointer that can be safely dereferenced,
// it's semantically the same as `&'static T`;
// but it isn't allowed to make a static reference from an arbitrary integer value at the moment.
// For more information, please see the issue #5918.
pub struct StaticRef<T> {
ptr: *const T,
}
impl<T> StaticRef<T> {
/// Create a new `StaticRef` from a raw pointer
///
/// ## Safety
///
/// Callers must pass in a reference to statically allocated memory which
/// does not overlap with other values.
pub const unsafe fn new(ptr: *const T) -> StaticRef<T> {
StaticRef { ptr }
}
}
impl<T> std::ops::Deref for StaticRef<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.ptr }
}
}
// ICE regression test
mod issue12979 {
use std::cell::UnsafeCell;
const ATOMIC_TUPLE: (Vec<UnsafeCell<u8>>, ()) = (Vec::new(), ());
fn main() {
let _x = &ATOMIC_TUPLE.0;
}
}
// use a tuple to make sure referencing a field behind a pointer isn't linted.
const CELL_REF: StaticRef<(UnsafeCell<u32>,)> = unsafe { StaticRef::new(std::ptr::null()) };
fn main() {
ATOMIC.store(1, Ordering::SeqCst);
//~^ borrow_interior_mutable_const
assert_eq!(ATOMIC.load(Ordering::SeqCst), 5);
//~^ borrow_interior_mutable_const
let _once = ONCE_INIT;
let _once_ref = &ONCE_INIT;
//~^ borrow_interior_mutable_const
let _once_ref_2 = &&ONCE_INIT;
//~^ borrow_interior_mutable_const
let _once_ref_4 = &&&&ONCE_INIT;
//~^ borrow_interior_mutable_const
let _once_mut = &mut ONCE_INIT;
//~^ borrow_interior_mutable_const
let _atomic_into_inner = ATOMIC.into_inner();
// these should be all fine.
let _twice = (ONCE_INIT, ONCE_INIT);
let _ref_twice = &(ONCE_INIT, ONCE_INIT);
let _ref_once = &(ONCE_INIT, ONCE_INIT).0;
let _array_twice = [ONCE_INIT, ONCE_INIT];
let _ref_array_twice = &[ONCE_INIT, ONCE_INIT];
let _ref_array_once = &[ONCE_INIT, ONCE_INIT][0];
// referencing projection is still bad.
let _ = &ATOMIC_TUPLE;
//~^ borrow_interior_mutable_const
let _ = &ATOMIC_TUPLE.0;
//~^ borrow_interior_mutable_const
let _ = &(&&&&ATOMIC_TUPLE).0;
//~^ borrow_interior_mutable_const
let _ = &ATOMIC_TUPLE.0[0];
//~^ borrow_interior_mutable_const
let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst);
//~^ borrow_interior_mutable_const
let _ = &ATOMIC_TUPLE.2;
let _ = (&&&&ATOMIC_TUPLE).0;
let _ = (&&&&ATOMIC_TUPLE).2;
let _ = ATOMIC_TUPLE.0;
let _ = ATOMIC_TUPLE.0[0];
//~^ borrow_interior_mutable_const
let _ = ATOMIC_TUPLE.1.into_iter();
let _ = ATOMIC_TUPLE.2;
let _ = &{ ATOMIC_TUPLE };
CELL.set(2);
//~^ borrow_interior_mutable_const
assert_eq!(CELL.get(), 6);
//~^ borrow_interior_mutable_const
assert_eq!(INTEGER, 8);
assert!(STRING.is_empty());
let a = ATOMIC;
a.store(4, Ordering::SeqCst);
assert_eq!(a.load(Ordering::SeqCst), 4);
STATIC_TUPLE.0.store(3, Ordering::SeqCst);
assert_eq!(STATIC_TUPLE.0.load(Ordering::SeqCst), 3);
assert!(STATIC_TUPLE.1.is_empty());
assert_eq!(NO_ANN.to_string(), "70"); // should never lint this.
let _ = &CELL_REF.0;
}

View file

@ -1,119 +0,0 @@
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:65:5
|
LL | ATOMIC.store(1, Ordering::SeqCst);
| ^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
note: the lint level is defined here
--> tests/ui/borrow_interior_mutable_const/others.rs:1:9
|
LL | #![deny(clippy::borrow_interior_mutable_const)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:67:16
|
LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5);
| ^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:71:22
|
LL | let _once_ref = &ONCE_INIT;
| ^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:73:25
|
LL | let _once_ref_2 = &&ONCE_INIT;
| ^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:75:27
|
LL | let _once_ref_4 = &&&&ONCE_INIT;
| ^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:77:26
|
LL | let _once_mut = &mut ONCE_INIT;
| ^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:89:14
|
LL | let _ = &ATOMIC_TUPLE;
| ^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:91:14
|
LL | let _ = &ATOMIC_TUPLE.0;
| ^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:93:19
|
LL | let _ = &(&&&&ATOMIC_TUPLE).0;
| ^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:95:14
|
LL | let _ = &ATOMIC_TUPLE.0[0];
| ^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:97:13
|
LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst);
| ^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:103:13
|
LL | let _ = ATOMIC_TUPLE.0[0];
| ^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:109:5
|
LL | CELL.set(2);
| ^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/others.rs:111:16
|
LL | assert_eq!(CELL.get(), 6);
| ^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: aborting due to 14 previous errors

View file

@ -1,42 +0,0 @@
#![deny(clippy::borrow_interior_mutable_const)]
#![deny(clippy::declare_interior_mutable_const)]
// Inspired by https://github.com/rust-lang/rust/pull/130543#issuecomment-2364828139
use std::cell::UnsafeCell;
trait Trait {
type Assoc;
}
type Assoc<T> = <T as Trait>::Assoc;
impl Trait for u8 {
type Assoc = UnsafeCell<u8>;
}
impl Trait for () {
type Assoc = ();
}
enum MaybeMutable {
Mutable(Assoc<u8>),
Immutable(Assoc<()>),
}
const CELL: Assoc<u8> = UnsafeCell::new(0); //~ ERROR: interior mutable
const UNIT: Assoc<()> = ();
const MUTABLE: MaybeMutable = MaybeMutable::Mutable(CELL); //~ ERROR: interior mutable
const IMMUTABLE: MaybeMutable = MaybeMutable::Immutable(UNIT);
fn print_ref<T>(t: &T) {
let p: *const T = t;
println!("{p:p}")
}
fn main() {
print_ref(&CELL); //~ ERROR: interior mutability
print_ref(&UNIT);
print_ref(&MUTABLE); //~ ERROR: interior mutability
print_ref(&IMMUTABLE);
}

View file

@ -1,44 +0,0 @@
error: a `const` item should not be interior mutable
--> tests/ui/borrow_interior_mutable_const/projections.rs:27:1
|
LL | const CELL: Assoc<u8> = UnsafeCell::new(0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
note: the lint level is defined here
--> tests/ui/borrow_interior_mutable_const/projections.rs:2:9
|
LL | #![deny(clippy::declare_interior_mutable_const)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/borrow_interior_mutable_const/projections.rs:29:1
|
LL | const MUTABLE: MaybeMutable = MaybeMutable::Mutable(CELL);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/projections.rs:38:16
|
LL | print_ref(&CELL);
| ^^^^
|
= help: assign this const to a local or static variable, and use the variable here
note: the lint level is defined here
--> tests/ui/borrow_interior_mutable_const/projections.rs:1:9
|
LL | #![deny(clippy::borrow_interior_mutable_const)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/projections.rs:40:16
|
LL | print_ref(&MUTABLE);
| ^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: aborting due to 4 previous errors

View file

@ -1,219 +0,0 @@
#![deny(clippy::borrow_interior_mutable_const)]
#![allow(clippy::declare_interior_mutable_const)]
// this file replicates its `declare` counterpart. Please see it for more discussions.
use std::borrow::Cow;
use std::cell::Cell;
use std::sync::atomic::{AtomicUsize, Ordering};
trait ConcreteTypes {
const ATOMIC: AtomicUsize;
const STRING: String;
fn function() {
let _ = &Self::ATOMIC;
//~^ borrow_interior_mutable_const
let _ = &Self::STRING;
}
}
impl ConcreteTypes for u64 {
const ATOMIC: AtomicUsize = AtomicUsize::new(9);
const STRING: String = String::new();
fn function() {
// Lint this again since implementers can choose not to borrow it.
let _ = &Self::ATOMIC;
//~^ borrow_interior_mutable_const
let _ = &Self::STRING;
}
}
// a helper trait used below
trait ConstDefault {
const DEFAULT: Self;
}
trait GenericTypes<T, U> {
const TO_REMAIN_GENERIC: T;
const TO_BE_CONCRETE: U;
fn function() {
let _ = &Self::TO_REMAIN_GENERIC;
}
}
impl<T: ConstDefault> GenericTypes<T, AtomicUsize> for Vec<T> {
const TO_REMAIN_GENERIC: T = T::DEFAULT;
const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11);
fn function() {
let _ = &Self::TO_REMAIN_GENERIC;
let _ = &Self::TO_BE_CONCRETE;
//~^ borrow_interior_mutable_const
}
}
// a helper type used below
pub struct Wrapper<T>(T);
trait AssocTypes {
type ToBeFrozen;
type ToBeUnfrozen;
type ToBeGenericParam;
const TO_BE_FROZEN: Self::ToBeFrozen;
const TO_BE_UNFROZEN: Self::ToBeUnfrozen;
const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen>;
const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam>;
fn function() {
let _ = &Self::TO_BE_FROZEN;
let _ = &Self::WRAPPED_TO_BE_UNFROZEN;
}
}
impl<T: ConstDefault> AssocTypes for Vec<T> {
type ToBeFrozen = u16;
type ToBeUnfrozen = AtomicUsize;
type ToBeGenericParam = T;
const TO_BE_FROZEN: Self::ToBeFrozen = 12;
const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13);
const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14));
const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam> = Wrapper(T::DEFAULT);
fn function() {
let _ = &Self::TO_BE_FROZEN;
let _ = &Self::TO_BE_UNFROZEN;
//~^ borrow_interior_mutable_const
let _ = &Self::WRAPPED_TO_BE_UNFROZEN;
//~^ borrow_interior_mutable_const
let _ = &Self::WRAPPED_TO_BE_GENERIC_PARAM;
}
}
// a helper trait used below
trait AssocTypesHelper {
type NotToBeBounded;
type ToBeBounded;
const NOT_TO_BE_BOUNDED: Self::NotToBeBounded;
}
trait AssocTypesFromGenericParam<T>
where
T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
{
const NOT_BOUNDED: T::NotToBeBounded;
const BOUNDED: T::ToBeBounded;
fn function() {
let _ = &Self::NOT_BOUNDED;
let _ = &Self::BOUNDED;
//~^ borrow_interior_mutable_const
}
}
impl<T> AssocTypesFromGenericParam<T> for Vec<T>
where
T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
{
const NOT_BOUNDED: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
const BOUNDED: T::ToBeBounded = AtomicUsize::new(15);
fn function() {
let _ = &Self::NOT_BOUNDED;
let _ = &Self::BOUNDED;
//~^ borrow_interior_mutable_const
}
}
trait SelfType: Sized {
const SELF: Self;
const WRAPPED_SELF: Option<Self>;
fn function() {
let _ = &Self::SELF;
let _ = &Self::WRAPPED_SELF;
}
}
impl SelfType for u64 {
const SELF: Self = 16;
const WRAPPED_SELF: Option<Self> = Some(20);
fn function() {
let _ = &Self::SELF;
let _ = &Self::WRAPPED_SELF;
}
}
impl SelfType for AtomicUsize {
const SELF: Self = AtomicUsize::new(17);
const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21));
fn function() {
let _ = &Self::SELF;
//~^ borrow_interior_mutable_const
let _ = &Self::WRAPPED_SELF;
//~^ borrow_interior_mutable_const
}
}
trait BothOfCellAndGeneric<T> {
const DIRECT: Cell<T>;
const INDIRECT: Cell<*const T>;
fn function() {
let _ = &Self::DIRECT;
//~^ borrow_interior_mutable_const
let _ = &Self::INDIRECT;
//~^ borrow_interior_mutable_const
}
}
impl<T: ConstDefault> BothOfCellAndGeneric<T> for Vec<T> {
const DIRECT: Cell<T> = Cell::new(T::DEFAULT);
const INDIRECT: Cell<*const T> = Cell::new(std::ptr::null());
fn function() {
let _ = &Self::DIRECT;
//~^ borrow_interior_mutable_const
let _ = &Self::INDIRECT;
//~^ borrow_interior_mutable_const
}
}
struct Local<T>(T);
impl<T> Local<T>
where
T: ConstDefault + AssocTypesHelper<ToBeBounded = AtomicUsize>,
{
const ATOMIC: AtomicUsize = AtomicUsize::new(18);
const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy");
const GENERIC_TYPE: T = T::DEFAULT;
const ASSOC_TYPE: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19);
fn function() {
let _ = &Self::ATOMIC;
//~^ borrow_interior_mutable_const
let _ = &Self::COW;
let _ = &Self::GENERIC_TYPE;
let _ = &Self::ASSOC_TYPE;
let _ = &Self::BOUNDED_ASSOC_TYPE;
//~^ borrow_interior_mutable_const
}
}
fn main() {
u64::ATOMIC.store(5, Ordering::SeqCst);
//~^ borrow_interior_mutable_const
assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9);
//~^ borrow_interior_mutable_const
}

View file

@ -1,143 +0,0 @@
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:15:18
|
LL | let _ = &Self::ATOMIC;
| ^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
note: the lint level is defined here
--> tests/ui/borrow_interior_mutable_const/traits.rs:1:9
|
LL | #![deny(clippy::borrow_interior_mutable_const)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:27:18
|
LL | let _ = &Self::ATOMIC;
| ^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:53:18
|
LL | let _ = &Self::TO_BE_CONCRETE;
| ^^^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:89:18
|
LL | let _ = &Self::TO_BE_UNFROZEN;
| ^^^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:91:18
|
LL | let _ = &Self::WRAPPED_TO_BE_UNFROZEN;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:114:18
|
LL | let _ = &Self::BOUNDED;
| ^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:128:18
|
LL | let _ = &Self::BOUNDED;
| ^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:158:18
|
LL | let _ = &Self::SELF;
| ^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:160:18
|
LL | let _ = &Self::WRAPPED_SELF;
| ^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:170:18
|
LL | let _ = &Self::DIRECT;
| ^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:172:18
|
LL | let _ = &Self::INDIRECT;
| ^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:182:18
|
LL | let _ = &Self::DIRECT;
| ^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:184:18
|
LL | let _ = &Self::INDIRECT;
| ^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:204:18
|
LL | let _ = &Self::ATOMIC;
| ^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:209:18
|
LL | let _ = &Self::BOUNDED_ASSOC_TYPE;
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:215:5
|
LL | u64::ATOMIC.store(5, Ordering::SeqCst);
| ^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
--> tests/ui/borrow_interior_mutable_const/traits.rs:217:16
|
LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9);
| ^^^^^^^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
error: aborting due to 17 previous errors

View file

@ -0,0 +1,2 @@
#[deny(clippy::declare_interior_mutable_const)] //~ empty_line_after_outer_attr
const FOO: u8 = 0;

View file

@ -0,0 +1,3 @@
#![deny(clippy::declare_interior_mutable_const)] //~ empty_line_after_outer_attr
const FOO: u8 = 0;

View file

@ -0,0 +1,3 @@
#[deny(clippy::declare_interior_mutable_const)] //~ empty_line_after_outer_attr
const FOO: u8 = 0;

View file

@ -0,0 +1,19 @@
error: empty line after outer attribute
--> tests/ui/crashes/ice-12979.rs:1:1
|
LL | / #[deny(clippy::declare_interior_mutable_const)]
LL | |
| |_^
LL | const FOO: u8 = 0;
| --------- the attribute applies to this constant item
|
= note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::empty_line_after_outer_attr)]`
= help: if the empty line is unintentional, remove it
help: if the attribute should apply to the crate use an inner attribute
|
LL | #![deny(clippy::declare_interior_mutable_const)]
| +
error: aborting due to 1 previous error

View file

@ -1,4 +0,0 @@
const UNINIT: core::mem::MaybeUninit<core::cell::Cell<&'static ()>> = core::mem::MaybeUninit::uninit();
//~^ declare_interior_mutable_const
fn main() {}

View file

@ -1,12 +0,0 @@
error: a `const` item should not be interior mutable
--> tests/ui/crashes/ice-9445.rs:1:1
|
LL | const UNINIT: core::mem::MaybeUninit<core::cell::Cell<&'static ()>> = core::mem::MaybeUninit::uninit();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
= note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]`
error: aborting due to 1 previous error

View file

@ -0,0 +1,200 @@
#![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));

View file

@ -0,0 +1,197 @@
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:12:7
|
LL | const UNSAFE_CELL: UnsafeCell<u32> = UnsafeCell::new(0);
| ^^^^^^^^^^^
|
= help: did you mean to make this a `thread_local!` item
note: the lint level is defined here
--> tests/ui/declare_interior_mutable_const.rs:1:9
|
LL | #![deny(clippy::declare_interior_mutable_const)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:13:7
|
LL | const REF_CELL: RefCell<u32> = RefCell::new(0);
| ^^^^^^^^
|
= help: did you mean to make this a `thread_local!` item
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:14:7
|
LL | const CELL: Cell<u32> = Cell::new(0);
| ^^^^
|
= help: did you mean to make this a `thread_local!` item
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:28:7
|
LL | const CELL_TUPLE: (bool, Cell<u32>) = (true, Cell::new(0));
| ^^^^^^^^^^
|
= help: did you mean to make this a `thread_local!` item
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:29:7
|
LL | const CELL_ARRAY: [Cell<u32>; 2] = [Cell::new(0), Cell::new(0)];
| ^^^^^^^^^^
|
= help: did you mean to make this a `thread_local!` item
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:38:7
|
LL | const CELL_STRUCT: CellStruct = CellStruct {
| ^^^^^^^^^^^
|
= help: did you mean to make this a `thread_local!` item
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:46:7
|
LL | const CELL_ENUM: CellEnum = CellEnum::Cell(Cell::new(0));
| ^^^^^^^^^
|
= help: did you mean to make this a `thread_local!` item
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:49:7
|
LL | const SOME_CELL: Option<Cell<u32>> = Some(Cell::new(0));
| ^^^^^^^^^
|
= help: did you mean to make this a `thread_local!` item
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:53:7
|
LL | const SOME_NESTED_CELL: NestedCell = NestedCell([(Some(Cell::new(0)),)]);
| ^^^^^^^^^^^^^^^^
|
= help: did you mean to make this a `thread_local!` item
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:60:7
|
LL | const UNION_CELL: UnionCell = UnionCell {
| ^^^^^^^^^^
|
= help: did you mean to make this a `thread_local!` item
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:64:7
|
LL | const UNION_U32: UnionCell = UnionCell { x: 0 };
| ^^^^^^^^^
|
= help: did you mean to make this a `thread_local!` item
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:69:11
|
LL | const CELL: Cell<u32> = Cell::new(0);
| ^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:74:11
|
LL | const SELF: Self = Self(Cell::new(0));
| ^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:76:11
|
LL | const SOME_SELF: Option<Self> = Some(Self(Cell::new(0)));
| ^^^^^^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:92:11
|
LL | const DEFAULT: Self = Some(Cell::new(T::DEFAULT));
| ^^^^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:100:11
|
LL | const DEFAULT: Self = Self::Cell(Cell::new(T::DEFAULT));
| ^^^^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:103:11
|
LL | const CELL: Self = Self::DEFAULT;
| ^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:104:11
|
LL | const CELL_BY_DEFAULT: Self = Self::Cell(Cell::DEFAULT);
| ^^^^^^^^^^^^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:116:11
|
LL | const GENERIC_CELL: Self = Self::GenericEnumCell(GenericEnumCell::<T>::CELL);
| ^^^^^^^^^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:118:11
|
LL | const ENUM_CELL: Self = Self::EnumCell(GenericEnumCell::<u32>::CELL);
| ^^^^^^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:123:11
|
LL | const CELL: Cell<Self>;
| ^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:127:11
|
LL | const SOME_CELL: Option<Cell<Self>> = Some(Cell::new(Self::DEFAULT));
| ^^^^^^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:136:11
|
LL | const CELL: Cell<Self::T>;
| ^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:140:11
|
LL | const SOME_CELL: Option<Cell<Self::T>> = Some(Cell::new(Self::DEFAULT));
| ^^^^^^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:160:11
|
LL | const VALUE: Self::T = Cell::new(0);
| ^^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:171:11
|
LL | const VALUE: <Self::T as WithAssoc>::T = Cell::new(0);
| ^^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:181:11
|
LL | const VALUE: Self::T<u32> = Cell::new(0);
| ^^^^^
error: named constant with interior mutability
--> tests/ui/declare_interior_mutable_const.rs:196:11
|
LL | const VALUE: Self::T<Cell<u32>> = Some(Cell::new(0));
| ^^^^^
error: aborting due to 28 previous errors

View file

@ -1,135 +0,0 @@
#![warn(clippy::declare_interior_mutable_const)]
use std::cell::Cell;
use std::sync::atomic::AtomicUsize;
enum OptionalCell {
Unfrozen(Cell<bool>),
Frozen,
}
// a constant with enums should be linted only when the used variant is unfrozen (#3962).
const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true));
//~^ declare_interior_mutable_const
const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
const fn unfrozen_variant() -> OptionalCell {
OptionalCell::Unfrozen(Cell::new(false))
}
const fn frozen_variant() -> OptionalCell {
OptionalCell::Frozen
}
const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant();
//~^ declare_interior_mutable_const
const FROZEN_VARIANT_FROM_FN: OptionalCell = frozen_variant();
enum NestedInnermost {
Unfrozen(AtomicUsize),
Frozen,
}
struct NestedInner {
inner: NestedInnermost,
}
enum NestedOuter {
NestedInner(NestedInner),
NotNested(usize),
}
struct NestedOutermost {
outer: NestedOuter,
}
// a constant with enums should be linted according to its value, no matter how structs involve.
const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost {
//~^ declare_interior_mutable_const
outer: NestedOuter::NestedInner(NestedInner {
inner: NestedInnermost::Unfrozen(AtomicUsize::new(2)),
}),
};
const NESTED_FROZEN_VARIANT: NestedOutermost = NestedOutermost {
outer: NestedOuter::NestedInner(NestedInner {
inner: NestedInnermost::Frozen,
}),
};
trait AssocConsts {
// When there's no default value, lint it only according to its type.
// Further details are on the corresponding code (`NonCopyConst::check_trait_item`).
const TO_BE_UNFROZEN_VARIANT: OptionalCell;
//~^ declare_interior_mutable_const
const TO_BE_FROZEN_VARIANT: OptionalCell;
//~^ declare_interior_mutable_const
// Lint default values accordingly.
const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
//~^ declare_interior_mutable_const
const DEFAULTED_ON_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
}
// The lint doesn't trigger for an assoc constant in a trait impl with an unfrozen type even if it
// has enums. Further details are on the corresponding code in 'NonCopyConst::check_impl_item'.
impl AssocConsts for u64 {
const TO_BE_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
const TO_BE_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
// even if this sets an unfrozen variant, the lint ignores it.
const DEFAULTED_ON_FROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
}
// At first, I thought I'd need to check every patterns in `trait.rs`; but, what matters
// here are values; and I think substituted generics at definitions won't appear in MIR.
trait AssocTypes {
type ToBeUnfrozen;
const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen>;
const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen>;
}
impl AssocTypes for u64 {
type ToBeUnfrozen = AtomicUsize;
const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4));
//~^ declare_interior_mutable_const
const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen> = None;
}
// Use raw pointers since direct generics have a false negative at the type level.
enum BothOfCellAndGeneric<T> {
Unfrozen(Cell<*const T>),
Generic(*const T),
Frozen(usize),
}
impl<T> BothOfCellAndGeneric<T> {
const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null()));
//~^ declare_interior_mutable_const
// This is a false positive. The argument about this is on `is_value_unfrozen_raw`
const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null());
//~^ declare_interior_mutable_const
const FROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Frozen(5);
// This is what is likely to be a false negative when one tries to fix
// the `GENERIC_VARIANT` false positive.
const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null());
//~^ declare_interior_mutable_const
}
// associated types here is basically the same as the one above.
trait BothOfCellAndGenericWithAssocType {
type AssocType;
const UNFROZEN_VARIANT: BothOfCellAndGeneric<Self::AssocType> =
//~^ declare_interior_mutable_const
BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null()));
const GENERIC_VARIANT: BothOfCellAndGeneric<Self::AssocType> = BothOfCellAndGeneric::Generic(std::ptr::null());
//~^ declare_interior_mutable_const
const FROZEN_VARIANT: BothOfCellAndGeneric<Self::AssocType> = BothOfCellAndGeneric::Frozen(5);
}
fn main() {}

View file

@ -1,89 +0,0 @@
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/enums.rs:12:1
|
LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
= note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]`
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/enums.rs:24:1
|
LL | const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/enums.rs:47:1
|
LL | / const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost {
LL | |
LL | | outer: NestedOuter::NestedInner(NestedInner {
LL | | inner: NestedInnermost::Unfrozen(AtomicUsize::new(2)),
LL | | }),
LL | | };
| |__^
|
= help: consider making this a static item
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/enums.rs:62:5
|
LL | const TO_BE_UNFROZEN_VARIANT: OptionalCell;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/enums.rs:64:5
|
LL | const TO_BE_FROZEN_VARIANT: OptionalCell;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/enums.rs:68:5
|
LL | const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/enums.rs:95:5
|
LL | const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/enums.rs:108:5
|
LL | const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/enums.rs:112:5
|
LL | const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/enums.rs:119:5
|
LL | const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/enums.rs:127:5
|
LL | / const UNFROZEN_VARIANT: BothOfCellAndGeneric<Self::AssocType> =
LL | |
LL | | BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null()));
| |____________________________________________________________________^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/enums.rs:130:5
|
LL | const GENERIC_VARIANT: BothOfCellAndGeneric<Self::AssocType> = BothOfCellAndGeneric::Generic(std::ptr::null());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 12 previous errors

View file

@ -1,76 +0,0 @@
#![warn(clippy::declare_interior_mutable_const)]
use std::borrow::Cow;
use std::cell::Cell;
use std::fmt::Display;
use std::ptr;
use std::sync::Once;
use std::sync::atomic::AtomicUsize;
const ATOMIC: AtomicUsize = AtomicUsize::new(5);
//~^ declare_interior_mutable_const
const CELL: Cell<usize> = Cell::new(6);
//~^ declare_interior_mutable_const
const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
//~^ declare_interior_mutable_const
macro_rules! declare_const {
($name:ident: $ty:ty = $e:expr) => {
const $name: $ty = $e;
//~^ declare_interior_mutable_const
};
}
declare_const!(_ONCE: Once = Once::new());
// const ATOMIC_REF: &AtomicUsize = &AtomicUsize::new(7); // This will simply trigger E0492.
const INTEGER: u8 = 8;
const STRING: String = String::new();
const STR: &str = "012345";
const COW: Cow<str> = Cow::Borrowed("abcdef");
// note: a const item of Cow is used in the `postgres` package.
const NO_ANN: &dyn Display = &70;
static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING);
// there should be no lints on the line above line
mod issue_8493 {
use std::cell::Cell;
thread_local! {
static _BAR: Cell<i32> = const { Cell::new(0) };
}
macro_rules! issue_8493 {
() => {
const _BAZ: Cell<usize> = Cell::new(0);
//~^ declare_interior_mutable_const
static _FOOBAR: () = {
thread_local! {
static _VAR: Cell<i32> = const { Cell::new(0) };
}
};
};
}
issue_8493!();
}
#[repr(C, align(8))]
struct NoAtomic(usize);
#[repr(C, align(8))]
struct WithAtomic(AtomicUsize);
const fn with_non_null() -> *const WithAtomic {
const NO_ATOMIC: NoAtomic = NoAtomic(0);
(&NO_ATOMIC as *const NoAtomic).cast()
}
const WITH_ATOMIC: *const WithAtomic = with_non_null();
struct Generic<T>(T);
impl<T> Generic<T> {
const RAW_POINTER: *const Cell<T> = ptr::null();
}
fn main() {}

View file

@ -1,50 +0,0 @@
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/others.rs:10:1
|
LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider making this a static item
= note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]`
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/others.rs:12:1
|
LL | const CELL: Cell<usize> = Cell::new(6);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/others.rs:14:1
|
LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider making this a static item
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/others.rs:19:9
|
LL | const $name: $ty = $e;
| ^^^^^^^^^^^^^^^^^^^^^^
...
LL | declare_const!(_ONCE: Once = Once::new());
| ----------------------------------------- in this macro invocation
|
= note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info)
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/others.rs:47:13
|
LL | const _BAZ: Cell<usize> = Cell::new(0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | issue_8493!();
| ------------- in this macro invocation
|
= note: this error originates in the macro `issue_8493` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 5 previous errors

View file

@ -1,162 +0,0 @@
#![warn(clippy::declare_interior_mutable_const)]
use std::borrow::Cow;
use std::cell::Cell;
use std::sync::atomic::AtomicUsize;
macro_rules! declare_const {
($name:ident: $ty:ty = $e:expr) => {
const $name: $ty = $e;
//~^ declare_interior_mutable_const
};
}
// a constant whose type is a concrete type should be linted at the definition site.
trait ConcreteTypes {
const ATOMIC: AtomicUsize;
//~^ declare_interior_mutable_const
const INTEGER: u64;
const STRING: String;
declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC);
}
impl ConcreteTypes for u64 {
const ATOMIC: AtomicUsize = AtomicUsize::new(9);
const INTEGER: u64 = 10;
const STRING: String = String::new();
}
// a helper trait used below
trait ConstDefault {
const DEFAULT: Self;
}
// a constant whose type is a generic type should be linted at the implementation site.
trait GenericTypes<T, U> {
const TO_REMAIN_GENERIC: T;
const TO_BE_CONCRETE: U;
const HAVING_DEFAULT: T = Self::TO_REMAIN_GENERIC;
declare_const!(IN_MACRO: T = Self::TO_REMAIN_GENERIC);
}
impl<T: ConstDefault> GenericTypes<T, AtomicUsize> for u64 {
const TO_REMAIN_GENERIC: T = T::DEFAULT;
const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11);
//~^ declare_interior_mutable_const
}
// a helper type used below
struct Wrapper<T>(T);
// a constant whose type is an associated type should be linted at the implementation site, too.
trait AssocTypes {
type ToBeFrozen;
type ToBeUnfrozen;
type ToBeGenericParam;
const TO_BE_FROZEN: Self::ToBeFrozen;
const TO_BE_UNFROZEN: Self::ToBeUnfrozen;
const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen>;
// to ensure it can handle things when a generic type remains after normalization.
const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam>;
}
impl<T: ConstDefault> AssocTypes for Vec<T> {
type ToBeFrozen = u16;
type ToBeUnfrozen = AtomicUsize;
type ToBeGenericParam = T;
const TO_BE_FROZEN: Self::ToBeFrozen = 12;
const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13);
//~^ declare_interior_mutable_const
const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14));
//~^ declare_interior_mutable_const
const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam> = Wrapper(T::DEFAULT);
}
// a helper trait used below
trait AssocTypesHelper {
type NotToBeBounded;
type ToBeBounded;
const NOT_TO_BE_BOUNDED: Self::NotToBeBounded;
}
// a constant whose type is an assoc type originated from a generic param bounded at the definition
// site should be linted at there.
trait AssocTypesFromGenericParam<T>
where
T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
{
const NOT_BOUNDED: T::NotToBeBounded;
const BOUNDED: T::ToBeBounded;
//~^ declare_interior_mutable_const
}
impl<T> AssocTypesFromGenericParam<T> for u64
where
T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
{
// an associated type could remain unknown in a trait impl.
const NOT_BOUNDED: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
const BOUNDED: T::ToBeBounded = AtomicUsize::new(15);
}
// a constant whose type is `Self` should be linted at the implementation site as well.
// (`Option` requires `Sized` bound.)
trait SelfType: Sized {
const SELF: Self;
// this was the one in the original issue (#5050).
const WRAPPED_SELF: Option<Self>;
}
impl SelfType for u64 {
const SELF: Self = 16;
const WRAPPED_SELF: Option<Self> = Some(20);
}
impl SelfType for AtomicUsize {
// this (interior mutable `Self` const) exists in `parking_lot`.
// `const_trait_impl` will replace it in the future, hopefully.
const SELF: Self = AtomicUsize::new(17);
//~^ declare_interior_mutable_const
const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21));
//~^ declare_interior_mutable_const
}
// Even though a constant contains a generic type, if it also have an interior mutable type,
// it should be linted at the definition site.
trait BothOfCellAndGeneric<T> {
const DIRECT: Cell<T>;
//~^ declare_interior_mutable_const
const INDIRECT: Cell<*const T>;
//~^ declare_interior_mutable_const
}
impl<T: ConstDefault> BothOfCellAndGeneric<T> for u64 {
const DIRECT: Cell<T> = Cell::new(T::DEFAULT);
//~^ declare_interior_mutable_const
const INDIRECT: Cell<*const T> = Cell::new(std::ptr::null());
}
struct Local<T>(T);
// a constant in an inherent impl are essentially the same as a normal const item
// except there can be a generic or associated type.
impl<T> Local<T>
where
T: ConstDefault + AssocTypesHelper<ToBeBounded = AtomicUsize>,
{
const ATOMIC: AtomicUsize = AtomicUsize::new(18);
//~^ declare_interior_mutable_const
const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy");
const GENERIC_TYPE: T = T::DEFAULT;
const ASSOC_TYPE: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19);
//~^ declare_interior_mutable_const
}
fn main() {}

View file

@ -1,88 +0,0 @@
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:16:5
|
LL | const ATOMIC: AtomicUsize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]`
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:9:9
|
LL | const $name: $ty = $e;
| ^^^^^^^^^^^^^^^^^^^^^^
...
LL | declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC);
| ---------------------------------------------------------- in this macro invocation
|
= note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info)
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:45:5
|
LL | const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:71:5
|
LL | const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:73:5
|
LL | const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:93:5
|
LL | const BOUNDED: T::ToBeBounded;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:122:5
|
LL | const SELF: Self = AtomicUsize::new(17);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:124:5
|
LL | const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:131:5
|
LL | const DIRECT: Cell<T>;
| ^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:133:5
|
LL | const INDIRECT: Cell<*const T>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:138:5
|
LL | const DIRECT: Cell<T> = Cell::new(T::DEFAULT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:151:5
|
LL | const ATOMIC: AtomicUsize = AtomicUsize::new(18);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: a `const` item should not be interior mutable
--> tests/ui/declare_interior_mutable_const/traits.rs:158:5
|
LL | const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 13 previous errors