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,46 @@ 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 `T<Option<U>>` where `T` is a type that has
310
+ /// [null pointer optimization](https://doc.rust-lang.org/core/option/#representation).
311
+ ///
312
+ /// ### Why is this bad?
313
+ /// It's slower, as `Option` can use `null` as `None`, instead of adding another layer of
314
+ /// indirection.
315
+ ///
316
+ /// ### Example
317
+ /// ```rust
318
+ /// struct MyWrapperType<T>(Box<Option<T>>);
319
+ /// ```
320
+ /// Use instead:
321
+ /// ```rust
322
+ /// struct MyWrapperType<T>(Option<Box<T>>);
323
+ /// ```
324
+ #[ clippy:: version = "1.72.0" ]
325
+ pub NULL_POINTER_OPTIMIZATION ,
326
+ perf,
327
+ "checks for `U<Option<T>>` where `U` is a type that has null pointer optimization"
328
+ }
306
329
pub struct Types {
307
330
vec_box_size_threshold : u64 ,
308
331
type_complexity_threshold : u64 ,
309
332
avoid_breaking_exported_api : bool ,
310
333
}
311
334
312
- impl_lint_pass ! ( Types => [ BOX_COLLECTION , VEC_BOX , OPTION_OPTION , LINKEDLIST , BORROWED_BOX , REDUNDANT_ALLOCATION , RC_BUFFER , RC_MUTEX , TYPE_COMPLEXITY ] ) ;
335
+ impl_lint_pass ! ( Types => [
336
+ BOX_COLLECTION ,
337
+ VEC_BOX ,
338
+ OPTION_OPTION ,
339
+ LINKEDLIST ,
340
+ BORROWED_BOX ,
341
+ REDUNDANT_ALLOCATION ,
342
+ RC_BUFFER ,
343
+ RC_MUTEX ,
344
+ TYPE_COMPLEXITY ,
345
+ NULL_POINTER_OPTIMIZATION ,
346
+ ] ) ;
313
347
314
348
impl < ' tcx > LateLintPass < ' tcx > for Types {
315
349
fn check_fn (
@@ -349,10 +383,11 @@ impl<'tcx> LateLintPass<'tcx> for Types {
349
383
let is_exported = cx. effective_visibilities . is_exported ( item. owner_id . def_id ) ;
350
384
351
385
match item. kind {
352
- ItemKind :: Static ( ty, _, _) | ItemKind :: Const ( ty, _) => self . check_ty (
386
+ ItemKind :: Static ( ty, _, _) | ItemKind :: Const ( ty, _) | ItemKind :: TyAlias ( ty , _ ) => self . check_ty (
353
387
cx,
354
388
ty,
355
389
CheckTyContext {
390
+ is_in_ty_alias : matches ! ( item. kind, ItemKind :: TyAlias ( ..) ) ,
356
391
is_exported,
357
392
..CheckTyContext :: default ( )
358
393
} ,
@@ -476,7 +511,10 @@ impl Types {
476
511
return ;
477
512
}
478
513
479
- if !context. is_nested_call && type_complexity:: check ( cx, hir_ty, self . type_complexity_threshold ) {
514
+ if !context. is_nested_call
515
+ && !context. is_in_ty_alias
516
+ && type_complexity:: check ( cx, hir_ty, self . type_complexity_threshold )
517
+ {
480
518
return ;
481
519
}
482
520
@@ -492,13 +530,16 @@ impl Types {
492
530
// in `clippy_lints::utils::conf.rs`
493
531
494
532
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) ;
533
+ if !context. is_in_ty_alias {
534
+ triggered |= box_collection:: check ( cx, hir_ty, qpath, def_id) ;
535
+ triggered |= redundant_allocation:: check ( cx, hir_ty, qpath, def_id) ;
536
+ triggered |= rc_buffer:: check ( cx, hir_ty, qpath, def_id) ;
537
+ triggered |= vec_box:: check ( cx, hir_ty, qpath, def_id, self . vec_box_size_threshold ) ;
538
+ triggered |= option_option:: check ( cx, hir_ty, qpath, def_id) ;
539
+ triggered |= linked_list:: check ( cx, hir_ty, def_id) ;
540
+ triggered |= rc_mutex:: check ( cx, hir_ty, qpath, def_id) ;
541
+ }
542
+ triggered |= null_pointer_optimization:: check ( cx, hir_ty, qpath, res) ;
502
543
503
544
if triggered {
504
545
return ;
@@ -580,6 +621,7 @@ impl Types {
580
621
#[ allow( clippy:: struct_excessive_bools) ]
581
622
#[ derive( Clone , Copy , Default ) ]
582
623
struct CheckTyContext {
624
+ is_in_ty_alias : bool ,
583
625
is_in_trait_impl : bool ,
584
626
/// `true` for types on local variables.
585
627
is_local : bool ,
0 commit comments