1
1
mod borrowed_box;
2
2
mod box_collection;
3
3
mod linked_list;
4
+ mod null_pointer_optimization;
4
5
mod option_option;
5
6
mod rc_buffer;
6
7
mod rc_mutex;
@@ -303,13 +304,50 @@ declare_clippy_lint! {
303
304
"usage of `Rc<Mutex<T>>`"
304
305
}
305
306
307
+ declare_clippy_lint ! {
308
+ /// ### What it does
309
+ /// Checks for `C<Option<T>>` where `C` is a type that has
310
+ /// [null pointer optimization](https://doc.rust-lang.org/core/option/#representation).
311
+ ///
312
+ /// Note: There are some cases where `C<Option<T>>` is necessary, like getting a
313
+ /// `&mut Option<T>` from a `Box<Option<T>>`. This is not possible with `Option<Box<T>>` without
314
+ /// unstable features, currently.
315
+ ///
316
+ /// ### Why is this bad?
317
+ /// It's slower, as `Option` can use `null` as `None`, instead of adding another layer of
318
+ /// indirection.
319
+ ///
320
+ /// ### Example
321
+ /// ```rust
322
+ /// struct MyWrapperType<T>(Box<Option<T>>);
323
+ /// ```
324
+ /// Use instead:
325
+ /// ```rust
326
+ /// struct MyWrapperType<T>(Option<Box<T>>);
327
+ /// ```
328
+ #[ clippy:: version = "1.72.0" ]
329
+ pub NULL_POINTER_OPTIMIZATION ,
330
+ perf,
331
+ "checks for `C<Option<T>>` where `C` is a type that has null pointer optimization"
332
+ }
306
333
pub struct Types {
307
334
vec_box_size_threshold : u64 ,
308
335
type_complexity_threshold : u64 ,
309
336
avoid_breaking_exported_api : bool ,
310
337
}
311
338
312
- impl_lint_pass ! ( Types => [ BOX_COLLECTION , VEC_BOX , OPTION_OPTION , LINKEDLIST , BORROWED_BOX , REDUNDANT_ALLOCATION , RC_BUFFER , RC_MUTEX , TYPE_COMPLEXITY ] ) ;
339
+ impl_lint_pass ! ( Types => [
340
+ BOX_COLLECTION ,
341
+ VEC_BOX ,
342
+ OPTION_OPTION ,
343
+ LINKEDLIST ,
344
+ BORROWED_BOX ,
345
+ REDUNDANT_ALLOCATION ,
346
+ RC_BUFFER ,
347
+ RC_MUTEX ,
348
+ TYPE_COMPLEXITY ,
349
+ NULL_POINTER_OPTIMIZATION ,
350
+ ] ) ;
313
351
314
352
impl < ' tcx > LateLintPass < ' tcx > for Types {
315
353
fn check_fn (
@@ -349,10 +387,11 @@ impl<'tcx> LateLintPass<'tcx> for Types {
349
387
let is_exported = cx. effective_visibilities . is_exported ( item. owner_id . def_id ) ;
350
388
351
389
match item. kind {
352
- ItemKind :: Static ( ty, _, _) | ItemKind :: Const ( ty, _) => self . check_ty (
390
+ ItemKind :: Static ( ty, _, _) | ItemKind :: Const ( ty, _) | ItemKind :: TyAlias ( ty , _ ) => self . check_ty (
353
391
cx,
354
392
ty,
355
393
CheckTyContext {
394
+ is_in_ty_alias : matches ! ( item. kind, ItemKind :: TyAlias ( ..) ) ,
356
395
is_exported,
357
396
..CheckTyContext :: default ( )
358
397
} ,
@@ -476,7 +515,10 @@ impl Types {
476
515
return ;
477
516
}
478
517
479
- if !context. is_nested_call && type_complexity:: check ( cx, hir_ty, self . type_complexity_threshold ) {
518
+ if !context. is_nested_call
519
+ && !context. is_in_ty_alias
520
+ && type_complexity:: check ( cx, hir_ty, self . type_complexity_threshold )
521
+ {
480
522
return ;
481
523
}
482
524
@@ -492,13 +534,16 @@ impl Types {
492
534
// in `clippy_lints::utils::conf.rs`
493
535
494
536
let mut triggered = false ;
495
- triggered |= box_collection:: check ( cx, hir_ty, qpath, def_id) ;
496
- triggered |= redundant_allocation:: check ( cx, hir_ty, qpath, def_id) ;
497
- triggered |= rc_buffer:: check ( cx, hir_ty, qpath, def_id) ;
498
- triggered |= vec_box:: check ( cx, hir_ty, qpath, def_id, self . vec_box_size_threshold ) ;
499
- triggered |= option_option:: check ( cx, hir_ty, qpath, def_id) ;
500
- triggered |= linked_list:: check ( cx, hir_ty, def_id) ;
501
- triggered |= rc_mutex:: check ( cx, hir_ty, qpath, def_id) ;
537
+ if !context. is_in_ty_alias {
538
+ triggered |= box_collection:: check ( cx, hir_ty, qpath, def_id) ;
539
+ triggered |= redundant_allocation:: check ( cx, hir_ty, qpath, def_id) ;
540
+ triggered |= rc_buffer:: check ( cx, hir_ty, qpath, def_id) ;
541
+ triggered |= vec_box:: check ( cx, hir_ty, qpath, def_id, self . vec_box_size_threshold ) ;
542
+ triggered |= option_option:: check ( cx, hir_ty, qpath, def_id) ;
543
+ triggered |= linked_list:: check ( cx, hir_ty, def_id) ;
544
+ triggered |= rc_mutex:: check ( cx, hir_ty, qpath, def_id) ;
545
+ }
546
+ triggered |= null_pointer_optimization:: check ( cx, hir_ty, qpath, res) ;
502
547
503
548
if triggered {
504
549
return ;
@@ -580,6 +625,7 @@ impl Types {
580
625
#[ allow( clippy:: struct_excessive_bools) ]
581
626
#[ derive( Clone , Copy , Default ) ]
582
627
struct CheckTyContext {
628
+ is_in_ty_alias : bool ,
583
629
is_in_trait_impl : bool ,
584
630
/// `true` for types on local variables.
585
631
is_local : bool ,
0 commit comments