Skip to content

Commit fe5f91e

Browse files
Don't add reference when it isn't needed for the "Extract variable" assist
I.e. don't generate `let var_name = &foo()`. Anything that creates a new value don't need a reference. That excludes mostly field accesses and indexing. I had a thought that we can also not generate a reference for fields and indexing as long as the type is `Copy`, but sometimes people impl `Copy` even when they don't want to copy the values (e.g. a large type), so I didn't do that.
1 parent 2a7ec0b commit fe5f91e

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

Diff for: src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs

+42-1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,15 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
6767
ast::Expr::IndexExpr(index) if index.base().as_ref() == Some(&to_extract) => true,
6868
_ => false,
6969
});
70+
let needs_ref = needs_adjust
71+
&& matches!(
72+
to_extract,
73+
ast::Expr::FieldExpr(_)
74+
| ast::Expr::IndexExpr(_)
75+
| ast::Expr::MacroExpr(_)
76+
| ast::Expr::ParenExpr(_)
77+
| ast::Expr::PathExpr(_)
78+
);
7079

7180
let anchor = Anchor::from(&to_extract)?;
7281
let target = to_extract.syntax().text_range();
@@ -93,10 +102,16 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
93102
Some(ast::Expr::RefExpr(expr)) if expr.mut_token().is_some() => {
94103
make::ident_pat(false, true, make::name(&var_name))
95104
}
105+
_ if needs_adjust
106+
&& !needs_ref
107+
&& ty.as_ref().is_some_and(|ty| ty.is_mutable_reference()) =>
108+
{
109+
make::ident_pat(false, true, make::name(&var_name))
110+
}
96111
_ => make::ident_pat(false, false, make::name(&var_name)),
97112
};
98113

99-
let to_extract = match ty.as_ref().filter(|_| needs_adjust) {
114+
let to_extract = match ty.as_ref().filter(|_| needs_ref) {
100115
Some(receiver_type) if receiver_type.is_mutable_reference() => {
101116
make::expr_ref(to_extract, true)
102117
}
@@ -1503,6 +1518,32 @@ fn foo() {
15031518
fn foo() {
15041519
let mut $0var_name = 0;
15051520
let v = &mut var_name;
1521+
}"#,
1522+
);
1523+
}
1524+
1525+
#[test]
1526+
fn generates_no_ref_on_calls() {
1527+
check_assist(
1528+
extract_variable,
1529+
r#"
1530+
struct S;
1531+
impl S {
1532+
fn do_work(&mut self) {}
1533+
}
1534+
fn bar() -> S { S }
1535+
fn foo() {
1536+
$0bar()$0.do_work();
1537+
}"#,
1538+
r#"
1539+
struct S;
1540+
impl S {
1541+
fn do_work(&mut self) {}
1542+
}
1543+
fn bar() -> S { S }
1544+
fn foo() {
1545+
let mut $0bar = bar();
1546+
bar.do_work();
15061547
}"#,
15071548
);
15081549
}

0 commit comments

Comments
 (0)