102 lines
3.5 KiB
Rust
102 lines
3.5 KiB
Rust
|
// aux-build:helper.rs
|
||
|
|
||
|
#![warn(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 mutable
|
||
|
|
||
|
// 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 mutable
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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 mutable
|
||
|
let _ = &<Self as AssocConsts>::TO_BE_FROZEN_VARIANT;
|
||
|
let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mutable
|
||
|
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)); //~ ERROR interior mutable
|
||
|
const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen> = None;
|
||
|
|
||
|
fn function() {
|
||
|
let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
|
||
|
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())); //~ ERROR interior mutable
|
||
|
const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable
|
||
|
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;
|
||
|
}
|