-fn is_nested(cx: &LateContext<'_>, match_expr: &Expr<'_>, iter_expr: &Expr<'_>) -> bool {
- if_chain! {
- if let Some(loop_block) = get_enclosing_block(cx, match_expr.hir_id);
- let parent_node = cx.tcx.hir().get_parent_node(loop_block.hir_id);
- if let Some(Node::Expr(loop_expr)) = cx.tcx.hir().find(parent_node);
- then {
- return is_loop_nested(cx, loop_expr, iter_expr)
- }
+/// Checks if the given expression is the same field as, is a child of, or is the parent of the
+/// given field. Used to check if the expression can be used while the given field is borrowed
+/// mutably. e.g. if checking for `x.y`, then `x.y`, `x.y.z`, and `x` will all return true, but
+/// `x.z`, and `y` will return false.
+fn is_expr_same_child_or_parent_field(cx: &LateContext<'_>, expr: &Expr<'_>, fields: &[Symbol], path_res: Res) -> bool {
+ match expr.kind {
+ ExprKind::Field(base, name) => {
+ if let Some((head_field, tail_fields)) = fields.split_first() {
+ if name.name == *head_field && is_expr_same_field(cx, base, fields, path_res) {
+ return true;
+ }
+ // Check if the expression is a parent field
+ let mut fields_iter = tail_fields.iter();
+ while let Some(field) = fields_iter.next() {
+ if *field == name.name && is_expr_same_field(cx, base, fields_iter.as_slice(), path_res) {
+ return true;
+ }
+ }
+ }
+
+ // Check if the expression is a child field.
+ let mut e = base;
+ loop {
+ match e.kind {
+ ExprKind::Field(..) if is_expr_same_field(cx, e, fields, path_res) => break true,
+ ExprKind::Field(base, _) | ExprKind::DropTemps(base) | ExprKind::Type(base, _) => e = base,
+ ExprKind::Path(ref path) if fields.is_empty() => {
+ break cx.qpath_res(path, e.hir_id) == path_res;
+ },
+ _ => break false,
+ }
+ }
+ },
+ // If the path matches, this is either an exact match, or the expression is a parent of the field.
+ ExprKind::Path(ref path) => cx.qpath_res(path, expr.hir_id) == path_res,
+ ExprKind::DropTemps(base) | ExprKind::Type(base, _) | ExprKind::AddrOf(_, _, base) => {
+ is_expr_same_child_or_parent_field(cx, base, fields, path_res)
+ },
+ _ => false,