@@ -34,64 +34,135 @@ static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING);
3434#[ allow( clippy:: declare_interior_mutable_const) ]
3535const 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
97168fn main ( ) { }
0 commit comments