Unnamed repository; edit this file 'description' to name the repository.
Fix panic `!self.data().mutable` for destructure_struct_binding
When the reference type does not require adding a dereference or parentheses, it will panic Example --- ```rust struct Foo { bar: i32, baz: i32 } fn main() { let $0foo = &Foo { bar: 1, baz: 2 }; let _ = &foo.bar; } ``` **Before this PR**: Panic: ``` assertion failed: !self.data().mutable ``` **After this PR**: ```rust struct Foo { bar: i32, baz: i32 } fn main() { let Foo { bar, baz } = &Foo { bar: 1, baz: 2 }; let _ = bar; } ```
A4-Tacks 7 months ago
parent b12a129 · commit f34e9ca
-rw-r--r--crates/ide-assists/src/handlers/destructure_struct_binding.rs50
1 files changed, 48 insertions, 2 deletions
diff --git a/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/crates/ide-assists/src/handlers/destructure_struct_binding.rs
index 397327cb4f..5ba2f96c01 100644
--- a/crates/ide-assists/src/handlers/destructure_struct_binding.rs
+++ b/crates/ide-assists/src/handlers/destructure_struct_binding.rs
@@ -288,7 +288,7 @@ fn build_usage_edit(
Some(field_expr) => Some({
let field_name: SmolStr = field_expr.name_ref()?.to_string().into();
let new_field_name = field_names.get(&field_name)?;
- let new_expr = make.expr_path(ast::make::ext::ident_path(new_field_name));
+ let new_expr = ast::make::expr_path(ast::make::ext::ident_path(new_field_name));
// If struct binding is a reference, we might need to deref field usages
if data.is_ref {
@@ -298,7 +298,7 @@ fn build_usage_edit(
ref_data.wrap_expr(new_expr).syntax().clone_for_update(),
)
} else {
- (field_expr.syntax().clone(), new_expr.syntax().clone())
+ (field_expr.syntax().clone(), new_expr.syntax().clone_for_update())
}
}),
None => Some((
@@ -611,6 +611,52 @@ mod tests {
}
#[test]
+ fn ref_not_add_parenthesis_and_deref_record() {
+ check_assist(
+ destructure_struct_binding,
+ r#"
+ struct Foo { bar: i32, baz: i32 }
+
+ fn main() {
+ let $0foo = &Foo { bar: 1, baz: 2 };
+ let _ = &foo.bar;
+ }
+ "#,
+ r#"
+ struct Foo { bar: i32, baz: i32 }
+
+ fn main() {
+ let Foo { bar, baz } = &Foo { bar: 1, baz: 2 };
+ let _ = bar;
+ }
+ "#,
+ )
+ }
+
+ #[test]
+ fn ref_not_add_parenthesis_and_deref_tuple() {
+ check_assist(
+ destructure_struct_binding,
+ r#"
+ struct Foo(i32, i32);
+
+ fn main() {
+ let $0foo = &Foo(1, 2);
+ let _ = &foo.0;
+ }
+ "#,
+ r#"
+ struct Foo(i32, i32);
+
+ fn main() {
+ let Foo(_0, _1) = &Foo(1, 2);
+ let _ = _0;
+ }
+ "#,
+ )
+ }
+
+ #[test]
fn record_struct_name_collision() {
check_assist(
destructure_struct_binding,