diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/data.rs | 10 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 43 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 17 | ||||
-rw-r--r-- | crates/hir_def/src/path/lower.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/type_ref.rs | 17 |
5 files changed, 78 insertions, 13 deletions
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 0be868ba2..214bcc648 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -10,7 +10,7 @@ use crate::{ | |||
10 | body::Expander, | 10 | body::Expander, |
11 | db::DefDatabase, | 11 | db::DefDatabase, |
12 | item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, | 12 | item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, |
13 | type_ref::{TypeBound, TypeRef}, | 13 | type_ref::{TraitRef, TypeBound, TypeRef}, |
14 | visibility::RawVisibility, | 14 | visibility::RawVisibility, |
15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, | 15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, |
16 | Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, | 16 | Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, |
@@ -156,8 +156,8 @@ impl TraitData { | |||
156 | 156 | ||
157 | #[derive(Debug, Clone, PartialEq, Eq)] | 157 | #[derive(Debug, Clone, PartialEq, Eq)] |
158 | pub struct ImplData { | 158 | pub struct ImplData { |
159 | pub target_trait: Option<TypeRef>, | 159 | pub target_trait: Option<TraitRef>, |
160 | pub target_type: TypeRef, | 160 | pub self_ty: TypeRef, |
161 | pub items: Vec<AssocItemId>, | 161 | pub items: Vec<AssocItemId>, |
162 | pub is_negative: bool, | 162 | pub is_negative: bool, |
163 | } | 163 | } |
@@ -170,7 +170,7 @@ impl ImplData { | |||
170 | let item_tree = impl_loc.id.item_tree(db); | 170 | let item_tree = impl_loc.id.item_tree(db); |
171 | let impl_def = &item_tree[impl_loc.id.value]; | 171 | let impl_def = &item_tree[impl_loc.id.value]; |
172 | let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); | 172 | 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(); |
174 | let is_negative = impl_def.is_negative; | 174 | let is_negative = impl_def.is_negative; |
175 | let module_id = impl_loc.container; | 175 | let module_id = impl_loc.container; |
176 | let container = AssocContainerId::ImplId(id); | 176 | let container = AssocContainerId::ImplId(id); |
@@ -187,7 +187,7 @@ impl ImplData { | |||
187 | ); | 187 | ); |
188 | let items = items.into_iter().map(|(_, item)| item).collect(); | 188 | let items = items.into_iter().map(|(_, item)| item).collect(); |
189 | 189 | ||
190 | Arc::new(ImplData { target_trait, target_type, items, is_negative }) | 190 | Arc::new(ImplData { target_trait, self_ty, items, is_negative }) |
191 | } | 191 | } |
192 | } | 192 | } |
193 | 193 | ||
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index ca0048b16..5449bbf5d 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -31,7 +31,7 @@ use crate::{ | |||
31 | db::DefDatabase, | 31 | db::DefDatabase, |
32 | generics::GenericParams, | 32 | generics::GenericParams, |
33 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, | 33 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, |
34 | type_ref::{Mutability, TypeBound, TypeRef}, | 34 | type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, |
35 | visibility::RawVisibility, | 35 | visibility::RawVisibility, |
36 | }; | 36 | }; |
37 | 37 | ||
@@ -147,6 +147,7 @@ impl ItemTree { | |||
147 | vis, | 147 | vis, |
148 | generics, | 148 | generics, |
149 | type_refs, | 149 | type_refs, |
150 | trait_refs, | ||
150 | inner_items, | 151 | inner_items, |
151 | } = &mut **data; | 152 | } = &mut **data; |
152 | 153 | ||
@@ -173,6 +174,7 @@ impl ItemTree { | |||
173 | generics.arena.shrink_to_fit(); | 174 | generics.arena.shrink_to_fit(); |
174 | type_refs.arena.shrink_to_fit(); | 175 | type_refs.arena.shrink_to_fit(); |
175 | type_refs.map.shrink_to_fit(); | 176 | type_refs.map.shrink_to_fit(); |
177 | trait_refs.map.shrink_to_fit(); | ||
176 | 178 | ||
177 | inner_items.shrink_to_fit(); | 179 | inner_items.shrink_to_fit(); |
178 | } | 180 | } |
@@ -295,6 +297,32 @@ impl TypeRefStorage { | |||
295 | } | 297 | } |
296 | } | 298 | } |
297 | 299 | ||
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 | |||
298 | #[derive(Default, Debug, Eq, PartialEq)] | 326 | #[derive(Default, Debug, Eq, PartialEq)] |
299 | struct ItemTreeData { | 327 | struct ItemTreeData { |
300 | imports: Arena<Import>, | 328 | imports: Arena<Import>, |
@@ -319,6 +347,7 @@ struct ItemTreeData { | |||
319 | vis: ItemVisibilities, | 347 | vis: ItemVisibilities, |
320 | generics: GenericParamsStorage, | 348 | generics: GenericParamsStorage, |
321 | type_refs: TypeRefStorage, | 349 | type_refs: TypeRefStorage, |
350 | trait_refs: TraitRefStorage, | ||
322 | 351 | ||
323 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, | 352 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, |
324 | } | 353 | } |
@@ -556,6 +585,14 @@ impl Index<Idx<TypeRef>> for ItemTree { | |||
556 | } | 585 | } |
557 | } | 586 | } |
558 | 587 | ||
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 | |||
559 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | 596 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { |
560 | type Output = N; | 597 | type Output = N; |
561 | fn index(&self, id: FileItemTreeId<N>) -> &N { | 598 | fn index(&self, id: FileItemTreeId<N>) -> &N { |
@@ -692,8 +729,8 @@ pub struct Trait { | |||
692 | #[derive(Debug, Clone, Eq, PartialEq)] | 729 | #[derive(Debug, Clone, Eq, PartialEq)] |
693 | pub struct Impl { | 730 | pub struct Impl { |
694 | pub generic_params: GenericParamsId, | 731 | pub generic_params: GenericParamsId, |
695 | pub target_trait: Option<Idx<TypeRef>>, | 732 | pub target_trait: Option<Idx<TraitRef>>, |
696 | pub target_type: Idx<TypeRef>, | 733 | pub self_ty: Idx<TypeRef>, |
697 | pub is_negative: bool, | 734 | pub is_negative: bool, |
698 | pub items: Box<[AssocItem]>, | 735 | pub items: Box<[AssocItem]>, |
699 | pub ast_id: FileAstId<ast::Impl>, | 736 | pub ast_id: FileAstId<ast::Impl>, |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 3f558edd8..8d3862811 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -11,7 +11,7 @@ use syntax::{ | |||
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, | 13 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, |
14 | type_ref::LifetimeRef, | 14 | type_ref::{LifetimeRef, TraitRef}, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | use super::*; | 17 | use super::*; |
@@ -536,8 +536,11 @@ impl Ctx { | |||
536 | fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> { | 536 | fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> { |
537 | let generic_params = | 537 | let generic_params = |
538 | self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def); | 538 | 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)); | 539 | // FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl |
540 | let target_type = self.lower_type_ref(&impl_def.self_ty()?); | 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()?); | ||
541 | let is_negative = impl_def.excl_token().is_some(); | 544 | let is_negative = impl_def.excl_token().is_some(); |
542 | 545 | ||
543 | // We cannot use `assoc_items()` here as that does not include macro calls. | 546 | // We cannot use `assoc_items()` here as that does not include macro calls. |
@@ -554,7 +557,7 @@ impl Ctx { | |||
554 | }) | 557 | }) |
555 | .collect(); | 558 | .collect(); |
556 | let ast_id = self.source_ast_id_map.ast_id(impl_def); | 559 | 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 }; |
558 | Some(id(self.data().impls.alloc(res))) | 561 | Some(id(self.data().impls.alloc(res))) |
559 | } | 562 | } |
560 | 563 | ||
@@ -740,10 +743,16 @@ impl Ctx { | |||
740 | self.data().vis.alloc(vis) | 743 | self.data().vis.alloc(vis) |
741 | } | 744 | } |
742 | 745 | ||
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 | |||
743 | fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> { | 751 | fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> { |
744 | let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); | 752 | let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); |
745 | self.data().type_refs.intern(tyref) | 753 | self.data().type_refs.intern(tyref) |
746 | } | 754 | } |
755 | |||
747 | fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> { | 756 | fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> { |
748 | match type_ref.map(|ty| self.lower_type_ref(&ty)) { | 757 | match type_ref.map(|ty| self.lower_type_ref(&ty)) { |
749 | Some(it) => it, | 758 | Some(it) => it, |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index 505493a74..4de951fd3 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -74,6 +74,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
74 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo | 74 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo |
75 | Some(trait_ref) => { | 75 | Some(trait_ref) => { |
76 | let path = Path::from_src(trait_ref.path()?, hygiene)?; | 76 | let path = Path::from_src(trait_ref.path()?, hygiene)?; |
77 | let num_segments = path.mod_path.segments.len(); | ||
77 | kind = path.mod_path.kind; | 78 | kind = path.mod_path.kind; |
78 | 79 | ||
79 | let mut prefix_segments = path.mod_path.segments; | 80 | let mut prefix_segments = path.mod_path.segments; |
@@ -85,7 +86,8 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
85 | generic_args.extend(prefix_args); | 86 | generic_args.extend(prefix_args); |
86 | 87 | ||
87 | // Insert the type reference (T in the above example) as Self parameter for the trait | 88 | // Insert the type reference (T in the above example) as Self parameter for the trait |
88 | let last_segment = generic_args.last_mut()?; | 89 | let last_segment = |
90 | generic_args.iter_mut().rev().nth(num_segments.saturating_sub(1))?; | ||
89 | if last_segment.is_none() { | 91 | if last_segment.is_none() { |
90 | *last_segment = Some(Arc::new(GenericArgs::empty())); | 92 | *last_segment = Some(Arc::new(GenericArgs::empty())); |
91 | }; | 93 | }; |
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs index 049b2e462..4c24aae94 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs | |||
@@ -51,6 +51,23 @@ impl Rawness { | |||
51 | } | 51 | } |
52 | } | 52 | } |
53 | 53 | ||
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 | } | ||
54 | /// Compare ty::Ty | 71 | /// Compare ty::Ty |
55 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 72 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
56 | pub enum TypeRef { | 73 | pub enum TypeRef { |