@@ -827,16 +827,21 @@ impl FunctionBody {
827
827
. map ( |( var, src) | {
828
828
let usages = LocalUsages :: find_local_usages ( ctx, var) ;
829
829
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
+
830
836
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 }
840
845
} )
841
846
. collect ( )
842
847
}
@@ -4114,6 +4119,46 @@ fn foo() {
4114
4119
fn $0fun_name(x: &mut i32) {
4115
4120
*x += 1;
4116
4121
}
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
+ }
4117
4162
"# ,
4118
4163
) ;
4119
4164
}
0 commit comments