@@ -23,8 +23,10 @@ mod improper_ctypes;
23
23
use crate :: lints:: {
24
24
AmbiguousWidePointerComparisons , AmbiguousWidePointerComparisonsAddrMetadataSuggestion ,
25
25
AmbiguousWidePointerComparisonsAddrSuggestion , AtomicOrderingFence , AtomicOrderingLoad ,
26
- AtomicOrderingStore , ImproperCTypes , InvalidAtomicOrderingDiag , InvalidNanComparisons ,
27
- InvalidNanComparisonsSuggestion , UnusedComparisons , VariantSizeDifferencesDiag ,
26
+ AtomicOrderingStore , ImproperCTypes , InteriorMutableConstsDiag ,
27
+ InteriorMutableConstsSuggestionAllow , InteriorMutableConstsSuggestionStatic ,
28
+ InvalidAtomicOrderingDiag , InvalidNanComparisons , InvalidNanComparisonsSuggestion ,
29
+ UnusedComparisons , VariantSizeDifferencesDiag ,
28
30
} ;
29
31
use crate :: { LateContext , LateLintPass , LintContext , fluent_generated as fluent} ;
30
32
@@ -167,6 +169,37 @@ declare_lint! {
167
169
"detects ambiguous wide pointer comparisons"
168
170
}
169
171
172
+ declare_lint ! {
173
+ /// The `interior_mutable_consts` lint detects instance where
174
+ /// const-items have a interior mutable type, which silently does nothing.
175
+ ///
176
+ /// ### Example
177
+ ///
178
+ /// ```
179
+ /// use std::sync::Once;
180
+ ///
181
+ /// const A: Once = Once::new(); // using `B` will always duplicate `B` and never
182
+ /// // modify it-self as it's a const-item and not a
183
+ /// // static-item
184
+ /// ```
185
+ ///
186
+ /// {{produces}}
187
+ ///
188
+ /// ### Explanation
189
+ ///
190
+ /// Using a const-item with an interior mutable type has no effect as const-item
191
+ /// are essentially inlined wherever they are used, meaning that they are copied
192
+ /// directly into the relevant context when used rendering modification through
193
+ /// interior mutability ineffective across usage of that const-item.
194
+ ///
195
+ /// The current implementation of this lint only warns on significant `std` and
196
+ /// `core` interior mutable types, like `Once`, `AtomicI32`, ... this is done out
197
+ /// of prudence and may be extended in the future.
198
+ INTERIOR_MUTABLE_CONSTS ,
199
+ Warn ,
200
+ "detects const items with interior mutable type" ,
201
+ }
202
+
170
203
#[ derive( Copy , Clone ) ]
171
204
pub ( crate ) struct TypeLimits {
172
205
/// Id of the last visited negated expression
@@ -179,7 +212,8 @@ impl_lint_pass!(TypeLimits => [
179
212
UNUSED_COMPARISONS ,
180
213
OVERFLOWING_LITERALS ,
181
214
INVALID_NAN_COMPARISONS ,
182
- AMBIGUOUS_WIDE_POINTER_COMPARISONS
215
+ AMBIGUOUS_WIDE_POINTER_COMPARISONS ,
216
+ INTERIOR_MUTABLE_CONSTS ,
183
217
] ) ;
184
218
185
219
impl TypeLimits {
@@ -513,6 +547,44 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
513
547
} )
514
548
}
515
549
}
550
+
551
+ fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx hir:: Item < ' tcx > ) {
552
+ if let hir:: ItemKind :: Const ( ty, _generics, _body_id) = item. kind
553
+ && let hir:: TyKind :: Path ( ref qpath) = ty. kind
554
+ && let Some ( def_id) = cx. qpath_res ( qpath, ty. hir_id ) . opt_def_id ( )
555
+ && cx. tcx . has_attr ( def_id, sym:: rustc_significant_interior_mutable_type)
556
+ && let Some ( ty_name) = cx. tcx . opt_item_ident ( def_id)
557
+ {
558
+ let ( sugg_static, sugg_allow) = if let Some ( vis_span) =
559
+ item. vis_span . find_ancestor_inside ( item. span )
560
+ && item. span . can_be_used_for_suggestions ( )
561
+ && vis_span. can_be_used_for_suggestions ( )
562
+ {
563
+ (
564
+ InteriorMutableConstsSuggestionStatic :: Spanful {
565
+ const_ : item. vis_span . between ( item. ident . span ) ,
566
+ before : if !vis_span. is_empty ( ) { " " } else { "" } ,
567
+ } ,
568
+ InteriorMutableConstsSuggestionAllow :: Spanful {
569
+ span : item. span . shrink_to_lo ( ) ,
570
+ } ,
571
+ )
572
+ } else {
573
+ (
574
+ InteriorMutableConstsSuggestionStatic :: Spanless ,
575
+ InteriorMutableConstsSuggestionAllow :: Spanless ,
576
+ )
577
+ } ;
578
+
579
+ cx. emit_span_lint ( INTERIOR_MUTABLE_CONSTS , item. span , InteriorMutableConstsDiag {
580
+ ty_name,
581
+ ty_span : ty. span ,
582
+ const_name : item. ident ,
583
+ sugg_static,
584
+ sugg_allow,
585
+ } ) ;
586
+ }
587
+ }
516
588
}
517
589
518
590
declare_lint ! {
0 commit comments