@@ -171,11 +171,38 @@ declare_clippy_lint! {
171
171
"a borrow of a boxed type"
172
172
}
173
173
174
+ declare_clippy_lint ! {
175
+ /// **What it does:** Checks for use of `Box<&T>` anywhere in the code.
176
+ ///
177
+ /// **Why is this bad?** Any `Box<&T>` can also be a `&T`, which is more
178
+ /// general.
179
+ ///
180
+ /// **Known problems:** None.
181
+ ///
182
+ /// **Example:**
183
+ /// ```rust
184
+ /// struct X {
185
+ /// values: Box<&T>,
186
+ /// }
187
+ /// ```
188
+ ///
189
+ /// Better:
190
+ ///
191
+ /// ```rust
192
+ /// struct X {
193
+ /// values: &T,
194
+ /// }
195
+ /// ```
196
+ pub BOX_BORROWS ,
197
+ perf,
198
+ "a box of borrowed type"
199
+ }
200
+
174
201
pub struct Types {
175
202
vec_box_size_threshold : u64 ,
176
203
}
177
204
178
- impl_lint_pass ! ( Types => [ BOX_VEC , VEC_BOX , OPTION_OPTION , LINKEDLIST , BORROWED_BOX ] ) ;
205
+ impl_lint_pass ! ( Types => [ BOX_VEC , VEC_BOX , OPTION_OPTION , LINKEDLIST , BORROWED_BOX , BOX_BORROWS ] ) ;
179
206
180
207
impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for Types {
181
208
fn check_fn (
@@ -257,6 +284,7 @@ impl Types {
257
284
/// The parameter `is_local` distinguishes the context of the type; types from
258
285
/// local bindings should only be checked for the `BORROWED_BOX` lint.
259
286
#[ allow( clippy:: too_many_lines) ]
287
+ #[ allow( clippy:: cognitive_complexity) ]
260
288
fn check_ty ( & mut self , cx : & LateContext < ' _ , ' _ > , hir_ty : & hir:: Ty < ' _ > , is_local : bool ) {
261
289
if hir_ty. span . from_expansion ( ) {
262
290
return ;
@@ -267,6 +295,27 @@ impl Types {
267
295
let res = qpath_res ( cx, qpath, hir_id) ;
268
296
if let Some ( def_id) = res. opt_def_id ( ) {
269
297
if Some ( def_id) == cx. tcx . lang_items ( ) . owned_box ( ) {
298
+ if_chain ! {
299
+ let last = last_path_segment( qpath) ;
300
+ if let Some ( ref params) = last. args;
301
+ if !params. parenthesized;
302
+ if let Some ( ty) = params. args. iter( ) . find_map( |arg| match arg {
303
+ GenericArg :: Type ( ty) => Some ( ty) ,
304
+ _ => None ,
305
+ } ) ;
306
+ if let TyKind :: Rptr ( ..) = ty. kind;
307
+ let ty_ty = hir_ty_to_ty( cx. tcx, ty) ;
308
+ then {
309
+ span_lint_and_help(
310
+ cx,
311
+ BOX_BORROWS ,
312
+ hir_ty. span,
313
+ "usage of `Box<&T>`" ,
314
+ format!( "try `{}`" , ty_ty) . as_str( ) ,
315
+ ) ;
316
+ return ; // don't recurse into the type
317
+ }
318
+ }
270
319
if match_type_parameter ( cx, qpath, & paths:: VEC ) {
271
320
span_lint_and_help (
272
321
cx,
0 commit comments