forked from rust-lang/rust
-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of rust-lang#6110 - rail-rain:care_enums_non_copy_const, r…
…=llogiq "Respect" enums in `interior_mutable_const` fixes rust-lang#3962 fixes rust-lang#3825 Hello, It might not be a good idea to submit another relatively large PR while I have an opened PR; but, I've finished this anyway. This may be able to wait for months. Note: the code uses the MIR interpreter, which the author of rust-lang#3962 thought unlikely to be a solution. This might be over-engineering; but, I think it's important to be able to work with the 'http' crate (rust-lang#3825). (And, I don't want to write a MIR visitor) --- changelog: fix a false positive in two `interior_mutable_const` lints where a constant with enums gets linted even if it uses a clearly unfrozen variant
- Loading branch information
Showing
14 changed files
with
969 additions
and
179 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// this file solely exists to test constants defined in foreign crates. | ||
// As the most common case is the `http` crate, it replicates `http::HeadewrName`'s structure. | ||
|
||
#![allow(clippy::declare_interior_mutable_const)] | ||
|
||
use std::sync::atomic::AtomicUsize; | ||
|
||
enum Private<T> { | ||
ToBeUnfrozen(T), | ||
Frozen(usize), | ||
} | ||
|
||
pub struct Wrapper(Private<AtomicUsize>); | ||
|
||
pub const WRAPPED_PRIVATE_UNFROZEN_VARIANT: Wrapper = Wrapper(Private::ToBeUnfrozen(AtomicUsize::new(6))); | ||
pub const WRAPPED_PRIVATE_FROZEN_VARIANT: Wrapper = Wrapper(Private::Frozen(7)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// 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; | ||
} |
Oops, something went wrong.