@@ -631,20 +631,45 @@ pub fn can_mut_borrow_both(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>) -
631631
632632/// Checks if the top level expression can be moved into a closure as is.
633633/// Currently checks for:
634- /// * Break/Continue outside the given jump targets
634+ /// * Break/Continue outside the given loop HIR ids.
635635/// * Yield/Return statments.
636- /// * Inline assembly
636+ /// * Inline assembly.
637637/// * Usages of a field of a local where the type of the local can be partially moved.
638+ ///
639+ /// For example, given the following function:
640+ ///
641+ /// ```
642+ /// fn f<'a>(iter: &mut impl Iterator<Item = (usize, &'a mut String)>) {
643+ /// for item in iter {
644+ /// let s = item.1;
645+ /// if item.0 > 10 {
646+ /// continue;
647+ /// } else {
648+ /// s.clear();
649+ /// }
650+ /// }
651+ /// }
652+ /// ```
653+ ///
654+ /// When called on the expression `item.0` this will return false unless the local `item` is in the
655+ /// `ignore_locals` set. The type `(usize, &mut String)` can have the second element moved, so it
656+ /// isn't always safe to move into a closure when only a single field is needed.
657+ ///
658+ /// When called on the `continue` expression this will return false unless the outer loop expression
659+ /// is in the `loop_ids` set.
660+ ///
661+ /// Note that this check is not recursive, so passing the `if` expression will always return true
662+ /// even though sub-expressions might return false.
638663pub fn can_move_expr_to_closure_no_visit (
639664 cx : & LateContext < ' tcx > ,
640665 expr : & ' tcx Expr < ' _ > ,
641- jump_targets : & [ HirId ] ,
666+ loop_ids : & [ HirId ] ,
642667 ignore_locals : & HirIdSet ,
643668) -> bool {
644669 match expr. kind {
645670 ExprKind :: Break ( Destination { target_id : Ok ( id) , .. } , _)
646671 | ExprKind :: Continue ( Destination { target_id : Ok ( id) , .. } )
647- if jump_targets . contains ( & id) =>
672+ if loop_ids . contains ( & id) =>
648673 {
649674 true
650675 } ,
0 commit comments