1
+ mod explicit_counter_loop;
1
2
mod for_loop_arg;
2
- mod for_loop_explicit_counter;
3
3
mod for_loop_over_map_kv;
4
4
mod for_loop_range;
5
5
mod for_mut_range_bound;
@@ -11,27 +11,20 @@ mod needless_collect;
11
11
mod never_loop;
12
12
mod same_item_push;
13
13
mod utils;
14
+ mod while_let_on_iterator;
14
15
15
16
use crate :: utils:: sugg:: Sugg ;
16
- use crate :: utils:: usage:: mutated_variables;
17
17
use crate :: utils:: {
18
- get_enclosing_block, get_trait_def_id, higher, implements_trait, is_in_panic_handler, is_no_std_crate,
19
- is_refutable, last_path_segment, match_trait_method, path_to_local, path_to_local_id, paths,
20
- snippet_with_applicability, span_lint_and_help, span_lint_and_sugg, sugg,
18
+ higher, is_in_panic_handler, is_no_std_crate, snippet_with_applicability, span_lint_and_help, span_lint_and_sugg,
19
+ sugg,
21
20
} ;
22
- use if_chain:: if_chain;
23
21
use rustc_errors:: Applicability ;
24
- use rustc_hir:: intravisit:: { walk_block, walk_expr, NestedVisitorMap , Visitor } ;
25
- use rustc_hir:: { Block , Expr , ExprKind , HirId , LoopSource , MatchSource , Node , Pat , PatKind , StmtKind } ;
22
+ use rustc_hir:: { Block , Expr , ExprKind , LoopSource , MatchSource , Pat , StmtKind } ;
26
23
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
27
- use rustc_middle:: hir:: map:: Map ;
28
24
use rustc_middle:: lint:: in_external_macro;
29
25
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
30
26
use rustc_span:: source_map:: Span ;
31
- use rustc_span:: symbol:: sym;
32
- use utils:: {
33
- get_span_of_entire_for_loop, make_iterator_snippet, IncrementVisitor , InitializeVisitor , LoopNestVisitor , Nesting ,
34
- } ;
27
+ use utils:: { get_span_of_entire_for_loop, make_iterator_snippet, IncrementVisitor , InitializeVisitor } ;
35
28
36
29
declare_clippy_lint ! {
37
30
/// **What it does:** Checks for for-loops that manually copy items between
@@ -625,54 +618,8 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
625
618
}
626
619
}
627
620
}
628
- if let ExprKind :: Match ( ref match_expr, ref arms, MatchSource :: WhileLetDesugar ) = expr. kind {
629
- let pat = & arms[ 0 ] . pat . kind ;
630
- if let (
631
- & PatKind :: TupleStruct ( ref qpath, ref pat_args, _) ,
632
- & ExprKind :: MethodCall ( ref method_path, _, ref method_args, _) ,
633
- ) = ( pat, & match_expr. kind )
634
- {
635
- let iter_expr = & method_args[ 0 ] ;
636
-
637
- // Don't lint when the iterator is recreated on every iteration
638
- if_chain ! {
639
- if let ExprKind :: MethodCall ( ..) | ExprKind :: Call ( ..) = iter_expr. kind;
640
- if let Some ( iter_def_id) = get_trait_def_id( cx, & paths:: ITERATOR ) ;
641
- if implements_trait( cx, cx. typeck_results( ) . expr_ty( iter_expr) , iter_def_id, & [ ] ) ;
642
- then {
643
- return ;
644
- }
645
- }
646
621
647
- let lhs_constructor = last_path_segment ( qpath) ;
648
- if method_path. ident . name == sym:: next
649
- && match_trait_method ( cx, match_expr, & paths:: ITERATOR )
650
- && lhs_constructor. ident . name == sym:: Some
651
- && ( pat_args. is_empty ( )
652
- || !is_refutable ( cx, & pat_args[ 0 ] )
653
- && !is_used_inside ( cx, iter_expr, & arms[ 0 ] . body )
654
- && !is_iterator_used_after_while_let ( cx, iter_expr)
655
- && !is_nested ( cx, expr, & method_args[ 0 ] ) )
656
- {
657
- let mut applicability = Applicability :: MachineApplicable ;
658
- let iterator = snippet_with_applicability ( cx, method_args[ 0 ] . span , "_" , & mut applicability) ;
659
- let loop_var = if pat_args. is_empty ( ) {
660
- "_" . to_string ( )
661
- } else {
662
- snippet_with_applicability ( cx, pat_args[ 0 ] . span , "_" , & mut applicability) . into_owned ( )
663
- } ;
664
- span_lint_and_sugg (
665
- cx,
666
- WHILE_LET_ON_ITERATOR ,
667
- expr. span . with_hi ( match_expr. span . hi ( ) ) ,
668
- "this loop could be written as a `for` loop" ,
669
- "try" ,
670
- format ! ( "for {} in {}" , loop_var, iterator) ,
671
- applicability,
672
- ) ;
673
- }
674
- }
675
- }
622
+ while_let_on_iterator:: check_while_let_on_iterator ( cx, expr) ;
676
623
677
624
if let Some ( ( cond, body) ) = higher:: while_loop ( & expr) {
678
625
infinite_loop:: check_infinite_loop ( cx, cond, body) ;
@@ -693,7 +640,7 @@ fn check_for_loop<'tcx>(
693
640
let is_manual_memcpy_triggered = manual_memcpy:: detect_manual_memcpy ( cx, pat, arg, body, expr) ;
694
641
if !is_manual_memcpy_triggered {
695
642
for_loop_range:: check_for_loop_range ( cx, pat, arg, body, expr) ;
696
- for_loop_explicit_counter :: check_for_loop_explicit_counter ( cx, pat, arg, body, expr) ;
643
+ explicit_counter_loop :: check_for_loop_explicit_counter ( cx, pat, arg, body, expr) ;
697
644
}
698
645
for_loop_arg:: check_for_loop_arg ( cx, pat, arg, expr) ;
699
646
for_loop_over_map_kv:: check_for_loop_over_map_kv ( cx, pat, arg, body, expr) ;
@@ -773,61 +720,6 @@ impl std::ops::Sub<&MinifyingSugg<'static>> for MinifyingSugg<'static> {
773
720
}
774
721
}
775
722
776
- fn is_used_inside < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > , container : & ' tcx Expr < ' _ > ) -> bool {
777
- let def_id = match path_to_local ( expr) {
778
- Some ( id) => id,
779
- None => return false ,
780
- } ;
781
- if let Some ( used_mutably) = mutated_variables ( container, cx) {
782
- if used_mutably. contains ( & def_id) {
783
- return true ;
784
- }
785
- }
786
- false
787
- }
788
-
789
- fn is_iterator_used_after_while_let < ' tcx > ( cx : & LateContext < ' tcx > , iter_expr : & ' tcx Expr < ' _ > ) -> bool {
790
- let def_id = match path_to_local ( iter_expr) {
791
- Some ( id) => id,
792
- None => return false ,
793
- } ;
794
- let mut visitor = VarUsedAfterLoopVisitor {
795
- def_id,
796
- iter_expr_id : iter_expr. hir_id ,
797
- past_while_let : false ,
798
- var_used_after_while_let : false ,
799
- } ;
800
- if let Some ( enclosing_block) = get_enclosing_block ( cx, def_id) {
801
- walk_block ( & mut visitor, enclosing_block) ;
802
- }
803
- visitor. var_used_after_while_let
804
- }
805
-
806
- struct VarUsedAfterLoopVisitor {
807
- def_id : HirId ,
808
- iter_expr_id : HirId ,
809
- past_while_let : bool ,
810
- var_used_after_while_let : bool ,
811
- }
812
-
813
- impl < ' tcx > Visitor < ' tcx > for VarUsedAfterLoopVisitor {
814
- type Map = Map < ' tcx > ;
815
-
816
- fn visit_expr ( & mut self , expr : & ' tcx Expr < ' _ > ) {
817
- if self . past_while_let {
818
- if path_to_local_id ( expr, self . def_id ) {
819
- self . var_used_after_while_let = true ;
820
- }
821
- } else if self . iter_expr_id == expr. hir_id {
822
- self . past_while_let = true ;
823
- }
824
- walk_expr ( self , expr) ;
825
- }
826
- fn nested_visit_map ( & mut self ) -> NestedVisitorMap < Self :: Map > {
827
- NestedVisitorMap :: None
828
- }
829
- }
830
-
831
723
/// If a block begins with a statement (possibly a `let` binding) and has an
832
724
/// expression, return it.
833
725
fn extract_expr_from_first_stmt < ' tcx > ( block : & Block < ' tcx > ) -> Option < & ' tcx Expr < ' tcx > > {
@@ -863,53 +755,3 @@ fn is_simple_break_expr(expr: &Expr<'_>) -> bool {
863
755
_ => false ,
864
756
}
865
757
}
866
-
867
- fn is_nested ( cx : & LateContext < ' _ > , match_expr : & Expr < ' _ > , iter_expr : & Expr < ' _ > ) -> bool {
868
- if_chain ! {
869
- if let Some ( loop_block) = get_enclosing_block( cx, match_expr. hir_id) ;
870
- let parent_node = cx. tcx. hir( ) . get_parent_node( loop_block. hir_id) ;
871
- if let Some ( Node :: Expr ( loop_expr) ) = cx. tcx. hir( ) . find( parent_node) ;
872
- then {
873
- return is_loop_nested( cx, loop_expr, iter_expr)
874
- }
875
- }
876
- false
877
- }
878
-
879
- fn is_loop_nested ( cx : & LateContext < ' _ > , loop_expr : & Expr < ' _ > , iter_expr : & Expr < ' _ > ) -> bool {
880
- let mut id = loop_expr. hir_id ;
881
- let iter_id = if let Some ( id) = path_to_local ( iter_expr) {
882
- id
883
- } else {
884
- return true ;
885
- } ;
886
- loop {
887
- let parent = cx. tcx . hir ( ) . get_parent_node ( id) ;
888
- if parent == id {
889
- return false ;
890
- }
891
- match cx. tcx . hir ( ) . find ( parent) {
892
- Some ( Node :: Expr ( expr) ) => {
893
- if let ExprKind :: Loop ( ..) = expr. kind {
894
- return true ;
895
- } ;
896
- } ,
897
- Some ( Node :: Block ( block) ) => {
898
- let mut block_visitor = LoopNestVisitor {
899
- hir_id : id,
900
- iterator : iter_id,
901
- nesting : Nesting :: Unknown ,
902
- } ;
903
- walk_block ( & mut block_visitor, block) ;
904
- if block_visitor. nesting == Nesting :: RuledOut {
905
- return false ;
906
- }
907
- } ,
908
- Some ( Node :: Stmt ( _) ) => ( ) ,
909
- _ => {
910
- return false ;
911
- } ,
912
- }
913
- id = parent;
914
- }
915
- }
0 commit comments