Skip to content

Commit 5945709

Browse files
committed
Auto merge of rust-lang#16199 - Young-Flash:extract_struct_with_Self, r=Veykril
fix: `extract_struct_from_enum_variant` assist should resolve Self generic arg close rust-lang/rust-analyzer#16197
2 parents 2980d54 + 1a9b1b8 commit 5945709

File tree

1 file changed

+66
-6
lines changed

1 file changed

+66
-6
lines changed

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

+66-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use ide_db::{
66
defs::Definition,
77
helpers::mod_path_to_ast,
88
imports::insert_use::{insert_use, ImportScope, InsertUseConfig},
9+
path_transform::PathTransform,
910
search::FileReference,
1011
FxHashSet, RootDatabase,
1112
};
@@ -105,6 +106,16 @@ pub(crate) fn extract_struct_from_enum_variant(
105106
.generic_param_list()
106107
.and_then(|known_generics| extract_generic_params(&known_generics, &field_list));
107108
let generics = generic_params.as_ref().map(|generics| generics.clone_for_update());
109+
110+
// resolve GenericArg in field_list to actual type
111+
let field_list = field_list.clone_for_update();
112+
if let Some((target_scope, source_scope)) =
113+
ctx.sema.scope(enum_ast.syntax()).zip(ctx.sema.scope(field_list.syntax()))
114+
{
115+
PathTransform::generic_transformation(&target_scope, &source_scope)
116+
.apply(field_list.syntax());
117+
}
118+
108119
let def =
109120
create_struct_def(variant_name.clone(), &variant, &field_list, generics, &enum_ast);
110121

@@ -244,8 +255,6 @@ fn create_struct_def(
244255
// for fields without any existing visibility, use visibility of enum
245256
let field_list: ast::FieldList = match field_list {
246257
Either::Left(field_list) => {
247-
let field_list = field_list.clone_for_update();
248-
249258
if let Some(vis) = &enum_vis {
250259
field_list
251260
.fields()
@@ -254,11 +263,9 @@ fn create_struct_def(
254263
.for_each(|it| insert_vis(it.syntax(), vis.syntax()));
255264
}
256265

257-
field_list.into()
266+
field_list.clone().into()
258267
}
259268
Either::Right(field_list) => {
260-
let field_list = field_list.clone_for_update();
261-
262269
if let Some(vis) = &enum_vis {
263270
field_list
264271
.fields()
@@ -267,7 +274,7 @@ fn create_struct_def(
267274
.for_each(|it| insert_vis(it.syntax(), vis.syntax()));
268275
}
269276

270-
field_list.into()
277+
field_list.clone().into()
271278
}
272279
};
273280
field_list.reindent_to(IndentLevel::single());
@@ -425,6 +432,59 @@ mod tests {
425432

426433
use super::*;
427434

435+
#[test]
436+
fn issue_16197() {
437+
check_assist(
438+
extract_struct_from_enum_variant,
439+
r#"
440+
enum Foo {
441+
Bar $0{ node: Box<Self> },
442+
Nil,
443+
}
444+
"#,
445+
r#"
446+
struct Bar{ node: Box<Foo> }
447+
448+
enum Foo {
449+
Bar(Bar),
450+
Nil,
451+
}
452+
"#,
453+
);
454+
check_assist(
455+
extract_struct_from_enum_variant,
456+
r#"
457+
enum Foo {
458+
Bar $0{ node: Box<Self>, a: Arc<Box<Self>> },
459+
Nil,
460+
}
461+
"#,
462+
r#"
463+
struct Bar{ node: Box<Foo>, a: Arc<Box<Foo>> }
464+
465+
enum Foo {
466+
Bar(Bar),
467+
Nil,
468+
}
469+
"#,
470+
);
471+
check_assist(
472+
extract_struct_from_enum_variant,
473+
r#"
474+
enum Foo {
475+
Nil(Box$0<Self>, Arc<Box<Self>>),
476+
}
477+
"#,
478+
r#"
479+
struct Nil(Box<Foo>, Arc<Box<Foo>>);
480+
481+
enum Foo {
482+
Nil(Nil),
483+
}
484+
"#,
485+
);
486+
}
487+
428488
#[test]
429489
fn test_extract_struct_several_fields_tuple() {
430490
check_assist(

0 commit comments

Comments
 (0)