Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions clippy_lints/src/copies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,9 @@ fn scan_block_for_eq<'tcx>(
modifies_any_local(cx, stmt, &cond_locals)
|| !eq_stmts(stmt, blocks, |b| b.stmts.get(i), &mut eq, &mut moved_locals)
})
.map_or(block.stmts.len(), |(i, _)| i);
.map_or(block.stmts.len(), |(i, stmt)| {
adjust_by_closest_callsite(i, stmt, block.stmts[..i].iter().enumerate().rev())
});

if local_needs_ordered_drop {
return BlockEq {
Expand Down Expand Up @@ -467,7 +469,9 @@ fn scan_block_for_eq<'tcx>(
.is_none_or(|s| hash != hash_stmt(cx, s))
})
})
.map_or(block.stmts.len() - start_end_eq, |(i, _)| i);
.map_or(block.stmts.len() - start_end_eq, |(i, stmt)| {
adjust_by_closest_callsite(i, stmt, (0..i).rev().zip(block.stmts[(block.stmts.len() - i)..].iter()))
});

let moved_locals_at_start = moved_locals.len();
let mut i = end_search_start;
Expand Down Expand Up @@ -522,6 +526,49 @@ fn scan_block_for_eq<'tcx>(
}
}

/// Adjusts the index for which the statements begin to differ to the closest macro callsite. This
/// avoids giving suggestions that requires splitting a macro call in half, when only a part of the
/// macro expansion is equal.
///
/// For example, for the following macro:
/// ```rust,ignore
/// macro_rules! foo {
/// ($x:expr) => {
/// let y = 42;
/// $x;
/// };
/// }
/// ```
/// If the macro is called like this:
/// ```rust,ignore
/// if false {
/// let z = 42;
/// foo!(println!("Hello"));
/// } else {
/// let z = 42;
/// foo!(println!("World"));
/// }
/// ```
/// Although the expanded `let y = 42;` is equal, the macro call should not be included in the
/// suggestion.
fn adjust_by_closest_callsite<'tcx>(
i: usize,
stmt: &'tcx Stmt<'tcx>,
mut iter: impl Iterator<Item = (usize, &'tcx Stmt<'tcx>)>,
) -> usize {
let Some((_, first)) = iter.next() else {
return 0;
};

// If it is already at the boundary of a macro call, then just return.
if first.span.source_callsite() != stmt.span.source_callsite() {
return i;
}

iter.find(|(_, stmt)| stmt.span.source_callsite() != first.span.source_callsite())
.map_or(0, |(i, _)| i + 1)
}

fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbol)], if_expr: &Expr<'_>) -> bool {
get_enclosing_block(cx, if_expr.hir_id).is_some_and(|block| {
let ignore_span = block.span.shrink_to_lo().to(if_expr.span);
Expand Down
37 changes: 37 additions & 0 deletions tests/ui/branches_sharing_code/shared_at_bottom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,40 @@ fn fp_if_let_issue7054() {
}

fn main() {}

mod issue14873 {
fn foo() -> i32 {
todo!()
}

macro_rules! qux {
($a:ident, $b:ident, $condition:expr) => {
if $condition {
"."
} else {
""
};
$a = foo();
$b = foo();
};
}

fn share_on_bottom() {
let mut a = 0;
let mut b = 0;
if false {
qux!(a, b, a == b);
} else {
qux!(a, b, a != b);
};

if false {
qux!(a, b, a == b);
let y = 1;
} else {
qux!(a, b, a != b);
let y = 1;
//~^ branches_sharing_code
}
}
}
17 changes: 16 additions & 1 deletion tests/ui/branches_sharing_code/shared_at_bottom.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,20 @@ LL ~ if x == 17 { b = 1; a = 0x99; } else { }
LL + a = 0x99;
|

error: aborting due to 9 previous errors
error: all if blocks contain the same code at the end
--> tests/ui/branches_sharing_code/shared_at_bottom.rs:274:9
|
LL | / let y = 1;
LL | |
LL | | }
| |_________^
|
= warning: some moved values might need to be renamed to avoid wrong references
help: consider moving these statements after the if
|
LL ~ }
LL + let y = 1;
|

error: aborting due to 10 previous errors

31 changes: 31 additions & 0 deletions tests/ui/branches_sharing_code/shared_at_top.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,34 @@ fn pf_local_with_inferred_type_issue7053() {
}

fn main() {}

mod issue14873 {
fn foo() -> i32 {
todo!()
}

macro_rules! qux {
($a:ident, $b:ident, $condition:expr) => {
let $a: i32 = foo();
let $b: i32 = foo();
if $condition { "." } else { "" }
};
}

fn share_on_top() {
if false {
qux!(a, b, a == b);
} else {
qux!(a, b, a != b);
};

if false {
//~^ branches_sharing_code
let x = 1;
qux!(a, b, a == b);
} else {
let x = 1;
qux!(a, b, a != b);
}
}
}
17 changes: 16 additions & 1 deletion tests/ui/branches_sharing_code/shared_at_top.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,20 @@ note: the lint level is defined here
LL | #![deny(clippy::branches_sharing_code, clippy::if_same_then_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 7 previous errors
error: all if blocks contain the same code at the start
--> tests/ui/branches_sharing_code/shared_at_top.rs:148:9
|
LL | / if false {
LL | |
LL | | let x = 1;
| |______________________^
|
= warning: some moved values might need to be renamed to avoid wrong references
help: consider moving these statements before the if
|
LL ~ let x = 1;
LL + if false {
|

error: aborting due to 8 previous errors

39 changes: 39 additions & 0 deletions tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,42 @@ fn added_note_for_expression_use() -> u32 {
}

fn main() {}

mod issue14873 {
fn foo() -> i32 {
todo!()
}

macro_rules! qux {
($a:ident, $b:ident, $condition:expr) => {
let mut $a: i32 = foo();
let mut $b: i32 = foo();
if $condition {
"."
} else {
""
};
$a = foo();
$b = foo();
};
}

fn share_on_top_and_bottom() {
if false {
qux!(a, b, a == b);
} else {
qux!(a, b, a != b);
};

if false {
//~^ branches_sharing_code
let x = 1;
qux!(a, b, a == b);
let y = 1;
} else {
let x = 1;
qux!(a, b, a != b);
let y = 1;
}
}
}
28 changes: 27 additions & 1 deletion tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -159,5 +159,31 @@ LL ~ }
LL + x * 4
|

error: aborting due to 5 previous errors
error: all if blocks contain the same code at both the start and the end
--> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:158:9
|
LL | / if false {
LL | |
LL | | let x = 1;
| |______________________^
|
note: this code is shared at the end
--> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:166:9
|
LL | / let y = 1;
LL | | }
| |_________^
= warning: some moved values might need to be renamed to avoid wrong references
help: consider moving these statements before the if
|
LL ~ let x = 1;
LL + if false {
|
help: consider moving these statements after the if
|
LL ~ }
LL + let y = 1;
|

error: aborting due to 6 previous errors

Loading