@@ -2,6 +2,7 @@ mod borrowed_box;
2
2
mod box_collection;
3
3
mod linked_list;
4
4
mod option_option;
5
+ mod owned_cow;
5
6
mod rc_buffer;
6
7
mod rc_mutex;
7
8
mod redundant_allocation;
@@ -355,13 +356,63 @@ declare_clippy_lint! {
355
356
"usage of `Rc<Mutex<T>>`"
356
357
}
357
358
359
+ declare_clippy_lint ! {
360
+ /// ### What it does
361
+ /// Detects needlessly owned `Cow` types.
362
+ ///
363
+ /// ### Why is this bad?
364
+ /// The borrowed types are usually more flexible, in that e.g. a
365
+ /// `Cow<'_, str>` can accept both `&str` and `String` while
366
+ /// `Cow<'_, String>` can only accept `&String` and `String`. In
367
+ /// particular, `&str` is more general, because it allows for string
368
+ /// literals while `&String` can only be borrowed from a heap-owned
369
+ /// `String`).
370
+ ///
371
+ /// ### Known Problems
372
+ /// The lint does not check for usage of the type. There may be external
373
+ /// interfaces that require the use of an owned type.
374
+ ///
375
+ /// At least the `CString` type also has a different API than `CStr`: The
376
+ /// former has an `as_bytes` method which the latter calls `to_bytes`.
377
+ /// There is no guarantee that other types won't gain additional methods
378
+ /// leading to a similar mismatch.
379
+ ///
380
+ /// In addition, the lint only checks for the known problematic types
381
+ /// `String`, `Vec<_>`, `CString`, `OsString` and `PathBuf`. Custom types
382
+ /// that implement `ToOwned` will not be detected.
383
+ ///
384
+ /// ### Example
385
+ /// ```no_run
386
+ /// let wrogn: std::borrow::Cow<'_, Vec<u8>>;
387
+ /// ```
388
+ /// Use instead:
389
+ /// ```no_run
390
+ /// let right: std::borrow::Cow<'_, [u8]>;
391
+ /// ```
392
+ #[ clippy:: version = "1.85.0" ]
393
+ pub OWNED_COW ,
394
+ style,
395
+ "needlessly owned Cow type"
396
+ }
397
+
358
398
pub struct Types {
359
399
vec_box_size_threshold : u64 ,
360
400
type_complexity_threshold : u64 ,
361
401
avoid_breaking_exported_api : bool ,
362
402
}
363
403
364
- impl_lint_pass ! ( Types => [ BOX_COLLECTION , VEC_BOX , OPTION_OPTION , LINKEDLIST , BORROWED_BOX , REDUNDANT_ALLOCATION , RC_BUFFER , RC_MUTEX , TYPE_COMPLEXITY ] ) ;
404
+ impl_lint_pass ! ( Types => [
405
+ BOX_COLLECTION ,
406
+ VEC_BOX ,
407
+ OPTION_OPTION ,
408
+ LINKEDLIST ,
409
+ BORROWED_BOX ,
410
+ REDUNDANT_ALLOCATION ,
411
+ RC_BUFFER ,
412
+ RC_MUTEX ,
413
+ TYPE_COMPLEXITY ,
414
+ OWNED_COW
415
+ ] ) ;
365
416
366
417
impl < ' tcx > LateLintPass < ' tcx > for Types {
367
418
fn check_fn (
@@ -561,6 +612,7 @@ impl Types {
561
612
triggered |= option_option:: check ( cx, hir_ty, qpath, def_id) ;
562
613
triggered |= linked_list:: check ( cx, hir_ty, def_id) ;
563
614
triggered |= rc_mutex:: check ( cx, hir_ty, qpath, def_id) ;
615
+ triggered |= owned_cow:: check ( cx, qpath, def_id) ;
564
616
565
617
if triggered {
566
618
return ;
@@ -612,6 +664,14 @@ impl Types {
612
664
QPath :: LangItem ( ..) => { } ,
613
665
}
614
666
} ,
667
+ TyKind :: Path ( ref qpath) => {
668
+ let res = cx. qpath_res ( qpath, hir_ty. hir_id ) ;
669
+ if let Some ( def_id) = res. opt_def_id ( )
670
+ && self . is_type_change_allowed ( context)
671
+ {
672
+ owned_cow:: check ( cx, qpath, def_id) ;
673
+ }
674
+ } ,
615
675
TyKind :: Ref ( lt, ref mut_ty) => {
616
676
context. is_nested_call = true ;
617
677
if !borrowed_box:: check ( cx, hir_ty, lt, mut_ty) {
0 commit comments