@@ -194,11 +194,63 @@ declare_clippy_lint! {
194194 "a box of borrowed type"
195195}
196196
197+ declare_clippy_lint ! {
198+ /// **What it does:** Checks for use of `Rc<Rc<T>>` anywhere in the code.
199+ ///
200+ /// **Why is this bad?** Reference counting pointer of reference counting pointer
201+ /// is an unnecessary level of indirection.
202+ ///
203+ /// **Known problems:** None.
204+ ///
205+ /// **Example:**
206+ /// ```rust
207+ /// # use std::rc::Rc;
208+ /// fn foo(bar: Rc<Rc<usize>>) {}
209+ /// ```
210+ ///
211+ /// Better:
212+ ///
213+ /// ```rust
214+ /// # use std::rc::Rc;
215+ /// fn foo(bar: Rc<usize>) {}
216+ /// ```
217+ pub RC_RC ,
218+ perf,
219+ "an Rc of Rc"
220+ }
221+
222+ declare_clippy_lint ! {
223+ /// **What it does:** Checks for use of `Rc<Box<T>>` anywhere in the code.
224+ ///
225+ /// **Why is this bad?** `Rc` already keeps its contents in a separate area on
226+ /// the heap. So if you `Box` its contents, you just add another level of indirection.
227+ ///
228+ /// **Known problems:** None.
229+ ///
230+ /// **Example:**
231+ /// ```rust
232+ /// # use std::rc::Rc;
233+ /// # use std::boxed::Box;
234+ /// fn foo(bar: Rc<Box<usize>>) {}
235+ /// ```
236+ ///
237+ /// Better:
238+ ///
239+ /// ```rust
240+ /// # use std::rc::Rc;
241+ /// # use std::boxed::Box;
242+ /// fn foo(bar: Rc<usize>) {}
243+ /// ```
244+ pub RC_BOX ,
245+ perf,
246+ "an Rc of Box"
247+ }
248+
197249pub struct Types {
198250 vec_box_size_threshold : u64 ,
199251}
200252
201- impl_lint_pass ! ( Types => [ BOX_VEC , VEC_BOX , OPTION_OPTION , LINKEDLIST , BORROWED_BOX , BOX_BORROWS ] ) ;
253+ impl_lint_pass ! ( Types => [ BOX_VEC , VEC_BOX , OPTION_OPTION , LINKEDLIST , BORROWED_BOX , BOX_BORROWS , RC_RC , RC_BOX ] ) ;
202254
203255impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for Types {
204256 fn check_fn (
@@ -322,6 +374,27 @@ impl Types {
322374 ) ;
323375 return ; // don't recurse into the type
324376 }
377+ } else if Some ( def_id) == cx. tcx . lang_items ( ) . rc ( ) {
378+ if match_type_parameter ( cx, qpath, & paths:: RC ) {
379+ span_lint_and_help (
380+ cx,
381+ RC_RC ,
382+ hir_ty. span ,
383+ "usage of `Rc<Rc<T>>`" ,
384+ "Rc<Rc<T>> can be simplified to Rc<T>" ,
385+ ) ;
386+ return ; // don't recurse into the type
387+ }
388+ if match_type_parameter ( cx, qpath, & paths:: BOX ) {
389+ span_lint_and_help (
390+ cx,
391+ RC_BOX ,
392+ hir_ty. span ,
393+ "usage of `Rc<Box<T>>`" ,
394+ "Rc<Box<T>> can be simplified to Rc<T>" ,
395+ ) ;
396+ return ; // don't recurse into the type
397+ }
325398 } else if cx. tcx . is_diagnostic_item ( Symbol :: intern ( "vec_type" ) , def_id) {
326399 if_chain ! {
327400 // Get the _ part of Vec<_>
0 commit comments