1
1
#![ allow( rustc:: default_hash_types) ]
2
2
3
+ mod borrowed_box;
3
4
mod box_vec;
4
5
mod linked_list;
5
6
mod option_option;
@@ -18,9 +19,9 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
18
19
use rustc_hir as hir;
19
20
use rustc_hir:: intravisit:: { walk_body, walk_expr, walk_ty, FnKind , NestedVisitorMap , Visitor } ;
20
21
use rustc_hir:: {
21
- BinOpKind , Block , Body , Expr , ExprKind , FnDecl , FnRetTy , FnSig , GenericArg , GenericBounds , GenericParamKind , HirId ,
22
- ImplItem , ImplItemKind , Item , ItemKind , Lifetime , Lit , Local , MatchSource , MutTy , Mutability , Node , QPath , Stmt ,
23
- StmtKind , SyntheticTyParamKind , TraitFn , TraitItem , TraitItemKind , TyKind , UnOp ,
22
+ BinOpKind , Block , Body , Expr , ExprKind , FnDecl , FnRetTy , FnSig , GenericArg , GenericParamKind , HirId , ImplItem ,
23
+ ImplItemKind , Item , ItemKind , Lit , Local , MatchSource , MutTy , Mutability , Node , QPath , Stmt , StmtKind , TraitFn ,
24
+ TraitItem , TraitItemKind , TyKind , UnOp ,
24
25
} ;
25
26
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
26
27
use rustc_middle:: hir:: map:: Map ;
@@ -376,7 +377,11 @@ impl Types {
376
377
QPath :: LangItem ( ..) => { } ,
377
378
}
378
379
} ,
379
- TyKind :: Rptr ( ref lt, ref mut_ty) => self . check_ty_rptr ( cx, hir_ty, is_local, lt, mut_ty) ,
380
+ TyKind :: Rptr ( ref lt, ref mut_ty) => {
381
+ if !borrowed_box:: check ( cx, hir_ty, is_local, lt, mut_ty) {
382
+ self . check_ty ( cx, & mut_ty. ty , is_local) ;
383
+ }
384
+ } ,
380
385
TyKind :: Slice ( ref ty) | TyKind :: Array ( ref ty, _) | TyKind :: Ptr ( MutTy { ref ty, .. } ) => {
381
386
self . check_ty ( cx, ty, is_local)
382
387
} ,
@@ -388,115 +393,6 @@ impl Types {
388
393
_ => { } ,
389
394
}
390
395
}
391
-
392
- fn check_ty_rptr (
393
- & mut self ,
394
- cx : & LateContext < ' _ > ,
395
- hir_ty : & hir:: Ty < ' _ > ,
396
- is_local : bool ,
397
- lt : & Lifetime ,
398
- mut_ty : & MutTy < ' _ > ,
399
- ) {
400
- match mut_ty. ty . kind {
401
- TyKind :: Path ( ref qpath) => {
402
- let hir_id = mut_ty. ty . hir_id ;
403
- let def = cx. qpath_res ( qpath, hir_id) ;
404
- if_chain ! {
405
- if let Some ( def_id) = def. opt_def_id( ) ;
406
- if Some ( def_id) == cx. tcx. lang_items( ) . owned_box( ) ;
407
- if let QPath :: Resolved ( None , ref path) = * qpath;
408
- if let [ ref bx] = * path. segments;
409
- if let Some ( ref params) = bx. args;
410
- if !params. parenthesized;
411
- if let Some ( inner) = params. args. iter( ) . find_map( |arg| match arg {
412
- GenericArg :: Type ( ty) => Some ( ty) ,
413
- _ => None ,
414
- } ) ;
415
- then {
416
- if is_any_trait( inner) {
417
- // Ignore `Box<Any>` types; see issue #1884 for details.
418
- return ;
419
- }
420
-
421
- let ltopt = if lt. is_elided( ) {
422
- String :: new( )
423
- } else {
424
- format!( "{} " , lt. name. ident( ) . as_str( ) )
425
- } ;
426
-
427
- if mut_ty. mutbl == Mutability :: Mut {
428
- // Ignore `&mut Box<T>` types; see issue #2907 for
429
- // details.
430
- return ;
431
- }
432
-
433
- // When trait objects or opaque types have lifetime or auto-trait bounds,
434
- // we need to add parentheses to avoid a syntax error due to its ambiguity.
435
- // Originally reported as the issue #3128.
436
- let inner_snippet = snippet( cx, inner. span, ".." ) ;
437
- let suggestion = match & inner. kind {
438
- TyKind :: TraitObject ( bounds, lt_bound) if bounds. len( ) > 1 || !lt_bound. is_elided( ) => {
439
- format!( "&{}({})" , ltopt, & inner_snippet)
440
- } ,
441
- TyKind :: Path ( qpath)
442
- if get_bounds_if_impl_trait( cx, qpath, inner. hir_id)
443
- . map_or( false , |bounds| bounds. len( ) > 1 ) =>
444
- {
445
- format!( "&{}({})" , ltopt, & inner_snippet)
446
- } ,
447
- _ => format!( "&{}{}" , ltopt, & inner_snippet) ,
448
- } ;
449
- span_lint_and_sugg(
450
- cx,
451
- BORROWED_BOX ,
452
- hir_ty. span,
453
- "you seem to be trying to use `&Box<T>`. Consider using just `&T`" ,
454
- "try" ,
455
- suggestion,
456
- // To make this `MachineApplicable`, at least one needs to check if it isn't a trait item
457
- // because the trait impls of it will break otherwise;
458
- // and there may be other cases that result in invalid code.
459
- // For example, type coercion doesn't work nicely.
460
- Applicability :: Unspecified ,
461
- ) ;
462
- return ; // don't recurse into the type
463
- }
464
- } ;
465
- self . check_ty ( cx, & mut_ty. ty , is_local) ;
466
- } ,
467
- _ => self . check_ty ( cx, & mut_ty. ty , is_local) ,
468
- }
469
- }
470
- }
471
-
472
- // Returns true if given type is `Any` trait.
473
- fn is_any_trait ( t : & hir:: Ty < ' _ > ) -> bool {
474
- if_chain ! {
475
- if let TyKind :: TraitObject ( ref traits, _) = t. kind;
476
- if !traits. is_empty( ) ;
477
- // Only Send/Sync can be used as additional traits, so it is enough to
478
- // check only the first trait.
479
- if match_path( & traits[ 0 ] . trait_ref. path, & paths:: ANY_TRAIT ) ;
480
- then {
481
- return true ;
482
- }
483
- }
484
-
485
- false
486
- }
487
-
488
- fn get_bounds_if_impl_trait < ' tcx > ( cx : & LateContext < ' tcx > , qpath : & QPath < ' _ > , id : HirId ) -> Option < GenericBounds < ' tcx > > {
489
- if_chain ! {
490
- if let Some ( did) = cx. qpath_res( qpath, id) . opt_def_id( ) ;
491
- if let Some ( Node :: GenericParam ( generic_param) ) = cx. tcx. hir( ) . get_if_local( did) ;
492
- if let GenericParamKind :: Type { synthetic, .. } = generic_param. kind;
493
- if synthetic == Some ( SyntheticTyParamKind :: ImplTrait ) ;
494
- then {
495
- Some ( generic_param. bounds)
496
- } else {
497
- None
498
- }
499
- }
500
396
}
501
397
502
398
declare_clippy_lint ! {
0 commit comments