aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/code_model/src.rs12
-rw-r--r--crates/ra_hir_def/src/generics.rs93
2 files changed, 82 insertions, 23 deletions
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index 78a454082..8f04ebd23 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -9,8 +9,8 @@ use hir_def::{
9use ra_syntax::ast; 9use ra_syntax::ast;
10 10
11use crate::{ 11use crate::{
12 db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, ImplBlock, Import, MacroDef, 12 db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, GenericParam, ImplBlock,
13 Module, Static, Struct, StructField, Trait, TypeAlias, Union, 13 Import, MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, Union,
14}; 14};
15 15
16pub use hir_expand::InFile; 16pub use hir_expand::InFile;
@@ -129,3 +129,11 @@ impl HasSource for Import {
129 src.with_value(ptr.map_left(|it| it.to_node(&root)).map_right(|it| it.to_node(&root))) 129 src.with_value(ptr.map_left(|it| it.to_node(&root)).map_right(|it| it.to_node(&root)))
130 } 130 }
131} 131}
132
133impl HasSource for GenericParam {
134 type Ast = Either<ast::TraitDef, ast::TypeParam>;
135 fn source(self, db: &impl DefDatabase) -> InFile<Self::Ast> {
136 let child_source = self.id.parent.child_source(db);
137 child_source.map(|it| it[self.id.local_id].clone())
138 }
139}
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index b3e345082..0df5a20f5 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -4,12 +4,18 @@
4//! in rustc. 4//! in rustc.
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use hir_expand::name::{self, AsName, Name}; 7use either::Either;
8use ra_arena::Arena; 8use hir_expand::{
9 name::{self, AsName, Name},
10 InFile,
11};
12use ra_arena::{map::ArenaMap, Arena};
13use ra_db::FileId;
9use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; 14use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
10 15
11use crate::{ 16use crate::{
12 db::DefDatabase, 17 db::DefDatabase,
18 src::HasChildSource,
13 src::HasSource, 19 src::HasSource,
14 type_ref::{TypeBound, TypeRef}, 20 type_ref::{TypeBound, TypeRef},
15 AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup, 21 AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup,
@@ -39,46 +45,81 @@ pub struct WherePredicate {
39 pub bound: TypeBound, 45 pub bound: TypeBound,
40} 46}
41 47
48type SourceMap = ArenaMap<LocalGenericParamId, Either<ast::TraitDef, ast::TypeParam>>;
49
42impl GenericParams { 50impl GenericParams {
43 pub(crate) fn generic_params_query( 51 pub(crate) fn generic_params_query(
44 db: &impl DefDatabase, 52 db: &impl DefDatabase,
45 def: GenericDefId, 53 def: GenericDefId,
46 ) -> Arc<GenericParams> { 54 ) -> Arc<GenericParams> {
47 Arc::new(GenericParams::new(db, def.into())) 55 let (params, _source_map) = GenericParams::new(db, def.into());
56 Arc::new(params)
48 } 57 }
49 58
50 fn new(db: &impl DefDatabase, def: GenericDefId) -> GenericParams { 59 fn new(db: &impl DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
51 let mut generics = GenericParams { params: Arena::default(), where_predicates: Vec::new() }; 60 let mut generics = GenericParams { params: Arena::default(), where_predicates: Vec::new() };
61 let mut sm = ArenaMap::default();
52 // FIXME: add `: Sized` bound for everything except for `Self` in traits 62 // FIXME: add `: Sized` bound for everything except for `Self` in traits
53 match def { 63 let file_id = match def {
54 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value), 64 GenericDefId::FunctionId(it) => {
55 GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value), 65 let src = it.lookup(db).source(db);
56 GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value), 66 generics.fill(&mut sm, &src.value);
57 GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value), 67 src.file_id
68 }
69 GenericDefId::AdtId(AdtId::StructId(it)) => {
70 let src = it.source(db);
71 generics.fill(&mut sm, &src.value);
72 src.file_id
73 }
74 GenericDefId::AdtId(AdtId::UnionId(it)) => {
75 let src = it.source(db);
76 generics.fill(&mut sm, &src.value);
77 src.file_id
78 }
79 GenericDefId::AdtId(AdtId::EnumId(it)) => {
80 let src = it.source(db);
81 generics.fill(&mut sm, &src.value);
82 src.file_id
83 }
58 GenericDefId::TraitId(it) => { 84 GenericDefId::TraitId(it) => {
85 let src = it.source(db);
86
59 // traits get the Self type as an implicit first type parameter 87 // traits get the Self type as an implicit first type parameter
60 generics.params.alloc(GenericParamData { name: name::SELF_TYPE, default: None }); 88 let self_param_id = generics
89 .params
90 .alloc(GenericParamData { name: name::SELF_TYPE, default: None });
91 sm.insert(self_param_id, Either::Left(src.value.clone()));
61 // add super traits as bounds on Self 92 // add super traits as bounds on Self
62 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 93 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
63 let self_param = TypeRef::Path(name::SELF_TYPE.into()); 94 let self_param = TypeRef::Path(name::SELF_TYPE.into());
64 generics.fill_bounds(&it.source(db).value, self_param); 95 generics.fill_bounds(&src.value, self_param);
65 96
66 generics.fill(&it.source(db).value); 97 generics.fill(&mut sm, &src.value);
98 src.file_id
99 }
100 GenericDefId::TypeAliasId(it) => {
101 let src = it.lookup(db).source(db);
102 generics.fill(&mut sm, &src.value);
103 src.file_id
67 } 104 }
68 GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value),
69 // Note that we don't add `Self` here: in `impl`s, `Self` is not a 105 // Note that we don't add `Self` here: in `impl`s, `Self` is not a
70 // type-parameter, but rather is a type-alias for impl's target 106 // type-parameter, but rather is a type-alias for impl's target
71 // type, so this is handled by the resolver. 107 // type, so this is handled by the resolver.
72 GenericDefId::ImplId(it) => generics.fill(&it.source(db).value), 108 GenericDefId::ImplId(it) => {
73 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} 109 let src = it.source(db);
74 } 110 generics.fill(&mut sm, &src.value);
111 src.file_id
112 }
113 // We won't be using this ID anyway
114 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(),
115 };
75 116
76 generics 117 (generics, InFile::new(file_id, sm))
77 } 118 }
78 119
79 fn fill(&mut self, node: &dyn TypeParamsOwner) { 120 fn fill(&mut self, sm: &mut SourceMap, node: &dyn TypeParamsOwner) {
80 if let Some(params) = node.type_param_list() { 121 if let Some(params) = node.type_param_list() {
81 self.fill_params(params) 122 self.fill_params(sm, params)
82 } 123 }
83 if let Some(where_clause) = node.where_clause() { 124 if let Some(where_clause) = node.where_clause() {
84 self.fill_where_predicates(where_clause); 125 self.fill_where_predicates(where_clause);
@@ -93,13 +134,14 @@ impl GenericParams {
93 } 134 }
94 } 135 }
95 136
96 fn fill_params(&mut self, params: ast::TypeParamList) { 137 fn fill_params(&mut self, sm: &mut SourceMap, params: ast::TypeParamList) {
97 for type_param in params.type_params() { 138 for type_param in params.type_params() {
98 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); 139 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
99 // FIXME: Use `Path::from_src` 140 // FIXME: Use `Path::from_src`
100 let default = type_param.default_type().map(TypeRef::from_ast); 141 let default = type_param.default_type().map(TypeRef::from_ast);
101 let param = GenericParamData { name: name.clone(), default }; 142 let param = GenericParamData { name: name.clone(), default };
102 self.params.alloc(param); 143 let param_id = self.params.alloc(param);
144 sm.insert(param_id, Either::Right(type_param.clone()));
103 145
104 let type_ref = TypeRef::Path(name.into()); 146 let type_ref = TypeRef::Path(name.into());
105 self.fill_bounds(&type_param, type_ref); 147 self.fill_bounds(&type_param, type_ref);
@@ -132,3 +174,12 @@ impl GenericParams {
132 self.params.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) 174 self.params.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None })
133 } 175 }
134} 176}
177
178impl HasChildSource for GenericDefId {
179 type ChildId = LocalGenericParamId;
180 type Value = Either<ast::TraitDef, ast::TypeParam>;
181 fn child_source(&self, db: &impl DefDatabase) -> InFile<SourceMap> {
182 let (_, sm) = GenericParams::new(db, *self);
183 sm
184 }
185}