From 849c42f60e146aaa7628357101856852c8e7bcdc Mon Sep 17 00:00:00 2001 From: Brumbelow Date: Tue, 21 Apr 2026 11:27:25 -0400 Subject: [PATCH] fix: generate-method skips trait impl blocks when picking insertion site --- .../src/handlers/generate_function.rs | 82 ++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs index 6ef492619b50..e1e456fd5eda 100644 --- a/crates/ide-assists/src/handlers/generate_function.rs +++ b/crates/ide-assists/src/handlers/generate_function.rs @@ -148,7 +148,9 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let enclosing_impl = ctx.find_node_at_offset::(); let cursor_impl = enclosing_impl.filter(|impl_| { - ctx.sema.to_def(impl_).map_or(false, |def| def.self_ty(ctx.sema.db).as_adt() == Some(adt)) + ctx.sema.to_def(impl_).is_some_and(|def| { + def.self_ty(ctx.sema.db).as_adt() == Some(adt) && def.trait_(ctx.sema.db).is_none() + }) }); let (impl_, file) = if let Some(impl_) = cursor_impl { @@ -3239,6 +3241,84 @@ impl Foo { ${0:todo!()} } } +", + ) + } + + #[test] + fn generate_method_skips_trait_impl_for_inherent() { + // regression: rust-lang/rust-analyzer#22123 + check_assist( + generate_function, + r" +struct Bar; + +impl Bar { + fn func1() {} +} + +trait Foo { fn foo(&self); } + +impl Foo for Bar { + fn foo(&self) { + self.func2$0(); + } +} +", + r" +struct Bar; + +impl Bar { + fn func1() {} + + fn func2(&self) ${0:-> _} { + todo!() + } +} + +trait Foo { fn foo(&self); } + +impl Foo for Bar { + fn foo(&self) { + self.func2(); + } +} +", + ) + } + + #[test] + fn generate_method_from_trait_impl_creates_new_inherent_impl() { + // #22123: no inherent impl exists, so the assist must synthesize one + // instead of inserting into the trait impl. + check_assist( + generate_function, + r" +struct Bar; + +trait Foo { fn foo(&self); } + +impl Foo for Bar { + fn foo(&self) { + self.func2$0(); + } +} +", + r" +struct Bar; +impl Bar { + fn func2(&self) ${0:-> _} { + todo!() + } +} + +trait Foo { fn foo(&self); } + +impl Foo for Bar { + fn foo(&self) { + self.func2(); + } +} ", ) }