Skip to content

Commit fd7c454

Browse files
bors[bot]Veykril
andauthored
Merge #8186
8186: Lower traits to `TraitRef` instead of `TypeRef` r=matklad a=Veykril Co-authored-by: Lukas Wirth <[email protected]>
2 parents 277db63 + b4bb774 commit fd7c454

File tree

17 files changed

+100
-40
lines changed

17 files changed

+100
-40
lines changed

crates/hir/src/lib.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ use hir_def::{
4444
per_ns::PerNs,
4545
resolver::{HasResolver, Resolver},
4646
src::HasSource as _,
47+
type_ref::TraitRef,
4748
AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId,
4849
DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId,
4950
LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
@@ -1573,9 +1574,9 @@ impl Impl {
15731574
};
15741575

15751576
let filter = |impl_def: &Impl| {
1576-
let target_ty = impl_def.target_ty(db);
1577-
let rref = target_ty.remove_ref();
1578-
ty.equals_ctor(rref.as_ref().map_or(&target_ty.ty, |it| &it.ty))
1577+
let self_ty = impl_def.self_ty(db);
1578+
let rref = self_ty.remove_ref();
1579+
ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
15791580
};
15801581

15811582
let mut all = Vec::new();
@@ -1613,16 +1614,16 @@ impl Impl {
16131614

16141615
// FIXME: the return type is wrong. This should be a hir version of
16151616
// `TraitRef` (ie, resolved `TypeRef`).
1616-
pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> {
1617+
pub fn trait_(self, db: &dyn HirDatabase) -> Option<TraitRef> {
16171618
db.impl_data(self.id).target_trait.clone()
16181619
}
16191620

1620-
pub fn target_ty(self, db: &dyn HirDatabase) -> Type {
1621+
pub fn self_ty(self, db: &dyn HirDatabase) -> Type {
16211622
let impl_data = db.impl_data(self.id);
16221623
let resolver = self.id.resolver(db.upcast());
16231624
let krate = self.id.lookup(db.upcast()).container.krate();
16241625
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
1625-
let ty = ctx.lower_ty(&impl_data.target_type);
1626+
let ty = ctx.lower_ty(&impl_data.self_ty);
16261627
Type::new_with_resolver_inner(db, krate, &resolver, ty)
16271628
}
16281629

crates/hir_def/src/data.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
body::Expander,
1111
db::DefDatabase,
1212
item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param},
13-
type_ref::{TypeBound, TypeRef},
13+
type_ref::{TraitRef, TypeBound, TypeRef},
1414
visibility::RawVisibility,
1515
AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
1616
Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
@@ -156,8 +156,8 @@ impl TraitData {
156156

157157
#[derive(Debug, Clone, PartialEq, Eq)]
158158
pub struct ImplData {
159-
pub target_trait: Option<TypeRef>,
160-
pub target_type: TypeRef,
159+
pub target_trait: Option<TraitRef>,
160+
pub self_ty: TypeRef,
161161
pub items: Vec<AssocItemId>,
162162
pub is_negative: bool,
163163
}
@@ -170,7 +170,7 @@ impl ImplData {
170170
let item_tree = impl_loc.id.item_tree(db);
171171
let impl_def = &item_tree[impl_loc.id.value];
172172
let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone());
173-
let target_type = item_tree[impl_def.target_type].clone();
173+
let self_ty = item_tree[impl_def.self_ty].clone();
174174
let is_negative = impl_def.is_negative;
175175
let module_id = impl_loc.container;
176176
let container = AssocContainerId::ImplId(id);
@@ -187,7 +187,7 @@ impl ImplData {
187187
);
188188
let items = items.into_iter().map(|(_, item)| item).collect();
189189

190-
Arc::new(ImplData { target_trait, target_type, items, is_negative })
190+
Arc::new(ImplData { target_trait, self_ty, items, is_negative })
191191
}
192192
}
193193

crates/hir_def/src/item_tree.rs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::{
3131
db::DefDatabase,
3232
generics::GenericParams,
3333
path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
34-
type_ref::{Mutability, TypeBound, TypeRef},
34+
type_ref::{Mutability, TraitRef, TypeBound, TypeRef},
3535
visibility::RawVisibility,
3636
};
3737

@@ -147,6 +147,7 @@ impl ItemTree {
147147
vis,
148148
generics,
149149
type_refs,
150+
trait_refs,
150151
inner_items,
151152
} = &mut **data;
152153

@@ -173,6 +174,7 @@ impl ItemTree {
173174
generics.arena.shrink_to_fit();
174175
type_refs.arena.shrink_to_fit();
175176
type_refs.map.shrink_to_fit();
177+
trait_refs.map.shrink_to_fit();
176178

177179
inner_items.shrink_to_fit();
178180
}
@@ -295,6 +297,32 @@ impl TypeRefStorage {
295297
}
296298
}
297299

300+
/// `TraitRef` interner.
301+
#[derive(Default, Debug, Eq, PartialEq)]
302+
struct TraitRefStorage {
303+
arena: Arena<Arc<TraitRef>>,
304+
map: FxHashMap<Arc<TraitRef>, Idx<Arc<TraitRef>>>,
305+
}
306+
307+
impl TraitRefStorage {
308+
// Note: We lie about the `Idx<TraitRef>` to hide the interner details.
309+
310+
fn intern(&mut self, ty: TraitRef) -> Idx<TraitRef> {
311+
if let Some(id) = self.map.get(&ty) {
312+
return Idx::from_raw(id.into_raw());
313+
}
314+
315+
let ty = Arc::new(ty);
316+
let idx = self.arena.alloc(ty.clone());
317+
self.map.insert(ty, idx);
318+
Idx::from_raw(idx.into_raw())
319+
}
320+
321+
fn lookup(&self, id: Idx<TraitRef>) -> &TraitRef {
322+
&self.arena[Idx::from_raw(id.into_raw())]
323+
}
324+
}
325+
298326
#[derive(Default, Debug, Eq, PartialEq)]
299327
struct ItemTreeData {
300328
imports: Arena<Import>,
@@ -319,6 +347,7 @@ struct ItemTreeData {
319347
vis: ItemVisibilities,
320348
generics: GenericParamsStorage,
321349
type_refs: TypeRefStorage,
350+
trait_refs: TraitRefStorage,
322351

323352
inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>,
324353
}
@@ -556,6 +585,14 @@ impl Index<Idx<TypeRef>> for ItemTree {
556585
}
557586
}
558587

588+
impl Index<Idx<TraitRef>> for ItemTree {
589+
type Output = TraitRef;
590+
591+
fn index(&self, id: Idx<TraitRef>) -> &Self::Output {
592+
self.data().trait_refs.lookup(id)
593+
}
594+
}
595+
559596
impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
560597
type Output = N;
561598
fn index(&self, id: FileItemTreeId<N>) -> &N {
@@ -692,8 +729,8 @@ pub struct Trait {
692729
#[derive(Debug, Clone, Eq, PartialEq)]
693730
pub struct Impl {
694731
pub generic_params: GenericParamsId,
695-
pub target_trait: Option<Idx<TypeRef>>,
696-
pub target_type: Idx<TypeRef>,
732+
pub target_trait: Option<Idx<TraitRef>>,
733+
pub self_ty: Idx<TypeRef>,
697734
pub is_negative: bool,
698735
pub items: Box<[AssocItem]>,
699736
pub ast_id: FileAstId<ast::Impl>,

crates/hir_def/src/item_tree/lower.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use syntax::{
1111

1212
use crate::{
1313
generics::{GenericParams, TypeParamData, TypeParamProvenance},
14-
type_ref::LifetimeRef,
14+
type_ref::{LifetimeRef, TraitRef},
1515
};
1616

1717
use super::*;
@@ -536,8 +536,11 @@ impl Ctx {
536536
fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
537537
let generic_params =
538538
self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def);
539-
let target_trait = impl_def.trait_().map(|tr| self.lower_type_ref(&tr));
540-
let target_type = self.lower_type_ref(&impl_def.self_ty()?);
539+
// FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
540+
// as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
541+
// equals itself.
542+
let target_trait = impl_def.trait_().and_then(|tr| self.lower_trait_ref(&tr));
543+
let self_ty = self.lower_type_ref(&impl_def.self_ty()?);
541544
let is_negative = impl_def.excl_token().is_some();
542545

543546
// We cannot use `assoc_items()` here as that does not include macro calls.
@@ -554,7 +557,7 @@ impl Ctx {
554557
})
555558
.collect();
556559
let ast_id = self.source_ast_id_map.ast_id(impl_def);
557-
let res = Impl { generic_params, target_trait, target_type, is_negative, items, ast_id };
560+
let res = Impl { generic_params, target_trait, self_ty, is_negative, items, ast_id };
558561
Some(id(self.data().impls.alloc(res)))
559562
}
560563

@@ -740,10 +743,16 @@ impl Ctx {
740743
self.data().vis.alloc(vis)
741744
}
742745

746+
fn lower_trait_ref(&mut self, trait_ref: &ast::Type) -> Option<Idx<TraitRef>> {
747+
let trait_ref = TraitRef::from_ast(&self.body_ctx, trait_ref.clone())?;
748+
Some(self.data().trait_refs.intern(trait_ref))
749+
}
750+
743751
fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> {
744752
let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone());
745753
self.data().type_refs.intern(tyref)
746754
}
755+
747756
fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> {
748757
match type_ref.map(|ty| self.lower_type_ref(&ty)) {
749758
Some(it) => it,

crates/hir_def/src/type_ref.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,23 @@ impl Rawness {
5151
}
5252
}
5353

54+
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
55+
pub struct TraitRef {
56+
pub path: Path,
57+
}
58+
59+
impl TraitRef {
60+
/// Converts an `ast::PathType` to a `hir::TraitRef`.
61+
pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Option<Self> {
62+
// FIXME: Use `Path::from_src`
63+
match node {
64+
ast::Type::PathType(path) => {
65+
path.path().and_then(|it| ctx.lower_path(it)).map(|path| TraitRef { path })
66+
}
67+
_ => None,
68+
}
69+
}
70+
}
5471
/// Compare ty::Ty
5572
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
5673
pub enum TypeRef {

crates/hir_ty/src/lower.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use hir_def::{
1515
generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget},
1616
path::{GenericArg, Path, PathSegment, PathSegments},
1717
resolver::{HasResolver, Resolver, TypeNs},
18-
type_ref::{TypeBound, TypeRef},
18+
type_ref::{TraitRef as HirTraitRef, TypeBound, TypeRef},
1919
AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId,
2020
GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId,
2121
TypeAliasId, TypeParamId, UnionId, VariantId,
@@ -667,14 +667,10 @@ impl<'a> TyLoweringContext<'a> {
667667

668668
fn lower_trait_ref(
669669
&self,
670-
type_ref: &TypeRef,
670+
trait_ref: &HirTraitRef,
671671
explicit_self_ty: Option<Ty>,
672672
) -> Option<TraitRef> {
673-
let path = match type_ref {
674-
TypeRef::Path(path) => path,
675-
_ => return None,
676-
};
677-
self.lower_trait_ref_from_path(path, explicit_self_ty)
673+
self.lower_trait_ref_from_path(&trait_ref.path, explicit_self_ty)
678674
}
679675

680676
fn trait_ref_substs_from_path(
@@ -1253,7 +1249,7 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde
12531249
let generics = generics(db.upcast(), impl_id.into());
12541250
let ctx =
12551251
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1256-
Binders::new(generics.len(), ctx.lower_ty(&impl_data.target_type))
1252+
Binders::new(generics.len(), ctx.lower_ty(&impl_data.self_ty))
12571253
}
12581254

12591255
pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {

crates/ide/src/doc_links.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
237237
.and_then(|assoc| match assoc.container(db) {
238238
AssocItemContainer::Trait(t) => Some(t.into()),
239239
AssocItemContainer::Impl(impld) => {
240-
impld.target_ty(db).as_adt().map(|adt| adt.into())
240+
impld.self_ty(db).as_adt().map(|adt| adt.into())
241241
}
242242
})
243243
.unwrap_or_else(|| f.clone().into()),

crates/ide/src/hover.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov
195195
let adt = match def {
196196
Definition::ModuleDef(ModuleDef::Trait(it)) => return it.try_to_nav(db).map(to_action),
197197
Definition::ModuleDef(ModuleDef::Adt(it)) => Some(it),
198-
Definition::SelfType(it) => it.target_ty(db).as_adt(),
198+
Definition::SelfType(it) => it.self_ty(db).as_adt(),
199199
_ => None,
200200
}?;
201201
adt.try_to_nav(db).map(to_action)
@@ -318,7 +318,7 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String>
318318
Definition::ModuleDef(md) => match md {
319319
ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) {
320320
AssocItemContainer::Trait(t) => Some(t.name(db)),
321-
AssocItemContainer::Impl(i) => i.target_ty(db).as_adt().map(|adt| adt.name(db)),
321+
AssocItemContainer::Impl(i) => i.self_ty(db).as_adt().map(|adt| adt.name(db)),
322322
},
323323
ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)),
324324
_ => None,
@@ -376,7 +376,7 @@ fn hover_for_definition(
376376
},
377377
Definition::Local(it) => hover_for_local(it, db),
378378
Definition::SelfType(impl_def) => {
379-
impl_def.target_ty(db).as_adt().and_then(|adt| from_hir_fmt(db, adt, mod_path))
379+
impl_def.self_ty(db).as_adt().and_then(|adt| from_hir_fmt(db, adt, mod_path))
380380
}
381381
Definition::GenericParam(it) => from_hir_fmt(db, it, None),
382382
Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))),

crates/ide/src/references/rename.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameRe
307307
hir::AssocItemContainer::Impl(impl_) => impl_,
308308
};
309309
let first_param_ty = first_param.ty();
310-
let impl_ty = impl_.target_ty(sema.db);
310+
let impl_ty = impl_.self_ty(sema.db);
311311
let (ty, self_param) = if impl_ty.remove_ref().is_some() {
312312
// if the impl is a ref to the type we can just match the `&T` with self directly
313313
(first_param_ty.clone(), "self")

crates/ide/src/runnables.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Op
298298
// FIXME: this also looks very wrong
299299
if let Some(assoc_def) = assoc_def {
300300
if let hir::AssocItemContainer::Impl(imp) = assoc_def.container(sema.db) {
301-
let ty = imp.target_ty(sema.db);
301+
let ty = imp.self_ty(sema.db);
302302
if let Some(adt) = ty.as_adt() {
303303
let name = adt.name(sema.db);
304304
let idx = path.rfind(':').map_or(0, |idx| idx + 1);

0 commit comments

Comments
 (0)