Skip to content

Commit f438dbb

Browse files
bors[bot]Veykril
andauthored
Merge #9860
9860: fix: Fix extract_function tagging params as mut unnecessarily r=Veykril a=Veykril Fixes #9822 bors r+ Co-authored-by: Lukas Wirth <[email protected]>
2 parents 50617ee + 6d960ab commit f438dbb

File tree

1 file changed

+54
-9
lines changed

1 file changed

+54
-9
lines changed

crates/ide_assists/src/handlers/extract_function.rs

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -827,16 +827,21 @@ impl FunctionBody {
827827
.map(|(var, src)| {
828828
let usages = LocalUsages::find_local_usages(ctx, var);
829829
let ty = var.ty(ctx.db());
830+
831+
let defined_outside_parent_loop = container_info
832+
.parent_loop
833+
.as_ref()
834+
.map_or(true, |it| it.text_range().contains_range(src.syntax().text_range()));
835+
830836
let is_copy = ty.is_copy(ctx.db());
831-
Param {
832-
var,
833-
ty,
834-
move_local: container_info.parent_loop.as_ref().map_or(true, |it| {
835-
it.text_range().contains_range(src.syntax().text_range())
836-
}) && !self.has_usages_after_body(&usages),
837-
requires_mut: has_exclusive_usages(ctx, &usages, self),
838-
is_copy,
839-
}
837+
let has_usages = self.has_usages_after_body(&usages);
838+
let requires_mut =
839+
!ty.is_mutable_reference() && has_exclusive_usages(ctx, &usages, self);
840+
// We can move the value into the function call if it's not used after the call,
841+
// if the var is not used but defined outside a loop we are extracting from we can't move it either
842+
// as the function will reuse it in the next iteration.
843+
let move_local = !has_usages && defined_outside_parent_loop;
844+
Param { var, ty, move_local, requires_mut, is_copy }
840845
})
841846
.collect()
842847
}
@@ -4114,6 +4119,46 @@ fn foo() {
41144119
fn $0fun_name(x: &mut i32) {
41154120
*x += 1;
41164121
}
4122+
"#,
4123+
);
4124+
}
4125+
4126+
// regression test for #9822
4127+
#[test]
4128+
fn extract_mut_ref_param_has_no_mut_binding_in_loop() {
4129+
check_assist(
4130+
extract_function,
4131+
r#"
4132+
struct Foo;
4133+
impl Foo {
4134+
fn foo(&mut self) {}
4135+
}
4136+
fn foo() {
4137+
let mut x = Foo;
4138+
while false {
4139+
let y = &mut x;
4140+
$0y.foo();$0
4141+
}
4142+
let z = x;
4143+
}
4144+
"#,
4145+
r#"
4146+
struct Foo;
4147+
impl Foo {
4148+
fn foo(&mut self) {}
4149+
}
4150+
fn foo() {
4151+
let mut x = Foo;
4152+
while false {
4153+
let y = &mut x;
4154+
fun_name(y);
4155+
}
4156+
let z = x;
4157+
}
4158+
4159+
fn $0fun_name(y: &mut Foo) {
4160+
y.foo();
4161+
}
41174162
"#,
41184163
);
41194164
}

0 commit comments

Comments
 (0)