8186: Lower traits to `TraitRef` instead of `TypeRef` r=matklad a=Veykril



Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2021-03-30 16:45:05 +00:00 committed by GitHub
commit fd7c454d51
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 100 additions and 40 deletions

View file

@ -44,6 +44,7 @@ use hir_def::{
per_ns::PerNs, per_ns::PerNs,
resolver::{HasResolver, Resolver}, resolver::{HasResolver, Resolver},
src::HasSource as _, src::HasSource as _,
type_ref::TraitRef,
AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId,
DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId,
LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
@ -1573,9 +1574,9 @@ impl Impl {
}; };
let filter = |impl_def: &Impl| { let filter = |impl_def: &Impl| {
let target_ty = impl_def.target_ty(db); let self_ty = impl_def.self_ty(db);
let rref = target_ty.remove_ref(); let rref = self_ty.remove_ref();
ty.equals_ctor(rref.as_ref().map_or(&target_ty.ty, |it| &it.ty)) ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
}; };
let mut all = Vec::new(); let mut all = Vec::new();
@ -1613,16 +1614,16 @@ impl Impl {
// FIXME: the return type is wrong. This should be a hir version of // FIXME: the return type is wrong. This should be a hir version of
// `TraitRef` (ie, resolved `TypeRef`). // `TraitRef` (ie, resolved `TypeRef`).
pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { pub fn trait_(self, db: &dyn HirDatabase) -> Option<TraitRef> {
db.impl_data(self.id).target_trait.clone() db.impl_data(self.id).target_trait.clone()
} }
pub fn target_ty(self, db: &dyn HirDatabase) -> Type { pub fn self_ty(self, db: &dyn HirDatabase) -> Type {
let impl_data = db.impl_data(self.id); let impl_data = db.impl_data(self.id);
let resolver = self.id.resolver(db.upcast()); let resolver = self.id.resolver(db.upcast());
let krate = self.id.lookup(db.upcast()).container.krate(); let krate = self.id.lookup(db.upcast()).container.krate();
let ctx = hir_ty::TyLoweringContext::new(db, &resolver); let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
let ty = ctx.lower_ty(&impl_data.target_type); let ty = ctx.lower_ty(&impl_data.self_ty);
Type::new_with_resolver_inner(db, krate, &resolver, ty) Type::new_with_resolver_inner(db, krate, &resolver, ty)
} }

View file

@ -10,7 +10,7 @@ use crate::{
body::Expander, body::Expander,
db::DefDatabase, db::DefDatabase,
item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param},
type_ref::{TypeBound, TypeRef}, type_ref::{TraitRef, TypeBound, TypeRef},
visibility::RawVisibility, visibility::RawVisibility,
AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
@ -156,8 +156,8 @@ impl TraitData {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImplData { pub struct ImplData {
pub target_trait: Option<TypeRef>, pub target_trait: Option<TraitRef>,
pub target_type: TypeRef, pub self_ty: TypeRef,
pub items: Vec<AssocItemId>, pub items: Vec<AssocItemId>,
pub is_negative: bool, pub is_negative: bool,
} }
@ -170,7 +170,7 @@ impl ImplData {
let item_tree = impl_loc.id.item_tree(db); let item_tree = impl_loc.id.item_tree(db);
let impl_def = &item_tree[impl_loc.id.value]; let impl_def = &item_tree[impl_loc.id.value];
let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone());
let target_type = item_tree[impl_def.target_type].clone(); let self_ty = item_tree[impl_def.self_ty].clone();
let is_negative = impl_def.is_negative; let is_negative = impl_def.is_negative;
let module_id = impl_loc.container; let module_id = impl_loc.container;
let container = AssocContainerId::ImplId(id); let container = AssocContainerId::ImplId(id);
@ -187,7 +187,7 @@ impl ImplData {
); );
let items = items.into_iter().map(|(_, item)| item).collect(); let items = items.into_iter().map(|(_, item)| item).collect();
Arc::new(ImplData { target_trait, target_type, items, is_negative }) Arc::new(ImplData { target_trait, self_ty, items, is_negative })
} }
} }

View file

@ -31,7 +31,7 @@ use crate::{
db::DefDatabase, db::DefDatabase,
generics::GenericParams, generics::GenericParams,
path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
type_ref::{Mutability, TypeBound, TypeRef}, type_ref::{Mutability, TraitRef, TypeBound, TypeRef},
visibility::RawVisibility, visibility::RawVisibility,
}; };
@ -147,6 +147,7 @@ impl ItemTree {
vis, vis,
generics, generics,
type_refs, type_refs,
trait_refs,
inner_items, inner_items,
} = &mut **data; } = &mut **data;
@ -173,6 +174,7 @@ impl ItemTree {
generics.arena.shrink_to_fit(); generics.arena.shrink_to_fit();
type_refs.arena.shrink_to_fit(); type_refs.arena.shrink_to_fit();
type_refs.map.shrink_to_fit(); type_refs.map.shrink_to_fit();
trait_refs.map.shrink_to_fit();
inner_items.shrink_to_fit(); inner_items.shrink_to_fit();
} }
@ -295,6 +297,32 @@ impl TypeRefStorage {
} }
} }
/// `TraitRef` interner.
#[derive(Default, Debug, Eq, PartialEq)]
struct TraitRefStorage {
arena: Arena<Arc<TraitRef>>,
map: FxHashMap<Arc<TraitRef>, Idx<Arc<TraitRef>>>,
}
impl TraitRefStorage {
// Note: We lie about the `Idx<TraitRef>` to hide the interner details.
fn intern(&mut self, ty: TraitRef) -> Idx<TraitRef> {
if let Some(id) = self.map.get(&ty) {
return Idx::from_raw(id.into_raw());
}
let ty = Arc::new(ty);
let idx = self.arena.alloc(ty.clone());
self.map.insert(ty, idx);
Idx::from_raw(idx.into_raw())
}
fn lookup(&self, id: Idx<TraitRef>) -> &TraitRef {
&self.arena[Idx::from_raw(id.into_raw())]
}
}
#[derive(Default, Debug, Eq, PartialEq)] #[derive(Default, Debug, Eq, PartialEq)]
struct ItemTreeData { struct ItemTreeData {
imports: Arena<Import>, imports: Arena<Import>,
@ -319,6 +347,7 @@ struct ItemTreeData {
vis: ItemVisibilities, vis: ItemVisibilities,
generics: GenericParamsStorage, generics: GenericParamsStorage,
type_refs: TypeRefStorage, type_refs: TypeRefStorage,
trait_refs: TraitRefStorage,
inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>,
} }
@ -556,6 +585,14 @@ impl Index<Idx<TypeRef>> for ItemTree {
} }
} }
impl Index<Idx<TraitRef>> for ItemTree {
type Output = TraitRef;
fn index(&self, id: Idx<TraitRef>) -> &Self::Output {
self.data().trait_refs.lookup(id)
}
}
impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
type Output = N; type Output = N;
fn index(&self, id: FileItemTreeId<N>) -> &N { fn index(&self, id: FileItemTreeId<N>) -> &N {
@ -692,8 +729,8 @@ pub struct Trait {
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
pub struct Impl { pub struct Impl {
pub generic_params: GenericParamsId, pub generic_params: GenericParamsId,
pub target_trait: Option<Idx<TypeRef>>, pub target_trait: Option<Idx<TraitRef>>,
pub target_type: Idx<TypeRef>, pub self_ty: Idx<TypeRef>,
pub is_negative: bool, pub is_negative: bool,
pub items: Box<[AssocItem]>, pub items: Box<[AssocItem]>,
pub ast_id: FileAstId<ast::Impl>, pub ast_id: FileAstId<ast::Impl>,

View file

@ -11,7 +11,7 @@ use syntax::{
use crate::{ use crate::{
generics::{GenericParams, TypeParamData, TypeParamProvenance}, generics::{GenericParams, TypeParamData, TypeParamProvenance},
type_ref::LifetimeRef, type_ref::{LifetimeRef, TraitRef},
}; };
use super::*; use super::*;
@ -536,8 +536,11 @@ impl Ctx {
fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> { fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
let generic_params = let generic_params =
self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def); self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def);
let target_trait = impl_def.trait_().map(|tr| self.lower_type_ref(&tr)); // FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
let target_type = self.lower_type_ref(&impl_def.self_ty()?); // as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
// equals itself.
let target_trait = impl_def.trait_().and_then(|tr| self.lower_trait_ref(&tr));
let self_ty = self.lower_type_ref(&impl_def.self_ty()?);
let is_negative = impl_def.excl_token().is_some(); let is_negative = impl_def.excl_token().is_some();
// We cannot use `assoc_items()` here as that does not include macro calls. // We cannot use `assoc_items()` here as that does not include macro calls.
@ -554,7 +557,7 @@ impl Ctx {
}) })
.collect(); .collect();
let ast_id = self.source_ast_id_map.ast_id(impl_def); let ast_id = self.source_ast_id_map.ast_id(impl_def);
let res = Impl { generic_params, target_trait, target_type, is_negative, items, ast_id }; let res = Impl { generic_params, target_trait, self_ty, is_negative, items, ast_id };
Some(id(self.data().impls.alloc(res))) Some(id(self.data().impls.alloc(res)))
} }
@ -740,10 +743,16 @@ impl Ctx {
self.data().vis.alloc(vis) self.data().vis.alloc(vis)
} }
fn lower_trait_ref(&mut self, trait_ref: &ast::Type) -> Option<Idx<TraitRef>> {
let trait_ref = TraitRef::from_ast(&self.body_ctx, trait_ref.clone())?;
Some(self.data().trait_refs.intern(trait_ref))
}
fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> { fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> {
let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone());
self.data().type_refs.intern(tyref) self.data().type_refs.intern(tyref)
} }
fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> { fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> {
match type_ref.map(|ty| self.lower_type_ref(&ty)) { match type_ref.map(|ty| self.lower_type_ref(&ty)) {
Some(it) => it, Some(it) => it,

View file

@ -51,6 +51,23 @@ impl Rawness {
} }
} }
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct TraitRef {
pub path: Path,
}
impl TraitRef {
/// Converts an `ast::PathType` to a `hir::TraitRef`.
pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Option<Self> {
// FIXME: Use `Path::from_src`
match node {
ast::Type::PathType(path) => {
path.path().and_then(|it| ctx.lower_path(it)).map(|path| TraitRef { path })
}
_ => None,
}
}
}
/// Compare ty::Ty /// Compare ty::Ty
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub enum TypeRef { pub enum TypeRef {

View file

@ -15,7 +15,7 @@ use hir_def::{
generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget},
path::{GenericArg, Path, PathSegment, PathSegments}, path::{GenericArg, Path, PathSegment, PathSegments},
resolver::{HasResolver, Resolver, TypeNs}, resolver::{HasResolver, Resolver, TypeNs},
type_ref::{TypeBound, TypeRef}, type_ref::{TraitRef as HirTraitRef, TypeBound, TypeRef},
AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId,
GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId,
TypeAliasId, TypeParamId, UnionId, VariantId, TypeAliasId, TypeParamId, UnionId, VariantId,
@ -667,14 +667,10 @@ impl<'a> TyLoweringContext<'a> {
fn lower_trait_ref( fn lower_trait_ref(
&self, &self,
type_ref: &TypeRef, trait_ref: &HirTraitRef,
explicit_self_ty: Option<Ty>, explicit_self_ty: Option<Ty>,
) -> Option<TraitRef> { ) -> Option<TraitRef> {
let path = match type_ref { self.lower_trait_ref_from_path(&trait_ref.path, explicit_self_ty)
TypeRef::Path(path) => path,
_ => return None,
};
self.lower_trait_ref_from_path(path, explicit_self_ty)
} }
fn trait_ref_substs_from_path( fn trait_ref_substs_from_path(
@ -1253,7 +1249,7 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde
let generics = generics(db.upcast(), impl_id.into()); let generics = generics(db.upcast(), impl_id.into());
let ctx = let ctx =
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
Binders::new(generics.len(), ctx.lower_ty(&impl_data.target_type)) Binders::new(generics.len(), ctx.lower_ty(&impl_data.self_ty))
} }
pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {

View file

@ -237,7 +237,7 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
.and_then(|assoc| match assoc.container(db) { .and_then(|assoc| match assoc.container(db) {
AssocItemContainer::Trait(t) => Some(t.into()), AssocItemContainer::Trait(t) => Some(t.into()),
AssocItemContainer::Impl(impld) => { AssocItemContainer::Impl(impld) => {
impld.target_ty(db).as_adt().map(|adt| adt.into()) impld.self_ty(db).as_adt().map(|adt| adt.into())
} }
}) })
.unwrap_or_else(|| f.clone().into()), .unwrap_or_else(|| f.clone().into()),

View file

@ -195,7 +195,7 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov
let adt = match def { let adt = match def {
Definition::ModuleDef(ModuleDef::Trait(it)) => return it.try_to_nav(db).map(to_action), Definition::ModuleDef(ModuleDef::Trait(it)) => return it.try_to_nav(db).map(to_action),
Definition::ModuleDef(ModuleDef::Adt(it)) => Some(it), Definition::ModuleDef(ModuleDef::Adt(it)) => Some(it),
Definition::SelfType(it) => it.target_ty(db).as_adt(), Definition::SelfType(it) => it.self_ty(db).as_adt(),
_ => None, _ => None,
}?; }?;
adt.try_to_nav(db).map(to_action) adt.try_to_nav(db).map(to_action)
@ -318,7 +318,7 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String>
Definition::ModuleDef(md) => match md { Definition::ModuleDef(md) => match md {
ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) { ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) {
AssocItemContainer::Trait(t) => Some(t.name(db)), AssocItemContainer::Trait(t) => Some(t.name(db)),
AssocItemContainer::Impl(i) => i.target_ty(db).as_adt().map(|adt| adt.name(db)), AssocItemContainer::Impl(i) => i.self_ty(db).as_adt().map(|adt| adt.name(db)),
}, },
ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)), ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)),
_ => None, _ => None,
@ -376,7 +376,7 @@ fn hover_for_definition(
}, },
Definition::Local(it) => hover_for_local(it, db), Definition::Local(it) => hover_for_local(it, db),
Definition::SelfType(impl_def) => { Definition::SelfType(impl_def) => {
impl_def.target_ty(db).as_adt().and_then(|adt| from_hir_fmt(db, adt, mod_path)) impl_def.self_ty(db).as_adt().and_then(|adt| from_hir_fmt(db, adt, mod_path))
} }
Definition::GenericParam(it) => from_hir_fmt(db, it, None), Definition::GenericParam(it) => from_hir_fmt(db, it, None),
Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))), Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))),

View file

@ -307,7 +307,7 @@ fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameRe
hir::AssocItemContainer::Impl(impl_) => impl_, hir::AssocItemContainer::Impl(impl_) => impl_,
}; };
let first_param_ty = first_param.ty(); let first_param_ty = first_param.ty();
let impl_ty = impl_.target_ty(sema.db); let impl_ty = impl_.self_ty(sema.db);
let (ty, self_param) = if impl_ty.remove_ref().is_some() { let (ty, self_param) = if impl_ty.remove_ref().is_some() {
// if the impl is a ref to the type we can just match the `&T` with self directly // if the impl is a ref to the type we can just match the `&T` with self directly
(first_param_ty.clone(), "self") (first_param_ty.clone(), "self")

View file

@ -298,7 +298,7 @@ fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Op
// FIXME: this also looks very wrong // FIXME: this also looks very wrong
if let Some(assoc_def) = assoc_def { if let Some(assoc_def) = assoc_def {
if let hir::AssocItemContainer::Impl(imp) = assoc_def.container(sema.db) { if let hir::AssocItemContainer::Impl(imp) = assoc_def.container(sema.db) {
let ty = imp.target_ty(sema.db); let ty = imp.self_ty(sema.db);
if let Some(adt) = ty.as_adt() { if let Some(adt) = ty.as_adt() {
let name = adt.name(sema.db); let name = adt.name(sema.db);
let idx = path.rfind(':').map_or(0, |idx| idx + 1); let idx = path.rfind(':').map_or(0, |idx| idx + 1);

View file

@ -92,7 +92,7 @@ fn is_default_implemented(ctx: &AssistContext, impl_: &Impl) -> bool {
None => return false, None => return false,
}; };
let ty = impl_def.target_ty(db); let ty = impl_def.self_ty(db);
let krate = impl_def.module(db).krate(); let krate = impl_def.module(db).krate();
let default = FamousDefs(&ctx.sema, Some(krate)).core_default_Default(); let default = FamousDefs(&ctx.sema, Some(krate)).core_default_Default();
let default_trait = match default { let default_trait = match default {

View file

@ -91,7 +91,7 @@ fn get_impl_method(
let scope = ctx.sema.scope(impl_.syntax()); let scope = ctx.sema.scope(impl_.syntax());
let krate = impl_def.module(db).krate(); let krate = impl_def.module(db).krate();
let ty = impl_def.target_ty(db); let ty = impl_def.self_ty(db);
let traits_in_scope = scope.traits_in_scope(); let traits_in_scope = scope.traits_in_scope();
ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func)) ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func))
} }

View file

@ -338,11 +338,11 @@ pub(crate) fn find_struct_impl(
// (we currently use the wrong type parameter) // (we currently use the wrong type parameter)
// also we wouldn't want to use e.g. `impl S<u32>` // also we wouldn't want to use e.g. `impl S<u32>`
let same_ty = match blk.target_ty(db).as_adt() { let same_ty = match blk.self_ty(db).as_adt() {
Some(def) => def == struct_def, Some(def) => def == struct_def,
None => false, None => false,
}; };
let not_trait_impl = blk.target_trait(db).is_none(); let not_trait_impl = blk.trait_(db).is_none();
if !(same_ty && not_trait_impl) { if !(same_ty && not_trait_impl) {
None None

View file

@ -220,7 +220,7 @@ fn complete_enum_variants(
}; };
if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) { if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) {
if impl_.target_ty(ctx.db) == *ty { if impl_.self_ty(ctx.db) == *ty {
for &variant in &variants { for &variant in &variants {
let self_path = hir::ModPath::from_segments( let self_path = hir::ModPath::from_segments(
hir::PathKind::Plain, hir::PathKind::Plain,

View file

@ -40,7 +40,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
_ => false, _ => false,
}, },
hir::ScopeDef::MacroDef(_) => true, hir::ScopeDef::MacroDef(_) => true,
hir::ScopeDef::ImplSelfType(impl_) => match impl_.target_ty(ctx.db).as_adt() { hir::ScopeDef::ImplSelfType(impl_) => match impl_.self_ty(ctx.db).as_adt() {
Some(hir::Adt::Struct(strukt)) => { Some(hir::Adt::Struct(strukt)) => {
acc.add_struct_pat(ctx, strukt, Some(name.clone())); acc.add_struct_pat(ctx, strukt, Some(name.clone()));
true true

View file

@ -117,7 +117,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
if let Some(krate) = ctx.krate { if let Some(krate) = ctx.krate {
let ty = match resolution { let ty = match resolution {
PathResolution::TypeParam(param) => param.ty(ctx.db), PathResolution::TypeParam(param) => param.ty(ctx.db),
PathResolution::SelfType(impl_def) => impl_def.target_ty(ctx.db), PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db),
_ => return, _ => return,
}; };

View file

@ -361,7 +361,7 @@ fn item_for_path_search(db: &RootDatabase, item: ItemInNs) -> Option<ItemInNs> {
Some(assoc_item) => match assoc_item.container(db) { Some(assoc_item) => match assoc_item.container(db) {
AssocItemContainer::Trait(trait_) => ItemInNs::from(ModuleDef::from(trait_)), AssocItemContainer::Trait(trait_) => ItemInNs::from(ModuleDef::from(trait_)),
AssocItemContainer::Impl(impl_) => { AssocItemContainer::Impl(impl_) => {
ItemInNs::from(ModuleDef::from(impl_.target_ty(db).as_adt()?)) ItemInNs::from(ModuleDef::from(impl_.self_ty(db).as_adt()?))
} }
}, },
None => item, None => item,