@@ -194,11 +194,63 @@ declare_clippy_lint! {
194
194
"a box of borrowed type"
195
195
}
196
196
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
+
197
249
pub struct Types {
198
250
vec_box_size_threshold : u64 ,
199
251
}
200
252
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 ] ) ;
202
254
203
255
impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for Types {
204
256
fn check_fn (
@@ -322,6 +374,27 @@ impl Types {
322
374
) ;
323
375
return ; // don't recurse into the type
324
376
}
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
+ }
325
398
} else if cx. tcx . is_diagnostic_item ( Symbol :: intern ( "vec_type" ) , def_id) {
326
399
if_chain ! {
327
400
// Get the _ part of Vec<_>
0 commit comments