Skip to content

Commit 2fc9064

Browse files
committed
rewrite the test and fix a minor fp
* rewrite the test for `declare_interior_mutable_const from scratch` * fix a minor false positive where `Cell<"const T>` gets linted twice
1 parent d655c0a commit 2fc9064

File tree

3 files changed

+166
-75
lines changed

3 files changed

+166
-75
lines changed

clippy_lints/src/non_copy_const.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, Node, Tr
99
use rustc_infer::traits::specialization_graph;
1010
use rustc_lint::{LateContext, LateLintPass, Lint};
1111
use rustc_middle::ty::adjustment::Adjust;
12-
use rustc_middle::ty::fold::TypeFoldable as _;
13-
use rustc_middle::ty::{AssocKind, Ty, TypeFlags};
12+
use rustc_middle::ty::{AssocKind, Ty};
1413
use rustc_session::{declare_lint_pass, declare_tool_lint};
1514
use rustc_span::{InnerSpan, Span, DUMMY_SP};
1615
use rustc_typeck::hir_ty_to_ty;
@@ -178,15 +177,18 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
178177
if let Some(of_trait_def_id) = of_trait_ref.trait_def_id();
179178
if let Some(of_assoc_item) = specialization_graph::Node::Trait(of_trait_def_id)
180179
.item(cx.tcx, impl_item.ident, AssocKind::Const, of_trait_def_id);
181-
if cx.tcx
182-
// Normalize assoc types because ones originated from generic params
183-
// bounded other traits could have their bound at the trait defs;
184-
// and, in that case, the definition is *not* generic.
185-
.normalize_erasing_regions(
186-
cx.tcx.param_env(of_trait_def_id),
187-
cx.tcx.type_of(of_assoc_item.def_id),
188-
)
189-
.has_type_flags(TypeFlags::HAS_PROJECTION | TypeFlags::HAS_TY_PARAM);
180+
if cx
181+
.tcx
182+
.layout_of(cx.tcx.param_env(of_trait_def_id).and(
183+
// Normalize assoc types because ones originated from generic params
184+
// bounded other traits could have their bound at the trait defs;
185+
// and, in that case, the definition is *not* generic.
186+
cx.tcx.normalize_erasing_regions(
187+
cx.tcx.param_env(of_trait_def_id),
188+
cx.tcx.type_of(of_assoc_item.def_id),
189+
),
190+
))
191+
.is_err();
190192
then {
191193
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
192194
let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);

tests/ui/declare_interior_mutable_const.rs

Lines changed: 115 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -34,64 +34,135 @@ static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING);
3434
#[allow(clippy::declare_interior_mutable_const)]
3535
const ONCE_INIT: Once = Once::new();
3636

37-
struct Wrapper<T>(T);
38-
39-
trait Trait<T: Trait2<AssocType5 = AtomicUsize>> {
40-
type AssocType;
41-
type AssocType2;
42-
type AssocType3;
43-
37+
// a constant whose type is a concrete type should be linted at the definition site.
38+
trait ConcreteTypes {
4439
const ATOMIC: AtomicUsize; //~ ERROR interior mutable
4540
const INTEGER: u64;
4641
const STRING: String;
47-
const SELF: Self;
48-
const INPUT: T;
49-
const INPUT_ASSOC: T::AssocType4;
50-
const INPUT_ASSOC_2: T::AssocType5; //~ ERROR interior mutable
51-
const ASSOC: Self::AssocType;
52-
const ASSOC_2: Self::AssocType2;
53-
const WRAPPED_ASSOC_2: Wrapper<Self::AssocType2>;
54-
const WRAPPED_ASSOC_3: Wrapper<Self::AssocType3>;
55-
56-
const AN_INPUT: T = Self::INPUT;
57-
declare_const!(ANOTHER_INPUT: T = Self::INPUT);
5842
declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR interior mutable
5943
}
6044

61-
trait Trait2 {
62-
type AssocType4;
63-
type AssocType5;
45+
impl ConcreteTypes for u64 {
46+
const ATOMIC: AtomicUsize = AtomicUsize::new(9);
47+
const INTEGER: u64 = 10;
48+
const STRING: String = String::new();
49+
}
6450

65-
const SELF_2: Self;
66-
const ASSOC_4: Self::AssocType4;
51+
// a helper trait used below
52+
trait ConstDefault {
53+
const DEFAULT: Self;
6754
}
6855

69-
impl<T: Trait2<AssocType5 = AtomicUsize>> Trait<T> for u64 {
70-
type AssocType = u16;
71-
type AssocType2 = AtomicUsize;
72-
type AssocType3 = T;
56+
// a constant whose type is a generic type should be linted at the implementation site.
57+
trait GenericTypes<T, U> {
58+
const TO_REMAIN_GENERIC: T;
59+
const TO_BE_CONCRETE: U;
7360

74-
const ATOMIC: AtomicUsize = AtomicUsize::new(9);
75-
const INTEGER: u64 = 10;
76-
const STRING: String = String::new();
77-
const SELF: Self = 11;
78-
const INPUT: T = T::SELF_2;
79-
const INPUT_ASSOC: T::AssocType4 = T::ASSOC_4;
80-
const INPUT_ASSOC_2: T::AssocType5 = AtomicUsize::new(16);
81-
const ASSOC: Self::AssocType = 13;
82-
const ASSOC_2: Self::AssocType2 = AtomicUsize::new(15); //~ ERROR interior mutable
83-
const WRAPPED_ASSOC_2: Wrapper<Self::AssocType2> = Wrapper(AtomicUsize::new(16)); //~ ERROR interior mutable
84-
const WRAPPED_ASSOC_3: Wrapper<Self::AssocType3> = Wrapper(T::SELF_2);
61+
const HAVING_DEFAULT: T = Self::TO_REMAIN_GENERIC;
62+
declare_const!(IN_MACRO: T = Self::TO_REMAIN_GENERIC);
63+
}
64+
65+
impl<T: ConstDefault> GenericTypes<T, AtomicUsize> for u64 {
66+
const TO_REMAIN_GENERIC: T = T::DEFAULT;
67+
const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable
68+
}
69+
70+
// a helper type used below
71+
struct Wrapper<T>(T);
72+
73+
// a constant whose type is an associated type should be linted at the implementation site, too.
74+
trait AssocTypes {
75+
type ToBeFrozen;
76+
type ToBeUnfrozen;
77+
type ToBeGenericParam;
78+
79+
const TO_BE_FROZEN: Self::ToBeFrozen;
80+
const TO_BE_UNFROZEN: Self::ToBeUnfrozen;
81+
const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen>;
82+
// to ensure it can handle things when a generic type remains after normalization.
83+
const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam>;
84+
}
85+
86+
impl<T: ConstDefault> AssocTypes for Vec<T> {
87+
type ToBeFrozen = u16;
88+
type ToBeUnfrozen = AtomicUsize;
89+
type ToBeGenericParam = T;
90+
91+
const TO_BE_FROZEN: Self::ToBeFrozen = 12;
92+
const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable
93+
const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable
94+
const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam> = Wrapper(T::DEFAULT);
8595
}
8696

87-
struct Local<T, U>(T, U);
97+
// a helper trait used below
98+
trait AssocTypesHelper {
99+
type NotToBeBounded;
100+
type ToBeBounded;
88101

89-
impl<T: Trait<U>, U: Trait2<AssocType5 = AtomicUsize>> Local<T, U> {
90-
const ASSOC_5: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable
102+
const NOT_TO_BE_BOUNDED: Self::NotToBeBounded;
103+
}
104+
105+
// a constant whose type is an assoc type originated from a generic param bounded at the definition
106+
// site should be linted at there.
107+
trait AssocTypesFromGenericParam<T>
108+
where
109+
T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
110+
{
111+
const NOT_BOUNDED: T::NotToBeBounded;
112+
const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable
113+
}
114+
115+
impl<T> AssocTypesFromGenericParam<T> for u64
116+
where
117+
T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
118+
{
119+
// an associated type could remain unknown in a trait impl.
120+
const NOT_BOUNDED: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
121+
const BOUNDED: T::ToBeBounded = AtomicUsize::new(15);
122+
}
123+
124+
trait SelfType {
125+
const SELF: Self;
126+
}
127+
128+
impl SelfType for u64 {
129+
const SELF: Self = 16;
130+
}
131+
132+
impl SelfType for AtomicUsize {
133+
// this (interior mutable `Self` const) exists in `parking_lot`.
134+
// `const_trait_impl` will replace it in the future, hopefully.
135+
const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable
136+
}
137+
138+
// Even though a constant contains a generic type, if it also have a interior mutable type,
139+
// it should be linted at the definition site.
140+
trait BothOfCellAndGeneric<T> {
141+
// this is a false negative in the current implementation.
142+
const DIRECT: Cell<T>;
143+
const INDIRECT: Cell<*const T>; //~ ERROR interior mutable
144+
}
145+
146+
impl<T: ConstDefault> BothOfCellAndGeneric<T> for u64 {
147+
const DIRECT: Cell<T> = Cell::new(T::DEFAULT);
148+
const INDIRECT: Cell<*const T> = Cell::new(std::ptr::null());
149+
}
150+
151+
struct Local<T>(T);
152+
153+
// a constant in an inherent impl are essentially the same as a normal const item
154+
// except there can be a generic or associated type.
155+
impl<T> Local<T>
156+
where
157+
T: ConstDefault + AssocTypesHelper<ToBeBounded = AtomicUsize>,
158+
{
159+
const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable
91160
const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy");
92-
const U_SELF: U = U::SELF_2;
93-
const T_ASSOC: T::AssocType = T::ASSOC;
94-
const U_ASSOC: U::AssocType5 = AtomicUsize::new(17); //~ ERROR interior mutable
161+
162+
const GENERIC_TYPE: T = T::DEFAULT;
163+
164+
const ASSOC_TYPE: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
165+
const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable
95166
}
96167

97168
fn main() {}

tests/ui/declare_interior_mutable_const.stderr

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,11 @@ LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable
3636
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
3737

3838
error: a `const` item should never be interior mutable
39-
--> $DIR/declare_interior_mutable_const.rs:44:5
39+
--> $DIR/declare_interior_mutable_const.rs:39:5
4040
|
4141
LL | const ATOMIC: AtomicUsize; //~ ERROR interior mutable
4242
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
4343

44-
error: a `const` item should never be interior mutable
45-
--> $DIR/declare_interior_mutable_const.rs:50:5
46-
|
47-
LL | const INPUT_ASSOC_2: T::AssocType5; //~ ERROR interior mutable
48-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
49-
5044
error: a `const` item should never be interior mutable
5145
--> $DIR/declare_interior_mutable_const.rs:16:9
5246
|
@@ -59,28 +53,52 @@ LL | declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR i
5953
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
6054

6155
error: a `const` item should never be interior mutable
62-
--> $DIR/declare_interior_mutable_const.rs:82:5
56+
--> $DIR/declare_interior_mutable_const.rs:67:5
57+
|
58+
LL | const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable
59+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
60+
61+
error: a `const` item should never be interior mutable
62+
--> $DIR/declare_interior_mutable_const.rs:92:5
63+
|
64+
LL | const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable
65+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66+
67+
error: a `const` item should never be interior mutable
68+
--> $DIR/declare_interior_mutable_const.rs:93:5
69+
|
70+
LL | const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable
71+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
72+
73+
error: a `const` item should never be interior mutable
74+
--> $DIR/declare_interior_mutable_const.rs:112:5
75+
|
76+
LL | const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable
77+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
78+
79+
error: a `const` item should never be interior mutable
80+
--> $DIR/declare_interior_mutable_const.rs:135:5
6381
|
64-
LL | const ASSOC_2: Self::AssocType2 = AtomicUsize::new(15); //~ ERROR interior mutable
65-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
82+
LL | const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable
83+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6684

6785
error: a `const` item should never be interior mutable
68-
--> $DIR/declare_interior_mutable_const.rs:83:5
86+
--> $DIR/declare_interior_mutable_const.rs:143:5
6987
|
70-
LL | const WRAPPED_ASSOC_2: Wrapper<Self::AssocType2> = Wrapper(AtomicUsize::new(16)); //~ ERROR interior mutable
71-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
88+
LL | const INDIRECT: Cell<*const T>; //~ ERROR interior mutable
89+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7290

7391
error: a `const` item should never be interior mutable
74-
--> $DIR/declare_interior_mutable_const.rs:90:5
92+
--> $DIR/declare_interior_mutable_const.rs:159:5
7593
|
76-
LL | const ASSOC_5: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable
77-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
94+
LL | const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable
95+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7896

7997
error: a `const` item should never be interior mutable
80-
--> $DIR/declare_interior_mutable_const.rs:94:5
98+
--> $DIR/declare_interior_mutable_const.rs:165:5
8199
|
82-
LL | const U_ASSOC: U::AssocType5 = AtomicUsize::new(17); //~ ERROR interior mutable
83-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
100+
LL | const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable
101+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
84102

85-
error: aborting due to 11 previous errors
103+
error: aborting due to 14 previous errors
86104

0 commit comments

Comments
 (0)