1 mod empty_loop; 2 mod explicit_counter_loop; 3 mod explicit_into_iter_loop; 4 mod explicit_iter_loop; 5 mod for_kv_map; 6 mod iter_next_loop; 7 mod manual_find; 8 mod manual_flatten; 9 mod manual_memcpy; 10 mod manual_while_let_some; 11 mod missing_spin_loop; 12 mod mut_range_bound; 13 mod needless_range_loop; 14 mod never_loop; 15 mod same_item_push; 16 mod single_element_loop; 17 mod utils; 18 mod while_immutable_condition; 19 mod while_let_loop; 20 mod while_let_on_iterator; 21 22 use clippy_utils::higher; 23 use clippy_utils::msrvs::Msrv; 24 use rustc_hir::{Expr, ExprKind, LoopSource, Pat}; 25 use rustc_lint::{LateContext, LateLintPass}; 26 use rustc_session::{declare_tool_lint, impl_lint_pass}; 27 use rustc_span::source_map::Span; 28 use utils::{make_iterator_snippet, IncrementVisitor, InitializeVisitor}; 29 30 declare_clippy_lint! { 31 /// ### What it does 32 /// Checks for for-loops that manually copy items between 33 /// slices that could be optimized by having a memcpy. 34 /// 35 /// ### Why is this bad? 36 /// It is not as fast as a memcpy. 37 /// 38 /// ### Example 39 /// ```rust 40 /// # let src = vec![1]; 41 /// # let mut dst = vec![0; 65]; 42 /// for i in 0..src.len() { 43 /// dst[i + 64] = src[i]; 44 /// } 45 /// ``` 46 /// 47 /// Use instead: 48 /// ```rust 49 /// # let src = vec![1]; 50 /// # let mut dst = vec![0; 65]; 51 /// dst[64..(src.len() + 64)].clone_from_slice(&src[..]); 52 /// ``` 53 #[clippy::version = "pre 1.29.0"] 54 pub MANUAL_MEMCPY, 55 perf, 56 "manually copying items between slices" 57 } 58 59 declare_clippy_lint! { 60 /// ### What it does 61 /// Checks for looping over the range of `0..len` of some 62 /// collection just to get the values by index. 63 /// 64 /// ### Why is this bad? 65 /// Just iterating the collection itself makes the intent 66 /// more clear and is probably faster because it eliminates 67 /// the bounds check that is done when indexing. 68 /// 69 /// ### Example 70 /// ```rust 71 /// let vec = vec!['a', 'b', 'c']; 72 /// for i in 0..vec.len() { 73 /// println!("{}", vec[i]); 74 /// } 75 /// ``` 76 /// 77 /// Use instead: 78 /// ```rust 79 /// let vec = vec!['a', 'b', 'c']; 80 /// for i in vec { 81 /// println!("{}", i); 82 /// } 83 /// ``` 84 #[clippy::version = "pre 1.29.0"] 85 pub NEEDLESS_RANGE_LOOP, 86 style, 87 "for-looping over a range of indices where an iterator over items would do" 88 } 89 90 declare_clippy_lint! { 91 /// ### What it does 92 /// Checks for loops on `x.iter()` where `&x` will do, and 93 /// suggests the latter. 94 /// 95 /// ### Why is this bad? 96 /// Readability. 97 /// 98 /// ### Known problems 99 /// False negatives. We currently only warn on some known 100 /// types. 101 /// 102 /// ### Example 103 /// ```rust 104 /// // with `y` a `Vec` or slice: 105 /// # let y = vec![1]; 106 /// for x in y.iter() { 107 /// // .. 108 /// } 109 /// ``` 110 /// 111 /// Use instead: 112 /// ```rust 113 /// # let y = vec![1]; 114 /// for x in &y { 115 /// // .. 116 /// } 117 /// ``` 118 #[clippy::version = "pre 1.29.0"] 119 pub EXPLICIT_ITER_LOOP, 120 pedantic, 121 "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do" 122 } 123 124 declare_clippy_lint! { 125 /// ### What it does 126 /// Checks for loops on `y.into_iter()` where `y` will do, and 127 /// suggests the latter. 128 /// 129 /// ### Why is this bad? 130 /// Readability. 131 /// 132 /// ### Example 133 /// ```rust 134 /// # let y = vec![1]; 135 /// // with `y` a `Vec` or slice: 136 /// for x in y.into_iter() { 137 /// // .. 138 /// } 139 /// ``` 140 /// can be rewritten to 141 /// ```rust 142 /// # let y = vec![1]; 143 /// for x in y { 144 /// // .. 145 /// } 146 /// ``` 147 #[clippy::version = "pre 1.29.0"] 148 pub EXPLICIT_INTO_ITER_LOOP, 149 pedantic, 150 "for-looping over `_.into_iter()` when `_` would do" 151 } 152 153 declare_clippy_lint! { 154 /// ### What it does 155 /// Checks for loops on `x.next()`. 156 /// 157 /// ### Why is this bad? 158 /// `next()` returns either `Some(value)` if there was a 159 /// value, or `None` otherwise. The insidious thing is that `Option<_>` 160 /// implements `IntoIterator`, so that possibly one value will be iterated, 161 /// leading to some hard to find bugs. No one will want to write such code 162 /// [except to win an Underhanded Rust 163 /// Contest](https://www.reddit.com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr). 164 /// 165 /// ### Example 166 /// ```ignore 167 /// for x in y.next() { 168 /// .. 169 /// } 170 /// ``` 171 #[clippy::version = "pre 1.29.0"] 172 pub ITER_NEXT_LOOP, 173 correctness, 174 "for-looping over `_.next()` which is probably not intended" 175 } 176 177 declare_clippy_lint! { 178 /// ### What it does 179 /// Detects `loop + match` combinations that are easier 180 /// written as a `while let` loop. 181 /// 182 /// ### Why is this bad? 183 /// The `while let` loop is usually shorter and more 184 /// readable. 185 /// 186 /// ### Known problems 187 /// Sometimes the wrong binding is displayed ([#383](https://github.com/rust-lang/rust-clippy/issues/383)). 188 /// 189 /// ### Example 190 /// ```rust,no_run 191 /// # let y = Some(1); 192 /// loop { 193 /// let x = match y { 194 /// Some(x) => x, 195 /// None => break, 196 /// }; 197 /// // .. do something with x 198 /// } 199 /// // is easier written as 200 /// while let Some(x) = y { 201 /// // .. do something with x 202 /// }; 203 /// ``` 204 #[clippy::version = "pre 1.29.0"] 205 pub WHILE_LET_LOOP, 206 complexity, 207 "`loop { if let { ... } else break }`, which can be written as a `while let` loop" 208 } 209 210 declare_clippy_lint! { 211 /// ### What it does 212 /// Checks `for` loops over slices with an explicit counter 213 /// and suggests the use of `.enumerate()`. 214 /// 215 /// ### Why is this bad? 216 /// Using `.enumerate()` makes the intent more clear, 217 /// declutters the code and may be faster in some instances. 218 /// 219 /// ### Example 220 /// ```rust 221 /// # let v = vec![1]; 222 /// # fn bar(bar: usize, baz: usize) {} 223 /// let mut i = 0; 224 /// for item in &v { 225 /// bar(i, *item); 226 /// i += 1; 227 /// } 228 /// ``` 229 /// 230 /// Use instead: 231 /// ```rust 232 /// # let v = vec![1]; 233 /// # fn bar(bar: usize, baz: usize) {} 234 /// for (i, item) in v.iter().enumerate() { bar(i, *item); } 235 /// ``` 236 #[clippy::version = "pre 1.29.0"] 237 pub EXPLICIT_COUNTER_LOOP, 238 complexity, 239 "for-looping with an explicit counter when `_.enumerate()` would do" 240 } 241 242 declare_clippy_lint! { 243 /// ### What it does 244 /// Checks for empty `loop` expressions. 245 /// 246 /// ### Why is this bad? 247 /// These busy loops burn CPU cycles without doing 248 /// anything. It is _almost always_ a better idea to `panic!` than to have 249 /// a busy loop. 250 /// 251 /// If panicking isn't possible, think of the environment and either: 252 /// - block on something 253 /// - sleep the thread for some microseconds 254 /// - yield or pause the thread 255 /// 256 /// For `std` targets, this can be done with 257 /// [`std::thread::sleep`](https://doc.rust-lang.org/std/thread/fn.sleep.html) 258 /// or [`std::thread::yield_now`](https://doc.rust-lang.org/std/thread/fn.yield_now.html). 259 /// 260 /// For `no_std` targets, doing this is more complicated, especially because 261 /// `#[panic_handler]`s can't panic. To stop/pause the thread, you will 262 /// probably need to invoke some target-specific intrinsic. Examples include: 263 /// - [`x86_64::instructions::hlt`](https://docs.rs/x86_64/0.12.2/x86_64/instructions/fn.hlt.html) 264 /// - [`cortex_m::asm::wfi`](https://docs.rs/cortex-m/0.6.3/cortex_m/asm/fn.wfi.html) 265 /// 266 /// ### Example 267 /// ```no_run 268 /// loop {} 269 /// ``` 270 #[clippy::version = "pre 1.29.0"] 271 pub EMPTY_LOOP, 272 suspicious, 273 "empty `loop {}`, which should block or sleep" 274 } 275 276 declare_clippy_lint! { 277 /// ### What it does 278 /// Checks for `while let` expressions on iterators. 279 /// 280 /// ### Why is this bad? 281 /// Readability. A simple `for` loop is shorter and conveys 282 /// the intent better. 283 /// 284 /// ### Example 285 /// ```ignore 286 /// while let Some(val) = iter.next() { 287 /// .. 288 /// } 289 /// ``` 290 /// 291 /// Use instead: 292 /// ```ignore 293 /// for val in &mut iter { 294 /// .. 295 /// } 296 /// ``` 297 #[clippy::version = "pre 1.29.0"] 298 pub WHILE_LET_ON_ITERATOR, 299 style, 300 "using a `while let` loop instead of a for loop on an iterator" 301 } 302 303 declare_clippy_lint! { 304 /// ### What it does 305 /// Checks for iterating a map (`HashMap` or `BTreeMap`) and 306 /// ignoring either the keys or values. 307 /// 308 /// ### Why is this bad? 309 /// Readability. There are `keys` and `values` methods that 310 /// can be used to express that don't need the values or keys. 311 /// 312 /// ### Example 313 /// ```ignore 314 /// for (k, _) in &map { 315 /// .. 316 /// } 317 /// ``` 318 /// 319 /// could be replaced by 320 /// 321 /// ```ignore 322 /// for k in map.keys() { 323 /// .. 324 /// } 325 /// ``` 326 #[clippy::version = "pre 1.29.0"] 327 pub FOR_KV_MAP, 328 style, 329 "looping on a map using `iter` when `keys` or `values` would do" 330 } 331 332 declare_clippy_lint! { 333 /// ### What it does 334 /// Checks for loops that will always `break`, `return` or 335 /// `continue` an outer loop. 336 /// 337 /// ### Why is this bad? 338 /// This loop never loops, all it does is obfuscating the 339 /// code. 340 /// 341 /// ### Example 342 /// ```rust 343 /// loop { 344 /// ..; 345 /// break; 346 /// } 347 /// ``` 348 #[clippy::version = "pre 1.29.0"] 349 pub NEVER_LOOP, 350 correctness, 351 "any loop that will always `break` or `return`" 352 } 353 354 declare_clippy_lint! { 355 /// ### What it does 356 /// Checks for loops which have a range bound that is a mutable variable 357 /// 358 /// ### Why is this bad? 359 /// One might think that modifying the mutable variable changes the loop bounds 360 /// 361 /// ### Known problems 362 /// False positive when mutation is followed by a `break`, but the `break` is not immediately 363 /// after the mutation: 364 /// 365 /// ```rust 366 /// let mut x = 5; 367 /// for _ in 0..x { 368 /// x += 1; // x is a range bound that is mutated 369 /// ..; // some other expression 370 /// break; // leaves the loop, so mutation is not an issue 371 /// } 372 /// ``` 373 /// 374 /// False positive on nested loops ([#6072](https://github.com/rust-lang/rust-clippy/issues/6072)) 375 /// 376 /// ### Example 377 /// ```rust 378 /// let mut foo = 42; 379 /// for i in 0..foo { 380 /// foo -= 1; 381 /// println!("{}", i); // prints numbers from 0 to 42, not 0 to 21 382 /// } 383 /// ``` 384 #[clippy::version = "pre 1.29.0"] 385 pub MUT_RANGE_BOUND, 386 suspicious, 387 "for loop over a range where one of the bounds is a mutable variable" 388 } 389 390 declare_clippy_lint! { 391 /// ### What it does 392 /// Checks whether variables used within while loop condition 393 /// can be (and are) mutated in the body. 394 /// 395 /// ### Why is this bad? 396 /// If the condition is unchanged, entering the body of the loop 397 /// will lead to an infinite loop. 398 /// 399 /// ### Known problems 400 /// If the `while`-loop is in a closure, the check for mutation of the 401 /// condition variables in the body can cause false negatives. For example when only `Upvar` `a` is 402 /// in the condition and only `Upvar` `b` gets mutated in the body, the lint will not trigger. 403 /// 404 /// ### Example 405 /// ```rust 406 /// let i = 0; 407 /// while i > 10 { 408 /// println!("let me loop forever!"); 409 /// } 410 /// ``` 411 #[clippy::version = "pre 1.29.0"] 412 pub WHILE_IMMUTABLE_CONDITION, 413 correctness, 414 "variables used within while expression are not mutated in the body" 415 } 416 417 declare_clippy_lint! { 418 /// ### What it does 419 /// Checks whether a for loop is being used to push a constant 420 /// value into a Vec. 421 /// 422 /// ### Why is this bad? 423 /// This kind of operation can be expressed more succinctly with 424 /// `vec![item; SIZE]` or `vec.resize(NEW_SIZE, item)` and using these alternatives may also 425 /// have better performance. 426 /// 427 /// ### Example 428 /// ```rust 429 /// let item1 = 2; 430 /// let item2 = 3; 431 /// let mut vec: Vec<u8> = Vec::new(); 432 /// for _ in 0..20 { 433 /// vec.push(item1); 434 /// } 435 /// for _ in 0..30 { 436 /// vec.push(item2); 437 /// } 438 /// ``` 439 /// 440 /// Use instead: 441 /// ```rust 442 /// let item1 = 2; 443 /// let item2 = 3; 444 /// let mut vec: Vec<u8> = vec![item1; 20]; 445 /// vec.resize(20 + 30, item2); 446 /// ``` 447 #[clippy::version = "1.47.0"] 448 pub SAME_ITEM_PUSH, 449 style, 450 "the same item is pushed inside of a for loop" 451 } 452 453 declare_clippy_lint! { 454 /// ### What it does 455 /// Checks whether a for loop has a single element. 456 /// 457 /// ### Why is this bad? 458 /// There is no reason to have a loop of a 459 /// single element. 460 /// 461 /// ### Example 462 /// ```rust 463 /// let item1 = 2; 464 /// for item in &[item1] { 465 /// println!("{}", item); 466 /// } 467 /// ``` 468 /// 469 /// Use instead: 470 /// ```rust 471 /// let item1 = 2; 472 /// let item = &item1; 473 /// println!("{}", item); 474 /// ``` 475 #[clippy::version = "1.49.0"] 476 pub SINGLE_ELEMENT_LOOP, 477 complexity, 478 "there is no reason to have a single element loop" 479 } 480 481 declare_clippy_lint! { 482 /// ### What it does 483 /// Checks for unnecessary `if let` usage in a for loop 484 /// where only the `Some` or `Ok` variant of the iterator element is used. 485 /// 486 /// ### Why is this bad? 487 /// It is verbose and can be simplified 488 /// by first calling the `flatten` method on the `Iterator`. 489 /// 490 /// ### Example 491 /// 492 /// ```rust 493 /// let x = vec![Some(1), Some(2), Some(3)]; 494 /// for n in x { 495 /// if let Some(n) = n { 496 /// println!("{}", n); 497 /// } 498 /// } 499 /// ``` 500 /// Use instead: 501 /// ```rust 502 /// let x = vec![Some(1), Some(2), Some(3)]; 503 /// for n in x.into_iter().flatten() { 504 /// println!("{}", n); 505 /// } 506 /// ``` 507 #[clippy::version = "1.52.0"] 508 pub MANUAL_FLATTEN, 509 complexity, 510 "for loops over `Option`s or `Result`s with a single expression can be simplified" 511 } 512 513 declare_clippy_lint! { 514 /// ### What it does 515 /// Checks for empty spin loops 516 /// 517 /// ### Why is this bad? 518 /// The loop body should have something like `thread::park()` or at least 519 /// `std::hint::spin_loop()` to avoid needlessly burning cycles and conserve 520 /// energy. Perhaps even better use an actual lock, if possible. 521 /// 522 /// ### Known problems 523 /// This lint doesn't currently trigger on `while let` or 524 /// `loop { match .. { .. } }` loops, which would be considered idiomatic in 525 /// combination with e.g. `AtomicBool::compare_exchange_weak`. 526 /// 527 /// ### Example 528 /// 529 /// ```ignore 530 /// use core::sync::atomic::{AtomicBool, Ordering}; 531 /// let b = AtomicBool::new(true); 532 /// // give a ref to `b` to another thread,wait for it to become false 533 /// while b.load(Ordering::Acquire) {}; 534 /// ``` 535 /// Use instead: 536 /// ```rust,no_run 537 ///# use core::sync::atomic::{AtomicBool, Ordering}; 538 ///# let b = AtomicBool::new(true); 539 /// while b.load(Ordering::Acquire) { 540 /// std::hint::spin_loop() 541 /// } 542 /// ``` 543 #[clippy::version = "1.61.0"] 544 pub MISSING_SPIN_LOOP, 545 perf, 546 "An empty busy waiting loop" 547 } 548 549 declare_clippy_lint! { 550 /// ### What it does 551 /// Checks for manual implementations of Iterator::find 552 /// 553 /// ### Why is this bad? 554 /// It doesn't affect performance, but using `find` is shorter and easier to read. 555 /// 556 /// ### Example 557 /// 558 /// ```rust 559 /// fn example(arr: Vec<i32>) -> Option<i32> { 560 /// for el in arr { 561 /// if el == 1 { 562 /// return Some(el); 563 /// } 564 /// } 565 /// None 566 /// } 567 /// ``` 568 /// Use instead: 569 /// ```rust 570 /// fn example(arr: Vec<i32>) -> Option<i32> { 571 /// arr.into_iter().find(|&el| el == 1) 572 /// } 573 /// ``` 574 #[clippy::version = "1.64.0"] 575 pub MANUAL_FIND, 576 complexity, 577 "manual implementation of `Iterator::find`" 578 } 579 580 declare_clippy_lint! { 581 /// ### What it does 582 /// Looks for loops that check for emptiness of a `Vec` in the condition and pop an element 583 /// in the body as a separate operation. 584 /// 585 /// ### Why is this bad? 586 /// Such loops can be written in a more idiomatic way by using a while-let loop and directly 587 /// pattern matching on the return value of `Vec::pop()`. 588 /// 589 /// ### Example 590 /// ```rust 591 /// let mut numbers = vec![1, 2, 3, 4, 5]; 592 /// while !numbers.is_empty() { 593 /// let number = numbers.pop().unwrap(); 594 /// // use `number` 595 /// } 596 /// ``` 597 /// Use instead: 598 /// ```rust 599 /// let mut numbers = vec![1, 2, 3, 4, 5]; 600 /// while let Some(number) = numbers.pop() { 601 /// // use `number` 602 /// } 603 /// ``` 604 #[clippy::version = "1.70.0"] 605 pub MANUAL_WHILE_LET_SOME, 606 style, 607 "checking for emptiness of a `Vec` in the loop condition and popping an element in the body" 608 } 609 610 pub struct Loops { 611 msrv: Msrv, 612 } 613 impl Loops { new(msrv: Msrv) -> Self614 pub fn new(msrv: Msrv) -> Self { 615 Self { msrv } 616 } 617 } 618 impl_lint_pass!(Loops => [ 619 MANUAL_MEMCPY, 620 MANUAL_FLATTEN, 621 NEEDLESS_RANGE_LOOP, 622 EXPLICIT_ITER_LOOP, 623 EXPLICIT_INTO_ITER_LOOP, 624 ITER_NEXT_LOOP, 625 WHILE_LET_LOOP, 626 EXPLICIT_COUNTER_LOOP, 627 EMPTY_LOOP, 628 WHILE_LET_ON_ITERATOR, 629 FOR_KV_MAP, 630 NEVER_LOOP, 631 MUT_RANGE_BOUND, 632 WHILE_IMMUTABLE_CONDITION, 633 SAME_ITEM_PUSH, 634 SINGLE_ELEMENT_LOOP, 635 MISSING_SPIN_LOOP, 636 MANUAL_FIND, 637 MANUAL_WHILE_LET_SOME 638 ]); 639 640 impl<'tcx> LateLintPass<'tcx> for Loops { check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>)641 fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { 642 let for_loop = higher::ForLoop::hir(expr); 643 if let Some(higher::ForLoop { 644 pat, 645 arg, 646 body, 647 loop_id, 648 span, 649 }) = for_loop 650 { 651 // we don't want to check expanded macros 652 // this check is not at the top of the function 653 // since higher::for_loop expressions are marked as expansions 654 if body.span.from_expansion() { 655 return; 656 } 657 self.check_for_loop(cx, pat, arg, body, expr, span); 658 if let ExprKind::Block(block, _) = body.kind { 659 never_loop::check(cx, block, loop_id, span, for_loop.as_ref()); 660 } 661 } 662 663 // we don't want to check expanded macros 664 if expr.span.from_expansion() { 665 return; 666 } 667 668 // check for never_loop 669 if let ExprKind::Loop(block, ..) = expr.kind { 670 never_loop::check(cx, block, expr.hir_id, expr.span, None); 671 } 672 673 // check for `loop { if let {} else break }` that could be `while let` 674 // (also matches an explicit "match" instead of "if let") 675 // (even if the "match" or "if let" is used for declaration) 676 if let ExprKind::Loop(block, _, LoopSource::Loop, _) = expr.kind { 677 // also check for empty `loop {}` statements, skipping those in #[panic_handler] 678 empty_loop::check(cx, expr, block); 679 while_let_loop::check(cx, expr, block); 680 } 681 682 while_let_on_iterator::check(cx, expr); 683 684 if let Some(higher::While { condition, body, span }) = higher::While::hir(expr) { 685 while_immutable_condition::check(cx, condition, body); 686 missing_spin_loop::check(cx, condition, body); 687 manual_while_let_some::check(cx, condition, body, span); 688 } 689 } 690 691 extract_msrv_attr!(LateContext); 692 } 693 694 impl Loops { check_for_loop<'tcx>( &self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>, expr: &'tcx Expr<'_>, span: Span, )695 fn check_for_loop<'tcx>( 696 &self, 697 cx: &LateContext<'tcx>, 698 pat: &'tcx Pat<'_>, 699 arg: &'tcx Expr<'_>, 700 body: &'tcx Expr<'_>, 701 expr: &'tcx Expr<'_>, 702 span: Span, 703 ) { 704 let is_manual_memcpy_triggered = manual_memcpy::check(cx, pat, arg, body, expr); 705 if !is_manual_memcpy_triggered { 706 needless_range_loop::check(cx, pat, arg, body, expr); 707 explicit_counter_loop::check(cx, pat, arg, body, expr); 708 } 709 self.check_for_loop_arg(cx, pat, arg); 710 for_kv_map::check(cx, pat, arg, body); 711 mut_range_bound::check(cx, arg, body); 712 single_element_loop::check(cx, pat, arg, body, expr); 713 same_item_push::check(cx, pat, arg, body, expr); 714 manual_flatten::check(cx, pat, arg, body, span); 715 manual_find::check(cx, pat, arg, body, span, expr); 716 } 717 check_for_loop_arg(&self, cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>)718 fn check_for_loop_arg(&self, cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) { 719 if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind { 720 match method.ident.as_str() { 721 "iter" | "iter_mut" => { 722 explicit_iter_loop::check(cx, self_arg, arg, &self.msrv); 723 }, 724 "into_iter" => { 725 explicit_into_iter_loop::check(cx, self_arg, arg); 726 }, 727 "next" => { 728 iter_next_loop::check(cx, arg); 729 }, 730 _ => {}, 731 } 732 } 733 } 734 } 735