mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-24 17:16:25 +00:00
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;
}
```
This commit is contained in:
parent
b12a129347
commit
f34e9ca8d3
1 changed files with 48 additions and 2 deletions
|
|
@ -288,7 +288,7 @@ fn build_usage_edit(
|
||||||
Some(field_expr) => Some({
|
Some(field_expr) => Some({
|
||||||
let field_name: SmolStr = field_expr.name_ref()?.to_string().into();
|
let field_name: SmolStr = field_expr.name_ref()?.to_string().into();
|
||||||
let new_field_name = field_names.get(&field_name)?;
|
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 struct binding is a reference, we might need to deref field usages
|
||||||
if data.is_ref {
|
if data.is_ref {
|
||||||
|
|
@ -298,7 +298,7 @@ fn build_usage_edit(
|
||||||
ref_data.wrap_expr(new_expr).syntax().clone_for_update(),
|
ref_data.wrap_expr(new_expr).syntax().clone_for_update(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(field_expr.syntax().clone(), new_expr.syntax().clone())
|
(field_expr.syntax().clone(), new_expr.syntax().clone_for_update())
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
None => Some((
|
None => Some((
|
||||||
|
|
@ -610,6 +610,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]
|
#[test]
|
||||||
fn record_struct_name_collision() {
|
fn record_struct_name_collision() {
|
||||||
check_assist(
|
check_assist(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue