@@ -14,6 +14,7 @@ mod clone_on_copy;
14
14
mod clone_on_ref_ptr;
15
15
mod cloned_instead_of_copied;
16
16
mod collapsible_str_replace;
17
+ mod double_ended_iterator_last;
17
18
mod drain_collect;
18
19
mod err_expect;
19
20
mod expect_fun_call;
@@ -4284,6 +4285,32 @@ declare_clippy_lint! {
4284
4285
"map of a trivial closure (not dependent on parameter) over a range"
4285
4286
}
4286
4287
4288
+ declare_clippy_lint ! {
4289
+ /// ### What it does
4290
+ ///
4291
+ /// Checks for `Iterator::last` being called on a `DoubleEndedIterator`, which can be replaced
4292
+ /// with `DoubleEndedIterator::next_back`.
4293
+ ///
4294
+ /// ### Why is this bad?
4295
+ ///
4296
+ /// `Iterator::last` is implemented by consuming the iterator, which is unnecessary if
4297
+ /// the iterator is a `DoubleEndedIterator`. Since Rust traits do not allow specialization,
4298
+ /// `Iterator::last` cannot be optimized for `DoubleEndedIterator`.
4299
+ ///
4300
+ /// ### Example
4301
+ /// ```no_run
4302
+ /// let last_arg = "echo hello world".split(' ').last();
4303
+ /// ```
4304
+ /// Use instead:
4305
+ /// ```no_run
4306
+ /// let last_arg = "echo hello world".split(' ').next_back();
4307
+ /// ```
4308
+ #[ clippy:: version = "1.85.0" ]
4309
+ pub DOUBLE_ENDED_ITERATOR_LAST ,
4310
+ perf,
4311
+ "using `Iterator::last` on a `DoubleEndedIterator`"
4312
+ }
4313
+
4287
4314
pub struct Methods {
4288
4315
avoid_breaking_exported_api : bool ,
4289
4316
msrv : Msrv ,
@@ -4449,6 +4476,7 @@ impl_lint_pass!(Methods => [
4449
4476
MAP_ALL_ANY_IDENTITY ,
4450
4477
MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES ,
4451
4478
UNNECESSARY_MAP_OR ,
4479
+ DOUBLE_ENDED_ITERATOR_LAST ,
4452
4480
] ) ;
4453
4481
4454
4482
/// Extracts a method call name, args, and `Span` of the method name.
@@ -4931,6 +4959,7 @@ impl Methods {
4931
4959
false ,
4932
4960
) ;
4933
4961
}
4962
+ double_ended_iterator_last:: check ( cx, expr, recv, call_span) ;
4934
4963
} ,
4935
4964
( "len" , [ ] ) => {
4936
4965
if let Some ( ( "as_bytes" , prev_recv, [ ] , _, _) ) = method_call ( recv) {
0 commit comments