@@ -49,63 +49,72 @@ impl MapWithUnusedArgumentOverRanges {
49
49
50
50
impl_lint_pass ! ( MapWithUnusedArgumentOverRanges => [ MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES ] ) ;
51
51
52
+ fn extract_count_with_applicability (
53
+ cx : & LateContext < ' _ > ,
54
+ range : higher:: Range < ' _ > ,
55
+ applicability : & mut Applicability ,
56
+ ) -> Option < String > {
57
+ let start = range. start ?;
58
+ let end = range. end ?;
59
+ // TODO: This doens't handle if either the start or end are negative literals, or if the start is
60
+ // not a literal In the first case, we need to be careful about how we handle computing the
61
+ // count to avoid overflows. In the second, we may need to add parenthesis to make the
62
+ // suggestion correct.
63
+ if let ExprKind :: Lit ( lit) = start. kind
64
+ && let LitKind :: Int ( Pu128 ( lower_bound) , _) = lit. node
65
+ {
66
+ if let ExprKind :: Lit ( lit) = end. kind
67
+ && let LitKind :: Int ( Pu128 ( upper_bound) , _) = lit. node
68
+ {
69
+ let count = if range. limits == RangeLimits :: Closed {
70
+ upper_bound - lower_bound + 1
71
+ } else {
72
+ upper_bound - lower_bound
73
+ } ;
74
+ return Some ( format ! ( "{count}" ) ) ;
75
+ } else {
76
+ let end_snippet = snippet_with_applicability ( cx, end. span , "..." , applicability) . into_owned ( ) ;
77
+ if lower_bound == 0 {
78
+ if range. limits == RangeLimits :: Closed {
79
+ return Some ( format ! ( "{end_snippet} + 1" ) ) ;
80
+ } else {
81
+ return Some ( end_snippet) ;
82
+ } ;
83
+ } else if range. limits == RangeLimits :: Closed {
84
+ return Some ( format ! ( "{} + {}" , end_snippet, lower_bound + 1 ) ) ;
85
+ } else {
86
+ return Some ( format ! ( "{} + {}" , end_snippet, lower_bound) ) ;
87
+ } ;
88
+ }
89
+ }
90
+ None
91
+ }
92
+
52
93
impl LateLintPass < ' _ > for MapWithUnusedArgumentOverRanges {
53
94
fn check_expr ( & mut self , cx : & LateContext < ' _ > , ex : & Expr < ' _ > ) {
54
95
if !self . msrv . meets ( msrvs:: REPEAT_WITH ) {
55
96
return ;
56
97
}
98
+ let mut applicability = Applicability :: MaybeIncorrect ;
57
99
if let ExprKind :: MethodCall ( path, receiver, [ map_arg_expr] , _call_span) = ex. kind
58
100
&& path. ident . name == rustc_span:: sym:: map
59
- && let Some ( higher:: Range {
60
- start : Some ( start) ,
61
- end : Some ( end) ,
62
- limits,
63
- } ) = higher:: Range :: hir ( receiver)
101
+ && let Some ( range) = higher:: Range :: hir ( receiver)
64
102
&& let ExprKind :: Closure ( Closure { body, .. } ) = map_arg_expr. kind
65
103
&& let Body { params : [ param] , .. } = cx. tcx . hir ( ) . body ( * body)
66
104
&& matches ! ( param. pat. kind, PatKind :: Wild )
67
- && let ExprKind :: Lit ( lit) = start. kind
68
- && let LitKind :: Int ( Pu128 ( lower_bound) , _) = lit. node
105
+ && let Some ( count) = extract_count_with_applicability ( cx, range, & mut applicability)
69
106
{
70
- if let ExprKind :: Lit ( lit) = end. kind
71
- && let LitKind :: Int ( Pu128 ( upper_bound) , _) = lit. node
72
- {
73
- let count = if limits == RangeLimits :: Closed {
74
- upper_bound - lower_bound + 1
75
- } else {
76
- upper_bound - lower_bound
77
- } ;
78
- let mut applicability = Applicability :: MaybeIncorrect ;
79
- let snippet = snippet_with_applicability ( cx, map_arg_expr. span , "|| { ... }" , & mut applicability)
80
- . replacen ( "|_|" , "||" , 1 ) ;
81
- span_lint_and_sugg (
82
- cx,
83
- MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES ,
84
- ex. span ,
85
- "map of a trivial closure (not dependent on parameter) over a range" ,
86
- "use" ,
87
- format ! ( "std::iter::repeat_with({snippet}).take({count})" ) ,
88
- applicability,
89
- ) ;
90
- } else if lower_bound == 0 {
91
- let mut applicability = Applicability :: MaybeIncorrect ;
92
- let count = if limits == RangeLimits :: Closed {
93
- snippet_with_applicability ( cx, end. span , "..." , & mut applicability) + " + 1"
94
- } else {
95
- snippet_with_applicability ( cx, end. span , "..." , & mut applicability)
96
- } ;
97
- let snippet = snippet_with_applicability ( cx, map_arg_expr. span , "|| { ... }" , & mut applicability)
98
- . replacen ( "|_|" , "||" , 1 ) ;
99
- span_lint_and_sugg (
100
- cx,
101
- MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES ,
102
- ex. span ,
103
- "map of a trivial closure (not dependent on parameter) over a range" ,
104
- "use" ,
105
- format ! ( "std::iter::repeat_with({snippet}).take({count})" ) ,
106
- applicability,
107
- ) ;
108
- }
107
+ let snippet = snippet_with_applicability ( cx, map_arg_expr. span , "|| { ... }" , & mut applicability)
108
+ . replacen ( "|_|" , "||" , 1 ) ;
109
+ span_lint_and_sugg (
110
+ cx,
111
+ MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES ,
112
+ ex. span ,
113
+ "map of a trivial closure (not dependent on parameter) over a range" ,
114
+ "use" ,
115
+ format ! ( "std::iter::repeat_with({snippet}).take({count})" ) ,
116
+ applicability,
117
+ ) ;
109
118
}
110
119
}
111
120
extract_msrv_attr ! ( LateContext ) ;
0 commit comments