diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 50da9ed06a0d..ba0a2c0224a0 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -588,6 +588,14 @@ impl Resolver { _ => None, }) } + + pub fn impl_def(&self) -> Option { + self.scopes().find_map(|scope| match scope { + Scope::ImplDefScope(def) => Some(*def), + _ => None, + }) + } + /// `expr_id` is required to be an expression id that comes after the top level expression scope in the given resolver #[must_use] pub fn update_to_inner_scope( diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 46835ec04e01..55c14312071a 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -1556,6 +1556,10 @@ impl SemanticsScope<'_> { pub fn extern_crate_decls(&self) -> impl Iterator + '_ { self.resolver.extern_crate_decls_in_scope(self.db.upcast()) } + + pub fn has_same_self_type(&self, other: &SemanticsScope<'_>) -> bool { + self.resolver.impl_def() == other.resolver.impl_def() + } } #[derive(Debug)] diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index 7a5d3d0859c6..db1e0ceaec1e 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use hir::{self, HasCrate, HasSource, HasVisibility}; +use hir::{self, HasCrate, HasVisibility}; use ide_db::path_transform::PathTransform; use syntax::{ ast::{ @@ -106,11 +106,8 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' target, |edit| { // Create the function - let method_source = match method.source(ctx.db()) { - Some(source) => { - ctx.sema.parse_or_expand(source.file_id); - source.value - } + let method_source = match ctx.sema.source(method) { + Some(source) => source.value, None => return, }; let vis = method_source.visibility(); @@ -187,11 +184,11 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' let assoc_items = impl_def.get_or_create_assoc_item_list(); assoc_items.add_item(f.clone().into()); - PathTransform::generic_transformation( - &ctx.sema.scope(strukt.syntax()).unwrap(), - &ctx.sema.scope(method_source.syntax()).unwrap(), - ) - .apply(f.syntax()); + if let Some((target, source)) = + ctx.sema.scope(strukt.syntax()).zip(ctx.sema.scope(method_source.syntax())) + { + PathTransform::generic_transformation(&target, &source).apply(f.syntax()); + } if let Some(cap) = ctx.config.snippet_cap { edit.add_tabstop_before(cap, f) diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs index 49b990172a54..fb4c0c12691d 100644 --- a/crates/ide-db/src/path_transform.rs +++ b/crates/ide-db/src/path_transform.rs @@ -183,6 +183,7 @@ impl<'a> PathTransform<'a> { lifetime_substs, target_module, source_scope: self.source_scope, + same_self_type: self.target_scope.has_same_self_type(self.source_scope), }; ctx.transform_default_values(defaulted_params); ctx @@ -195,6 +196,7 @@ struct Ctx<'a> { lifetime_substs: FxHashMap, target_module: hir::Module, source_scope: &'a SemanticsScope<'a>, + same_self_type: bool, } fn postorder(item: &SyntaxNode) -> impl Iterator { @@ -333,6 +335,11 @@ impl Ctx<'_> { } } hir::PathResolution::SelfType(imp) => { + // keep Self type if it does not need to be replaced + if self.same_self_type { + return None; + } + let ty = imp.self_ty(self.source_scope.db); let ty_str = &ty .display_source_code( @@ -349,6 +356,7 @@ impl Ctx<'_> { self.source_scope.db.upcast(), ModuleDef::from(adt), false, + true, )?; if let Some(qual) = mod_path_to_ast(&found_path).qualifier() {