Skip to content

Commit 0c2e9fe

Browse files
committed
Auto merge of #16752 - Lindronics:destructure-struct-binding, r=Veykril
fix: Don't destructure struct with no public fields Unfortunately I missed this case in #16638. If a struct only has private members, the assist should not be applicable. Though valid syntax exists (`Foo { .. }`), it isn't particularly useful. Since this case applies to a lot of common types (`Arc`, `Vec`, ...), it probably makes the most sense to hide the action. As a side effect, this also disables the action for unit structs, where it also isn't particularly useful. I'd be open to changing it though if you think it makes more sense to keep it. This also fixes the `make::record_pat_field_list` function to produce valid syntax if the field list is empty, as it is used in other places too. ## Current behaviour ```rust // In crate `other_crate` pub struct Foo { bar: i32 } // In current crate fn do_something(foo: other_crate::Foo) {} // Becomes fn do_something(other_crate::Foo { , .. }: other_crate::Foo) {} ``` ## Fixed behaviour Assist should not be applicable in this case anymore.
2 parents 58e10c7 + 2a4ba42 commit 0c2e9fe

File tree

2 files changed

+23
-9
lines changed

2 files changed

+23
-9
lines changed

crates/ide-assists/src/handlers/destructure_struct_binding.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option<Str
107107
let visible_fields =
108108
fields.into_iter().filter(|field| field.is_visible_from(ctx.db(), module)).collect_vec();
109109

110+
if visible_fields.is_empty() {
111+
return None;
112+
}
113+
110114
let has_private_members =
111115
(is_non_exhaustive && is_foreign_crate) || visible_fields.len() < n_fields;
112116

@@ -413,7 +417,7 @@ mod tests {
413417

414418
#[test]
415419
fn unit_struct() {
416-
check_assist(
420+
check_assist_not_applicable(
417421
destructure_struct_binding,
418422
r#"
419423
struct Foo;
@@ -422,13 +426,6 @@ mod tests {
422426
let $0foo = Foo;
423427
}
424428
"#,
425-
r#"
426-
struct Foo;
427-
428-
fn main() {
429-
let Foo = Foo;
430-
}
431-
"#,
432429
)
433430
}
434431

@@ -739,4 +736,18 @@ mod tests {
739736
"#,
740737
)
741738
}
739+
740+
#[test]
741+
fn record_struct_no_public_members() {
742+
check_assist_not_applicable(
743+
destructure_struct_binding,
744+
r#"
745+
//- /lib.rs crate:dep
746+
pub struct Foo { bar: i32, baz: i32 };
747+
748+
//- /main.rs crate:main deps:dep
749+
fn main($0foo: dep::Foo) {}
750+
"#,
751+
)
752+
}
742753
}

crates/syntax/src/ast/make.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,10 @@ pub fn record_pat_field_list(
724724
) -> ast::RecordPatFieldList {
725725
let mut fields = fields.into_iter().join(", ");
726726
if let Some(rest_pat) = rest_pat {
727-
format_to!(fields, ", {rest_pat}");
727+
if !fields.is_empty() {
728+
fields.push_str(", ");
729+
}
730+
format_to!(fields, "{rest_pat}");
728731
}
729732
ast_from_text(&format!("fn f(S {{ {fields} }}: ()))"))
730733
}

0 commit comments

Comments
 (0)