@@ -49,63 +49,72 @@ impl MapWithUnusedArgumentOverRanges {
4949
5050impl_lint_pass ! ( MapWithUnusedArgumentOverRanges => [ MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES ] ) ;
5151
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+
5293impl LateLintPass < ' _ > for MapWithUnusedArgumentOverRanges {
5394 fn check_expr ( & mut self , cx : & LateContext < ' _ > , ex : & Expr < ' _ > ) {
5495 if !self . msrv . meets ( msrvs:: REPEAT_WITH ) {
5596 return ;
5697 }
98+ let mut applicability = Applicability :: MaybeIncorrect ;
5799 if let ExprKind :: MethodCall ( path, receiver, [ map_arg_expr] , _call_span) = ex. kind
58100 && 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)
64102 && let ExprKind :: Closure ( Closure { body, .. } ) = map_arg_expr. kind
65103 && let Body { params : [ param] , .. } = cx. tcx . hir ( ) . body ( * body)
66104 && 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)
69106 {
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+ ) ;
109118 }
110119 }
111120 extract_msrv_attr ! ( LateContext ) ;
0 commit comments