aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
authorSeivan Heidari <[email protected]>2019-11-21 00:11:41 +0000
committerSeivan Heidari <[email protected]>2019-11-21 00:11:41 +0000
commit358a1bcd708c622836723e5201b6de77cc9ff327 (patch)
treeaeff9c96a6059fa2b02e7c87ec88753bc7993d8d /crates/ra_hir_def
parent1e2d090ab8a9bda18f148b894b7948eb05b976e6 (diff)
parent612a72fc4ea4376920f2a7da7b3c334227c1716c (diff)
Merge branch 'master' of https://github.com/rust-analyzer/rust-analyzer into feature/themes
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/adt.rs8
-rw-r--r--crates/ra_hir_def/src/body.rs16
-rw-r--r--crates/ra_hir_def/src/body/scope.rs9
-rw-r--r--crates/ra_hir_def/src/db.rs18
-rw-r--r--crates/ra_hir_def/src/diagnostics.rs2
-rw-r--r--crates/ra_hir_def/src/generics.rs185
-rw-r--r--crates/ra_hir_def/src/impls.rs (renamed from crates/ra_hir_def/src/imp.rs)35
-rw-r--r--crates/ra_hir_def/src/lib.rs180
-rw-r--r--crates/ra_hir_def/src/nameres.rs8
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs33
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs2
-rw-r--r--crates/ra_hir_def/src/path.rs2
-rw-r--r--crates/ra_hir_def/src/traits.rs59
13 files changed, 498 insertions, 59 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index a29c4d41e..d04f54e15 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -54,8 +54,8 @@ impl StructData {
54 id: StructOrUnionId, 54 id: StructOrUnionId,
55 ) -> Arc<StructData> { 55 ) -> Arc<StructData> {
56 let src = id.source(db); 56 let src = id.source(db);
57 let name = src.ast.name().map(|n| n.as_name()); 57 let name = src.value.name().map(|n| n.as_name());
58 let variant_data = VariantData::new(src.ast.kind()); 58 let variant_data = VariantData::new(src.value.kind());
59 let variant_data = Arc::new(variant_data); 59 let variant_data = Arc::new(variant_data);
60 Arc::new(StructData { name, variant_data }) 60 Arc::new(StructData { name, variant_data })
61 } 61 }
@@ -64,9 +64,9 @@ impl StructData {
64impl EnumData { 64impl EnumData {
65 pub(crate) fn enum_data_query(db: &impl DefDatabase2, e: EnumId) -> Arc<EnumData> { 65 pub(crate) fn enum_data_query(db: &impl DefDatabase2, e: EnumId) -> Arc<EnumData> {
66 let src = e.source(db); 66 let src = e.source(db);
67 let name = src.ast.name().map(|n| n.as_name()); 67 let name = src.value.name().map(|n| n.as_name());
68 let variants = src 68 let variants = src
69 .ast 69 .value
70 .variant_list() 70 .variant_list()
71 .into_iter() 71 .into_iter()
72 .flat_map(|it| it.variants()) 72 .flat_map(|it| it.variants())
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 85dc4feb0..dfb79a30a 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -17,7 +17,7 @@ use crate::{
17 expr::{Expr, ExprId, Pat, PatId}, 17 expr::{Expr, ExprId, Pat, PatId},
18 nameres::CrateDefMap, 18 nameres::CrateDefMap,
19 path::Path, 19 path::Path,
20 AstItemDef, DefWithBodyId, ModuleId, 20 AstItemDef, DefWithBodyId, HasModule, HasSource, Lookup, ModuleId,
21}; 21};
22 22
23pub struct Expander { 23pub struct Expander {
@@ -73,8 +73,8 @@ impl Expander {
73 std::mem::forget(mark); 73 std::mem::forget(mark);
74 } 74 }
75 75
76 fn to_source<T>(&self, ast: T) -> Source<T> { 76 fn to_source<T>(&self, value: T) -> Source<T> {
77 Source { file_id: self.current_file_id, ast } 77 Source { file_id: self.current_file_id, value }
78 } 78 }
79 79
80 fn parse_path(&mut self, path: ast::Path) -> Option<Path> { 80 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
@@ -149,17 +149,19 @@ impl Body {
149 149
150 let (file_id, module, body) = match def { 150 let (file_id, module, body) = match def {
151 DefWithBodyId::FunctionId(f) => { 151 DefWithBodyId::FunctionId(f) => {
152 let f = f.lookup(db);
152 let src = f.source(db); 153 let src = f.source(db);
153 params = src.ast.param_list(); 154 params = src.value.param_list();
154 (src.file_id, f.module(db), src.ast.body().map(ast::Expr::from)) 155 (src.file_id, f.module(db), src.value.body().map(ast::Expr::from))
155 } 156 }
156 DefWithBodyId::ConstId(c) => { 157 DefWithBodyId::ConstId(c) => {
158 let c = c.lookup(db);
157 let src = c.source(db); 159 let src = c.source(db);
158 (src.file_id, c.module(db), src.ast.body()) 160 (src.file_id, c.module(db), src.value.body())
159 } 161 }
160 DefWithBodyId::StaticId(s) => { 162 DefWithBodyId::StaticId(s) => {
161 let src = s.source(db); 163 let src = s.source(db);
162 (src.file_id, s.module(db), src.ast.body()) 164 (src.file_id, s.module(db), src.value.body())
163 } 165 }
164 }; 166 };
165 let expander = Expander::new(db, file_id, module); 167 let expander = Expander::new(db, file_id, module);
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 10cb87d37..aeb71ff22 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -210,8 +210,9 @@ mod tests {
210 let scopes = db.expr_scopes(function.into()); 210 let scopes = db.expr_scopes(function.into());
211 let (_body, source_map) = db.body_with_source_map(function.into()); 211 let (_body, source_map) = db.body_with_source_map(function.into());
212 212
213 let expr_id = 213 let expr_id = source_map
214 source_map.node_expr(Source { file_id: file_id.into(), ast: &marker.into() }).unwrap(); 214 .node_expr(Source { file_id: file_id.into(), value: &marker.into() })
215 .unwrap();
215 let scope = scopes.scope_for(expr_id); 216 let scope = scopes.scope_for(expr_id);
216 217
217 let actual = scopes 218 let actual = scopes
@@ -317,14 +318,14 @@ mod tests {
317 let expr_scope = { 318 let expr_scope = {
318 let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap(); 319 let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap();
319 let expr_id = 320 let expr_id =
320 source_map.node_expr(Source { file_id: file_id.into(), ast: &expr_ast }).unwrap(); 321 source_map.node_expr(Source { file_id: file_id.into(), value: &expr_ast }).unwrap();
321 scopes.scope_for(expr_id).unwrap() 322 scopes.scope_for(expr_id).unwrap()
322 }; 323 };
323 324
324 let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap(); 325 let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap();
325 let pat_src = source_map.pat_syntax(resolved.pat()).unwrap(); 326 let pat_src = source_map.pat_syntax(resolved.pat()).unwrap();
326 327
327 let local_name = pat_src.ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); 328 let local_name = pat_src.value.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
328 assert_eq!(local_name.range(), expected_name.syntax().text_range()); 329 assert_eq!(local_name.range(), expected_name.syntax().text_range());
329 } 330 }
330 331
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 348aca07f..844f8bbe8 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -8,30 +8,32 @@ use ra_syntax::ast;
8use crate::{ 8use crate::{
9 adt::{EnumData, StructData}, 9 adt::{EnumData, StructData},
10 body::{scope::ExprScopes, Body, BodySourceMap}, 10 body::{scope::ExprScopes, Body, BodySourceMap},
11 imp::ImplData, 11 generics::GenericParams,
12 impls::ImplData,
12 nameres::{ 13 nameres::{
13 raw::{ImportSourceMap, RawItems}, 14 raw::{ImportSourceMap, RawItems},
14 CrateDefMap, 15 CrateDefMap,
15 }, 16 },
16 DefWithBodyId, EnumId, ImplId, ItemLoc, StructOrUnionId, 17 traits::TraitData,
18 DefWithBodyId, EnumId, GenericDefId, ImplId, ItemLoc, StructOrUnionId, TraitId,
17}; 19};
18 20
19#[salsa::query_group(InternDatabaseStorage)] 21#[salsa::query_group(InternDatabaseStorage)]
20pub trait InternDatabase: SourceDatabase { 22pub trait InternDatabase: SourceDatabase {
21 #[salsa::interned] 23 #[salsa::interned]
22 fn intern_function(&self, loc: ItemLoc<ast::FnDef>) -> crate::FunctionId; 24 fn intern_function(&self, loc: crate::FunctionLoc) -> crate::FunctionId;
23 #[salsa::interned] 25 #[salsa::interned]
24 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> crate::StructOrUnionId; 26 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> crate::StructOrUnionId;
25 #[salsa::interned] 27 #[salsa::interned]
26 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> crate::EnumId; 28 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> crate::EnumId;
27 #[salsa::interned] 29 #[salsa::interned]
28 fn intern_const(&self, loc: ItemLoc<ast::ConstDef>) -> crate::ConstId; 30 fn intern_const(&self, loc: crate::ConstLoc) -> crate::ConstId;
29 #[salsa::interned] 31 #[salsa::interned]
30 fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> crate::StaticId; 32 fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> crate::StaticId;
31 #[salsa::interned] 33 #[salsa::interned]
32 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> crate::TraitId; 34 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> crate::TraitId;
33 #[salsa::interned] 35 #[salsa::interned]
34 fn intern_type_alias(&self, loc: ItemLoc<ast::TypeAliasDef>) -> crate::TypeAliasId; 36 fn intern_type_alias(&self, loc: crate::TypeAliasLoc) -> crate::TypeAliasId;
35 #[salsa::interned] 37 #[salsa::interned]
36 fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> crate::ImplId; 38 fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> crate::ImplId;
37} 39}
@@ -59,6 +61,9 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
59 #[salsa::invoke(ImplData::impl_data_query)] 61 #[salsa::invoke(ImplData::impl_data_query)]
60 fn impl_data(&self, e: ImplId) -> Arc<ImplData>; 62 fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
61 63
64 #[salsa::invoke(TraitData::trait_data_query)]
65 fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
66
62 #[salsa::invoke(Body::body_with_source_map_query)] 67 #[salsa::invoke(Body::body_with_source_map_query)]
63 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); 68 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
64 69
@@ -67,4 +72,7 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
67 72
68 #[salsa::invoke(ExprScopes::expr_scopes_query)] 73 #[salsa::invoke(ExprScopes::expr_scopes_query)]
69 fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>; 74 fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>;
75
76 #[salsa::invoke(GenericParams::generic_params_query)]
77 fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>;
70} 78}
diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs
index 9843009a5..eda9b2269 100644
--- a/crates/ra_hir_def/src/diagnostics.rs
+++ b/crates/ra_hir_def/src/diagnostics.rs
@@ -20,7 +20,7 @@ impl Diagnostic for UnresolvedModule {
20 "unresolved module".to_string() 20 "unresolved module".to_string()
21 } 21 }
22 fn source(&self) -> Source<SyntaxNodePtr> { 22 fn source(&self) -> Source<SyntaxNodePtr> {
23 Source { file_id: self.file, ast: self.decl.into() } 23 Source { file_id: self.file, value: self.decl.into() }
24 } 24 }
25 fn as_any(&self) -> &(dyn Any + Send + 'static) { 25 fn as_any(&self) -> &(dyn Any + Send + 'static) {
26 self 26 self
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
new file mode 100644
index 000000000..9e2e4c3cc
--- /dev/null
+++ b/crates/ra_hir_def/src/generics.rs
@@ -0,0 +1,185 @@
1//! Many kinds of items or constructs can have generic parameters: functions,
2//! structs, impls, traits, etc. This module provides a common HIR for these
3//! generic parameters. See also the `Generics` type and the `generics_of` query
4//! in rustc.
5use std::sync::Arc;
6
7use hir_expand::name::{self, AsName, Name};
8use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
9
10use crate::{
11 db::DefDatabase2,
12 type_ref::{TypeBound, TypeRef},
13 AdtId, AstItemDef, ContainerId, GenericDefId, HasSource, Lookup,
14};
15
16/// Data about a generic parameter (to a function, struct, impl, ...).
17#[derive(Clone, PartialEq, Eq, Debug)]
18pub struct GenericParam {
19 // FIXME: give generic params proper IDs
20 pub idx: u32,
21 pub name: Name,
22 pub default: Option<TypeRef>,
23}
24
25/// Data about the generic parameters of a function, struct, impl, etc.
26#[derive(Clone, PartialEq, Eq, Debug)]
27pub struct GenericParams {
28 pub parent_params: Option<Arc<GenericParams>>,
29 pub params: Vec<GenericParam>,
30 pub where_predicates: Vec<WherePredicate>,
31}
32
33/// A single predicate from a where clause, i.e. `where Type: Trait`. Combined
34/// where clauses like `where T: Foo + Bar` are turned into multiple of these.
35/// It might still result in multiple actual predicates though, because of
36/// associated type bindings like `Iterator<Item = u32>`.
37#[derive(Clone, PartialEq, Eq, Debug)]
38pub struct WherePredicate {
39 pub type_ref: TypeRef,
40 pub bound: TypeBound,
41}
42
43impl GenericParams {
44 pub(crate) fn generic_params_query(
45 db: &impl DefDatabase2,
46 def: GenericDefId,
47 ) -> Arc<GenericParams> {
48 let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it));
49 Arc::new(GenericParams::new(db, def.into(), parent_generics))
50 }
51
52 fn new(
53 db: &impl DefDatabase2,
54 def: GenericDefId,
55 parent_params: Option<Arc<GenericParams>>,
56 ) -> GenericParams {
57 let mut generics =
58 GenericParams { params: Vec::new(), parent_params, where_predicates: Vec::new() };
59 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
60 // FIXME: add `: Sized` bound for everything except for `Self` in traits
61 match def {
62 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start),
63 GenericDefId::AdtId(AdtId::StructId(it)) => {
64 generics.fill(&it.0.source(db).value, start)
65 }
66 GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.0.source(db).value, start),
67 GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start),
68 GenericDefId::TraitId(it) => {
69 // traits get the Self type as an implicit first type parameter
70 generics.params.push(GenericParam {
71 idx: start,
72 name: name::SELF_TYPE,
73 default: None,
74 });
75 generics.fill(&it.source(db).value, start + 1);
76 // add super traits as bounds on Self
77 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
78 let self_param = TypeRef::Path(name::SELF_TYPE.into());
79 generics.fill_bounds(&it.source(db).value, self_param);
80 }
81 GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start),
82 // Note that we don't add `Self` here: in `impl`s, `Self` is not a
83 // type-parameter, but rather is a type-alias for impl's target
84 // type, so this is handled by the resolver.
85 GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start),
86 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {}
87 }
88
89 generics
90 }
91
92 fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) {
93 if let Some(params) = node.type_param_list() {
94 self.fill_params(params, start)
95 }
96 if let Some(where_clause) = node.where_clause() {
97 self.fill_where_predicates(where_clause);
98 }
99 }
100
101 fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) {
102 for bound in
103 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
104 {
105 self.add_where_predicate_from_bound(bound, type_ref.clone());
106 }
107 }
108
109 fn fill_params(&mut self, params: ast::TypeParamList, start: u32) {
110 for (idx, type_param) in params.type_params().enumerate() {
111 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
112 // FIXME: Use `Path::from_src`
113 let default = type_param.default_type().map(TypeRef::from_ast);
114 let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default };
115 self.params.push(param);
116
117 let type_ref = TypeRef::Path(name.into());
118 self.fill_bounds(&type_param, type_ref);
119 }
120 }
121
122 fn fill_where_predicates(&mut self, where_clause: ast::WhereClause) {
123 for pred in where_clause.predicates() {
124 let type_ref = match pred.type_ref() {
125 Some(type_ref) => type_ref,
126 None => continue,
127 };
128 let type_ref = TypeRef::from_ast(type_ref);
129 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
130 self.add_where_predicate_from_bound(bound, type_ref.clone());
131 }
132 }
133 }
134
135 fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) {
136 if bound.has_question_mark() {
137 // FIXME: remove this bound
138 return;
139 }
140 let bound = TypeBound::from_ast(bound);
141 self.where_predicates.push(WherePredicate { type_ref, bound });
142 }
143
144 pub fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
145 self.params.iter().find(|p| &p.name == name)
146 }
147
148 pub fn count_parent_params(&self) -> usize {
149 self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0)
150 }
151
152 pub fn count_params_including_parent(&self) -> usize {
153 let parent_count = self.count_parent_params();
154 parent_count + self.params.len()
155 }
156
157 fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) {
158 if let Some(parent) = &self.parent_params {
159 parent.for_each_param(f);
160 }
161 self.params.iter().for_each(f);
162 }
163
164 pub fn params_including_parent(&self) -> Vec<&GenericParam> {
165 let mut vec = Vec::with_capacity(self.count_params_including_parent());
166 self.for_each_param(&mut |p| vec.push(p));
167 vec
168 }
169}
170
171fn parent_generic_def(db: &impl DefDatabase2, def: GenericDefId) -> Option<GenericDefId> {
172 let container = match def {
173 GenericDefId::FunctionId(it) => it.lookup(db).container,
174 GenericDefId::TypeAliasId(it) => it.lookup(db).container,
175 GenericDefId::ConstId(it) => it.lookup(db).container,
176 GenericDefId::EnumVariantId(it) => return Some(it.parent.into()),
177 GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None,
178 };
179
180 match container {
181 ContainerId::ImplId(it) => Some(it.into()),
182 ContainerId::TraitId(it) => Some(it.into()),
183 ContainerId::ModuleId(_) => None,
184 }
185}
diff --git a/crates/ra_hir_def/src/imp.rs b/crates/ra_hir_def/src/impls.rs
index 717991c40..750a869f2 100644
--- a/crates/ra_hir_def/src/imp.rs
+++ b/crates/ra_hir_def/src/impls.rs
@@ -5,11 +5,12 @@
5 5
6use std::sync::Arc; 6use std::sync::Arc;
7 7
8use hir_expand::AstId;
8use ra_syntax::ast; 9use ra_syntax::ast;
9 10
10use crate::{ 11use crate::{
11 db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionId, ImplId, 12 db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstLoc, ContainerId,
12 LocationCtx, TypeAliasId, 13 FunctionLoc, ImplId, Intern, TypeAliasLoc,
13}; 14};
14 15
15#[derive(Debug, Clone, PartialEq, Eq)] 16#[derive(Debug, Clone, PartialEq, Eq)]
@@ -25,23 +26,37 @@ impl ImplData {
25 let src = id.source(db); 26 let src = id.source(db);
26 let items = db.ast_id_map(src.file_id); 27 let items = db.ast_id_map(src.file_id);
27 28
28 let target_trait = src.ast.target_trait().map(TypeRef::from_ast); 29 let target_trait = src.value.target_trait().map(TypeRef::from_ast);
29 let target_type = TypeRef::from_ast_opt(src.ast.target_type()); 30 let target_type = TypeRef::from_ast_opt(src.value.target_type());
30 let negative = src.ast.is_negative(); 31 let negative = src.value.is_negative();
31 32
32 let items = if let Some(item_list) = src.ast.item_list() { 33 let items = if let Some(item_list) = src.value.item_list() {
33 let ctx = LocationCtx::new(db, id.module(db), src.file_id);
34 item_list 34 item_list
35 .impl_items() 35 .impl_items()
36 .map(|item_node| match item_node { 36 .map(|item_node| match item_node {
37 ast::ImplItem::FnDef(it) => { 37 ast::ImplItem::FnDef(it) => {
38 FunctionId::from_ast_id(ctx, items.ast_id(&it)).into() 38 let def = FunctionLoc {
39 container: ContainerId::ImplId(id),
40 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
41 }
42 .intern(db);
43 def.into()
39 } 44 }
40 ast::ImplItem::ConstDef(it) => { 45 ast::ImplItem::ConstDef(it) => {
41 ConstId::from_ast_id(ctx, items.ast_id(&it)).into() 46 let def = ConstLoc {
47 container: ContainerId::ImplId(id),
48 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
49 }
50 .intern(db);
51 def.into()
42 } 52 }
43 ast::ImplItem::TypeAliasDef(it) => { 53 ast::ImplItem::TypeAliasDef(it) => {
44 TypeAliasId::from_ast_id(ctx, items.ast_id(&it)).into() 54 let def = TypeAliasLoc {
55 container: ContainerId::ImplId(id),
56 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
57 }
58 .intern(db);
59 def.into()
45 } 60 }
46 }) 61 })
47 .collect() 62 .collect()
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index a240a10b8..0af41de87 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -13,10 +13,12 @@ pub mod path;
13pub mod type_ref; 13pub mod type_ref;
14pub mod builtin_type; 14pub mod builtin_type;
15pub mod adt; 15pub mod adt;
16pub mod imp; 16pub mod impls;
17pub mod diagnostics; 17pub mod diagnostics;
18pub mod expr; 18pub mod expr;
19pub mod body; 19pub mod body;
20pub mod generics;
21pub mod traits;
20 22
21#[cfg(test)] 23#[cfg(test)]
22mod test_db; 24mod test_db;
@@ -80,7 +82,7 @@ impl ModuleSource {
80 82
81 pub fn from_child_node(db: &impl db::DefDatabase2, child: Source<&SyntaxNode>) -> ModuleSource { 83 pub fn from_child_node(db: &impl db::DefDatabase2, child: Source<&SyntaxNode>) -> ModuleSource {
82 if let Some(m) = 84 if let Some(m) =
83 child.ast.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) 85 child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi())
84 { 86 {
85 ModuleSource::Module(m) 87 ModuleSource::Module(m)
86 } else { 88 } else {
@@ -184,8 +186,8 @@ pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
184 } 186 }
185 fn source(self, db: &(impl AstDatabase + InternDatabase)) -> Source<N> { 187 fn source(self, db: &(impl AstDatabase + InternDatabase)) -> Source<N> {
186 let loc = self.lookup_intern(db); 188 let loc = self.lookup_intern(db);
187 let ast = loc.ast_id.to_node(db); 189 let value = loc.ast_id.to_node(db);
188 Source { file_id: loc.ast_id.file_id(), ast } 190 Source { file_id: loc.ast_id.file_id(), value }
189 } 191 }
190 fn module(self, db: &impl InternDatabase) -> ModuleId { 192 fn module(self, db: &impl InternDatabase) -> ModuleId {
191 let loc = self.lookup_intern(db); 193 let loc = self.lookup_intern(db);
@@ -197,12 +199,23 @@ pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
197pub struct FunctionId(salsa::InternId); 199pub struct FunctionId(salsa::InternId);
198impl_intern_key!(FunctionId); 200impl_intern_key!(FunctionId);
199 201
200impl AstItemDef<ast::FnDef> for FunctionId { 202#[derive(Debug, Clone, PartialEq, Eq, Hash)]
201 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::FnDef>) -> Self { 203pub struct FunctionLoc {
202 db.intern_function(loc) 204 pub container: ContainerId,
205 pub ast_id: AstId<ast::FnDef>,
206}
207
208impl Intern for FunctionLoc {
209 type ID = FunctionId;
210 fn intern(self, db: &impl db::DefDatabase2) -> FunctionId {
211 db.intern_function(self)
203 } 212 }
204 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::FnDef> { 213}
205 db.lookup_intern_function(self) 214
215impl Lookup for FunctionId {
216 type Data = FunctionLoc;
217 fn lookup(&self, db: &impl db::DefDatabase2) -> FunctionLoc {
218 db.lookup_intern_function(*self)
206 } 219 }
207} 220}
208 221
@@ -276,12 +289,23 @@ impl_arena_id!(LocalStructFieldId);
276#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 289#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
277pub struct ConstId(salsa::InternId); 290pub struct ConstId(salsa::InternId);
278impl_intern_key!(ConstId); 291impl_intern_key!(ConstId);
279impl AstItemDef<ast::ConstDef> for ConstId { 292#[derive(Debug, Clone, PartialEq, Eq, Hash)]
280 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::ConstDef>) -> Self { 293pub struct ConstLoc {
281 db.intern_const(loc) 294 pub container: ContainerId,
295 pub ast_id: AstId<ast::ConstDef>,
296}
297
298impl Intern for ConstLoc {
299 type ID = ConstId;
300 fn intern(self, db: &impl db::DefDatabase2) -> ConstId {
301 db.intern_const(self)
282 } 302 }
283 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::ConstDef> { 303}
284 db.lookup_intern_const(self) 304
305impl Lookup for ConstId {
306 type Data = ConstLoc;
307 fn lookup(&self, db: &impl db::DefDatabase2) -> ConstLoc {
308 db.lookup_intern_const(*self)
285 } 309 }
286} 310}
287 311
@@ -312,12 +336,24 @@ impl AstItemDef<ast::TraitDef> for TraitId {
312#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 336#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
313pub struct TypeAliasId(salsa::InternId); 337pub struct TypeAliasId(salsa::InternId);
314impl_intern_key!(TypeAliasId); 338impl_intern_key!(TypeAliasId);
315impl AstItemDef<ast::TypeAliasDef> for TypeAliasId { 339
316 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::TypeAliasDef>) -> Self { 340#[derive(Debug, Clone, PartialEq, Eq, Hash)]
317 db.intern_type_alias(loc) 341pub struct TypeAliasLoc {
342 pub container: ContainerId,
343 pub ast_id: AstId<ast::TypeAliasDef>,
344}
345
346impl Intern for TypeAliasLoc {
347 type ID = TypeAliasId;
348 fn intern(self, db: &impl db::DefDatabase2) -> TypeAliasId {
349 db.intern_type_alias(self)
318 } 350 }
319 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::TypeAliasDef> { 351}
320 db.lookup_intern_type_alias(self) 352
353impl Lookup for TypeAliasId {
354 type Data = TypeAliasLoc;
355 fn lookup(&self, db: &impl db::DefDatabase2) -> TypeAliasLoc {
356 db.lookup_intern_type_alias(*self)
321 } 357 }
322} 358}
323 359
@@ -352,6 +388,13 @@ macro_rules! impl_froms {
352 } 388 }
353} 389}
354 390
391#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
392pub enum ContainerId {
393 ModuleId(ModuleId),
394 ImplId(ImplId),
395 TraitId(TraitId),
396}
397
355/// A Data Type 398/// A Data Type
356#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 399#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
357pub enum AdtId { 400pub enum AdtId {
@@ -408,3 +451,102 @@ pub enum AssocItemId {
408// require not implementing From, and instead having some checked way of 451// require not implementing From, and instead having some checked way of
409// casting them, and somehow making the constructors private, which would be annoying. 452// casting them, and somehow making the constructors private, which would be annoying.
410impl_froms!(AssocItemId: FunctionId, ConstId, TypeAliasId); 453impl_froms!(AssocItemId: FunctionId, ConstId, TypeAliasId);
454
455#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
456pub enum GenericDefId {
457 FunctionId(FunctionId),
458 AdtId(AdtId),
459 TraitId(TraitId),
460 TypeAliasId(TypeAliasId),
461 ImplId(ImplId),
462 // enum variants cannot have generics themselves, but their parent enums
463 // can, and this makes some code easier to write
464 EnumVariantId(EnumVariantId),
465 // consts can have type parameters from their parents (i.e. associated consts of traits)
466 ConstId(ConstId),
467}
468impl_froms!(
469 GenericDefId: FunctionId,
470 AdtId(StructId, EnumId, UnionId),
471 TraitId,
472 TypeAliasId,
473 ImplId,
474 EnumVariantId,
475 ConstId
476);
477
478trait Intern {
479 type ID;
480 fn intern(self, db: &impl db::DefDatabase2) -> Self::ID;
481}
482
483pub trait Lookup {
484 type Data;
485 fn lookup(&self, db: &impl db::DefDatabase2) -> Self::Data;
486}
487
488pub trait HasModule {
489 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId;
490}
491
492impl HasModule for FunctionLoc {
493 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId {
494 match self.container {
495 ContainerId::ModuleId(it) => it,
496 ContainerId::ImplId(it) => it.module(db),
497 ContainerId::TraitId(it) => it.module(db),
498 }
499 }
500}
501
502impl HasModule for TypeAliasLoc {
503 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId {
504 match self.container {
505 ContainerId::ModuleId(it) => it,
506 ContainerId::ImplId(it) => it.module(db),
507 ContainerId::TraitId(it) => it.module(db),
508 }
509 }
510}
511
512impl HasModule for ConstLoc {
513 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId {
514 match self.container {
515 ContainerId::ModuleId(it) => it,
516 ContainerId::ImplId(it) => it.module(db),
517 ContainerId::TraitId(it) => it.module(db),
518 }
519 }
520}
521
522pub trait HasSource {
523 type Value;
524 fn source(&self, db: &impl db::DefDatabase2) -> Source<Self::Value>;
525}
526
527impl HasSource for FunctionLoc {
528 type Value = ast::FnDef;
529
530 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::FnDef> {
531 let node = self.ast_id.to_node(db);
532 Source::new(self.ast_id.file_id(), node)
533 }
534}
535
536impl HasSource for TypeAliasLoc {
537 type Value = ast::TypeAliasDef;
538
539 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::TypeAliasDef> {
540 let node = self.ast_id.to_node(db);
541 Source::new(self.ast_id.file_id(), node)
542 }
543}
544
545impl HasSource for ConstLoc {
546 type Value = ast::ConstDef;
547
548 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::ConstDef> {
549 let node = self.ast_id.to_node(db);
550 Source::new(self.ast_id.file_id(), node)
551 }
552}
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index e5b073a0f..c01e020ef 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -165,6 +165,14 @@ impl ModuleScope {
165 self.items.iter().chain(BUILTIN_SCOPE.iter()) 165 self.items.iter().chain(BUILTIN_SCOPE.iter())
166 } 166 }
167 167
168 pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
169 self.entries()
170 .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
171 .flat_map(|per_ns| {
172 per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
173 })
174 }
175
168 /// Iterate over all module scoped macros 176 /// Iterate over all module scoped macros
169 pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { 177 pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
170 self.items 178 self.items
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 8f426b097..aae3dcadf 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -19,9 +19,9 @@ use crate::{
19 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode, 19 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode,
20 }, 20 },
21 path::{Path, PathKind}, 21 path::{Path, PathKind},
22 AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionId, ImplId, 22 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, CrateModuleId, EnumId, EnumVariantId,
23 LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, StructOrUnionId, TraitId, TypeAliasId, 23 FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId,
24 UnionId, 24 StructOrUnionId, TraitId, TypeAliasLoc, UnionId,
25}; 25};
26 26
27pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { 27pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap {
@@ -673,8 +673,13 @@ where
673 let name = def.name.clone(); 673 let name = def.name.clone();
674 let def: PerNs = match def.kind { 674 let def: PerNs = match def.kind {
675 raw::DefKind::Function(ast_id) => { 675 raw::DefKind::Function(ast_id) => {
676 let f = FunctionId::from_ast_id(ctx, ast_id); 676 let def = FunctionLoc {
677 PerNs::values(f.into()) 677 container: ContainerId::ModuleId(module),
678 ast_id: AstId::new(self.file_id, ast_id),
679 }
680 .intern(self.def_collector.db);
681
682 PerNs::values(def.into())
678 } 683 }
679 raw::DefKind::Struct(ast_id) => { 684 raw::DefKind::Struct(ast_id) => {
680 let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); 685 let id = StructOrUnionId::from_ast_id(ctx, ast_id).into();
@@ -687,13 +692,27 @@ where
687 PerNs::both(u, u) 692 PerNs::both(u, u)
688 } 693 }
689 raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()), 694 raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()),
690 raw::DefKind::Const(ast_id) => PerNs::values(ConstId::from_ast_id(ctx, ast_id).into()), 695 raw::DefKind::Const(ast_id) => {
696 let def = ConstLoc {
697 container: ContainerId::ModuleId(module),
698 ast_id: AstId::new(self.file_id, ast_id),
699 }
700 .intern(self.def_collector.db);
701
702 PerNs::values(def.into())
703 }
691 raw::DefKind::Static(ast_id) => { 704 raw::DefKind::Static(ast_id) => {
692 PerNs::values(StaticId::from_ast_id(ctx, ast_id).into()) 705 PerNs::values(StaticId::from_ast_id(ctx, ast_id).into())
693 } 706 }
694 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()), 707 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()),
695 raw::DefKind::TypeAlias(ast_id) => { 708 raw::DefKind::TypeAlias(ast_id) => {
696 PerNs::types(TypeAliasId::from_ast_id(ctx, ast_id).into()) 709 let def = TypeAliasLoc {
710 container: ContainerId::ModuleId(module),
711 ast_id: AstId::new(self.file_id, ast_id),
712 }
713 .intern(self.def_collector.db);
714
715 PerNs::types(def.into())
697 } 716 }
698 }; 717 };
699 let resolution = Resolution { def, import: None }; 718 let resolution = Resolution { def, import: None };
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index a0a2c7273..7c68fd638 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -327,7 +327,7 @@ impl RawItemsCollector {
327 327
328 let mut buf = Vec::new(); 328 let mut buf = Vec::new();
329 Path::expand_use_item( 329 Path::expand_use_item(
330 Source { ast: use_item, file_id: self.file_id }, 330 Source { value: use_item, file_id: self.file_id },
331 &self.hygiene, 331 &self.hygiene,
332 |path, use_tree, is_glob, alias| { 332 |path, use_tree, is_glob, alias| {
333 let import_data = ImportData { 333 let import_data = ImportData {
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 04039376f..626ebffdc 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -71,7 +71,7 @@ impl Path {
71 hygiene: &Hygiene, 71 hygiene: &Hygiene,
72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>), 72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
73 ) { 73 ) {
74 if let Some(tree) = item_src.ast.use_tree() { 74 if let Some(tree) = item_src.value.use_tree() {
75 expand_use_tree(None, tree, hygiene, &mut cb); 75 expand_use_tree(None, tree, hygiene, &mut cb);
76 } 76 }
77 } 77 }
diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs
new file mode 100644
index 000000000..877d73d66
--- /dev/null
+++ b/crates/ra_hir_def/src/traits.rs
@@ -0,0 +1,59 @@
1//! HIR for trait definitions.
2
3use std::sync::Arc;
4
5use hir_expand::{
6 name::{AsName, Name},
7 AstId,
8};
9
10use ra_syntax::ast::{self, NameOwner};
11
12use crate::{
13 db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId,
14 TypeAliasLoc,
15};
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct TraitData {
19 pub name: Option<Name>,
20 pub items: Vec<AssocItemId>,
21 pub auto: bool,
22}
23
24impl TraitData {
25 pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc<TraitData> {
26 let src = tr.source(db);
27 let name = src.value.name().map(|n| n.as_name());
28 let auto = src.value.is_auto();
29 let ast_id_map = db.ast_id_map(src.file_id);
30 let items = if let Some(item_list) = src.value.item_list() {
31 item_list
32 .impl_items()
33 .map(|item_node| match item_node {
34 ast::ImplItem::FnDef(it) => FunctionLoc {
35 container: ContainerId::TraitId(tr),
36 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
37 }
38 .intern(db)
39 .into(),
40 ast::ImplItem::ConstDef(it) => ConstLoc {
41 container: ContainerId::TraitId(tr),
42 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
43 }
44 .intern(db)
45 .into(),
46 ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
47 container: ContainerId::TraitId(tr),
48 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
49 }
50 .intern(db)
51 .into(),
52 })
53 .collect()
54 } else {
55 Vec::new()
56 };
57 Arc::new(TraitData { name, items, auto })
58 }
59}