aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/body.rs6
-rw-r--r--crates/ra_hir_def/src/child_by_source.rs139
-rw-r--r--crates/ra_hir_def/src/child_from_source.rs276
-rw-r--r--crates/ra_hir_def/src/dyn_map.rs108
-rw-r--r--crates/ra_hir_def/src/generics.rs171
-rw-r--r--crates/ra_hir_def/src/keys.rs49
-rw-r--r--crates/ra_hir_def/src/lib.rs29
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs4
-rw-r--r--crates/ra_hir_def/src/per_ns.rs2
-rw-r--r--crates/ra_hir_def/src/resolver.rs38
10 files changed, 446 insertions, 376 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 7b385f3fd..b3bc336cf 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -6,9 +6,7 @@ pub mod scope;
6use std::{ops::Index, sync::Arc}; 6use std::{ops::Index, sync::Arc};
7 7
8use either::Either; 8use either::Either;
9use hir_expand::{ 9use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId};
10 hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId, MacroFileKind,
11};
12use ra_arena::{map::ArenaMap, Arena}; 10use ra_arena::{map::ArenaMap, Arena};
13use ra_syntax::{ast, AstNode, AstPtr}; 11use ra_syntax::{ast, AstNode, AstPtr};
14use rustc_hash::FxHashMap; 12use rustc_hash::FxHashMap;
@@ -49,7 +47,7 @@ impl Expander {
49 if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { 47 if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) {
50 if let Some(def) = self.resolve_path_as_macro(db, &path) { 48 if let Some(def) = self.resolve_path_as_macro(db, &path) {
51 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); 49 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id));
52 let file_id = call_id.as_file(MacroFileKind::Expr); 50 let file_id = call_id.as_file();
53 if let Some(node) = db.parse_or_expand(file_id) { 51 if let Some(node) = db.parse_or_expand(file_id) {
54 if let Some(expr) = ast::Expr::cast(node) { 52 if let Some(expr) = ast::Expr::cast(node) {
55 log::debug!("macro expansion {:#?}", expr.syntax()); 53 log::debug!("macro expansion {:#?}", expr.syntax());
diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs
new file mode 100644
index 000000000..a3574a9db
--- /dev/null
+++ b/crates/ra_hir_def/src/child_by_source.rs
@@ -0,0 +1,139 @@
1//! When *constructing* `hir`, we start at some parent syntax node and recursively
2//! lower the children.
3//!
4//! This modules allows one to go in the opposite direction: start with a syntax
5//! node for a *child*, and get its hir.
6
7use either::Either;
8
9use crate::{
10 db::DefDatabase,
11 dyn_map::DynMap,
12 keys,
13 src::{HasChildSource, HasSource},
14 AssocItemId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, ModuleId, StructFieldId,
15 TraitId, VariantId,
16};
17
18pub trait ChildBySource {
19 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap;
20}
21
22impl ChildBySource for TraitId {
23 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
24 let mut res = DynMap::default();
25
26 let data = db.trait_data(*self);
27 for (_name, item) in data.items.iter() {
28 match *item {
29 AssocItemId::FunctionId(func) => {
30 let src = func.lookup(db).source(db);
31 res[keys::FUNCTION].insert(src, func)
32 }
33 AssocItemId::ConstId(konst) => {
34 let src = konst.lookup(db).source(db);
35 res[keys::CONST].insert(src, konst)
36 }
37 AssocItemId::TypeAliasId(ty) => {
38 let src = ty.lookup(db).source(db);
39 res[keys::TYPE_ALIAS].insert(src, ty)
40 }
41 }
42 }
43
44 res
45 }
46}
47
48impl ChildBySource for ImplId {
49 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
50 let mut res = DynMap::default();
51
52 let data = db.impl_data(*self);
53 for &item in data.items.iter() {
54 match item {
55 AssocItemId::FunctionId(func) => {
56 let src = func.lookup(db).source(db);
57 res[keys::FUNCTION].insert(src, func)
58 }
59 AssocItemId::ConstId(konst) => {
60 let src = konst.lookup(db).source(db);
61 res[keys::CONST].insert(src, konst)
62 }
63 AssocItemId::TypeAliasId(ty) => {
64 let src = ty.lookup(db).source(db);
65 res[keys::TYPE_ALIAS].insert(src, ty)
66 }
67 }
68 }
69
70 res
71 }
72}
73
74impl ChildBySource for ModuleId {
75 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
76 let mut res = DynMap::default();
77
78 let crate_def_map = db.crate_def_map(self.krate);
79 for item in crate_def_map[self.local_id].scope.declarations() {
80 match item {
81 ModuleDefId::FunctionId(func) => {
82 let src = func.lookup(db).source(db);
83 res[keys::FUNCTION].insert(src, func)
84 }
85 ModuleDefId::ConstId(konst) => {
86 let src = konst.lookup(db).source(db);
87 res[keys::CONST].insert(src, konst)
88 }
89 ModuleDefId::StaticId(statik) => {
90 let src = statik.lookup(db).source(db);
91 res[keys::STATIC].insert(src, statik)
92 }
93 ModuleDefId::TypeAliasId(ty) => {
94 let src = ty.lookup(db).source(db);
95 res[keys::TYPE_ALIAS].insert(src, ty)
96 }
97 _ => (),
98 }
99 }
100
101 res
102 }
103}
104
105impl ChildBySource for VariantId {
106 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
107 let mut res = DynMap::default();
108
109 let arena_map = self.child_source(db);
110 let arena_map = arena_map.as_ref();
111 for (local_id, source) in arena_map.value.iter() {
112 let id = StructFieldId { parent: *self, local_id };
113 match source {
114 Either::Left(source) => {
115 res[keys::TUPLE_FIELD].insert(arena_map.with_value(source.clone()), id)
116 }
117 Either::Right(source) => {
118 res[keys::RECORD_FIELD].insert(arena_map.with_value(source.clone()), id)
119 }
120 }
121 }
122 res
123 }
124}
125
126impl ChildBySource for EnumId {
127 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
128 let mut res = DynMap::default();
129
130 let arena_map = self.child_source(db);
131 let arena_map = arena_map.as_ref();
132 for (local_id, source) in arena_map.value.iter() {
133 let id = EnumVariantId { parent: *self, local_id };
134 res[keys::ENUM_VARIANT].insert(arena_map.with_value(source.clone()), id)
135 }
136
137 res
138 }
139}
diff --git a/crates/ra_hir_def/src/child_from_source.rs b/crates/ra_hir_def/src/child_from_source.rs
deleted file mode 100644
index 37d4b7870..000000000
--- a/crates/ra_hir_def/src/child_from_source.rs
+++ /dev/null
@@ -1,276 +0,0 @@
1//! When *constructing* `hir`, we start at some parent syntax node and recursively
2//! lower the children.
3//!
4//! This modules allows one to go in the opposite direction: start with a syntax
5//! node for a *child*, and get its hir.
6
7use either::Either;
8use hir_expand::InFile;
9use ra_syntax::{ast, AstNode, AstPtr};
10
11use crate::{
12 db::DefDatabase,
13 src::{HasChildSource, HasSource},
14 AssocItemId, ConstId, EnumId, EnumVariantId, FunctionId, ImplId, Lookup, ModuleDefId, ModuleId,
15 StaticId, StructFieldId, TraitId, TypeAliasId, VariantId,
16};
17
18pub trait ChildFromSource<CHILD, SOURCE> {
19 fn child_from_source(
20 &self,
21 db: &impl DefDatabase,
22 child_source: InFile<SOURCE>,
23 ) -> Option<CHILD>;
24}
25
26impl ChildFromSource<FunctionId, ast::FnDef> for TraitId {
27 fn child_from_source(
28 &self,
29 db: &impl DefDatabase,
30 child_source: InFile<ast::FnDef>,
31 ) -> Option<FunctionId> {
32 let data = db.trait_data(*self);
33 data.items
34 .iter()
35 .filter_map(|(_, item)| match item {
36 AssocItemId::FunctionId(it) => Some(*it),
37 _ => None,
38 })
39 .find(|func| {
40 let source = func.lookup(db).source(db);
41 same_source(&source, &child_source)
42 })
43 }
44}
45
46impl ChildFromSource<FunctionId, ast::FnDef> for ImplId {
47 fn child_from_source(
48 &self,
49 db: &impl DefDatabase,
50 child_source: InFile<ast::FnDef>,
51 ) -> Option<FunctionId> {
52 let data = db.impl_data(*self);
53 data.items
54 .iter()
55 .filter_map(|item| match item {
56 AssocItemId::FunctionId(it) => Some(*it),
57 _ => None,
58 })
59 .find(|func| {
60 let source = func.lookup(db).source(db);
61 same_source(&source, &child_source)
62 })
63 }
64}
65
66impl ChildFromSource<FunctionId, ast::FnDef> for ModuleId {
67 fn child_from_source(
68 &self,
69 db: &impl DefDatabase,
70 child_source: InFile<ast::FnDef>,
71 ) -> Option<FunctionId> {
72 let crate_def_map = db.crate_def_map(self.krate);
73 let res = crate_def_map[self.local_id]
74 .scope
75 .declarations()
76 .filter_map(|item| match item {
77 ModuleDefId::FunctionId(it) => Some(it),
78 _ => None,
79 })
80 .find(|func| {
81 let source = func.lookup(db).source(db);
82 same_source(&source, &child_source)
83 });
84 res
85 }
86}
87
88impl ChildFromSource<ConstId, ast::ConstDef> for TraitId {
89 fn child_from_source(
90 &self,
91 db: &impl DefDatabase,
92 child_source: InFile<ast::ConstDef>,
93 ) -> Option<ConstId> {
94 let data = db.trait_data(*self);
95 data.items
96 .iter()
97 .filter_map(|(_, item)| match item {
98 AssocItemId::ConstId(it) => Some(*it),
99 _ => None,
100 })
101 .find(|func| {
102 let source = func.lookup(db).source(db);
103 same_source(&source, &child_source)
104 })
105 }
106}
107
108impl ChildFromSource<ConstId, ast::ConstDef> for ImplId {
109 fn child_from_source(
110 &self,
111 db: &impl DefDatabase,
112 child_source: InFile<ast::ConstDef>,
113 ) -> Option<ConstId> {
114 let data = db.impl_data(*self);
115 data.items
116 .iter()
117 .filter_map(|item| match item {
118 AssocItemId::ConstId(it) => Some(*it),
119 _ => None,
120 })
121 .find(|func| {
122 let source = func.lookup(db).source(db);
123 same_source(&source, &child_source)
124 })
125 }
126}
127
128impl ChildFromSource<ConstId, ast::ConstDef> for ModuleId {
129 fn child_from_source(
130 &self,
131 db: &impl DefDatabase,
132 child_source: InFile<ast::ConstDef>,
133 ) -> Option<ConstId> {
134 let crate_def_map = db.crate_def_map(self.krate);
135 let res = crate_def_map[self.local_id]
136 .scope
137 .declarations()
138 .filter_map(|item| match item {
139 ModuleDefId::ConstId(it) => Some(it),
140 _ => None,
141 })
142 .find(|func| {
143 let source = func.lookup(db).source(db);
144 same_source(&source, &child_source)
145 });
146 res
147 }
148}
149
150impl ChildFromSource<TypeAliasId, ast::TypeAliasDef> for TraitId {
151 fn child_from_source(
152 &self,
153 db: &impl DefDatabase,
154 child_source: InFile<ast::TypeAliasDef>,
155 ) -> Option<TypeAliasId> {
156 let data = db.trait_data(*self);
157 data.items
158 .iter()
159 .filter_map(|(_, item)| match item {
160 AssocItemId::TypeAliasId(it) => Some(*it),
161 _ => None,
162 })
163 .find(|func| {
164 let source = func.lookup(db).source(db);
165 same_source(&source, &child_source)
166 })
167 }
168}
169
170impl ChildFromSource<TypeAliasId, ast::TypeAliasDef> for ImplId {
171 fn child_from_source(
172 &self,
173 db: &impl DefDatabase,
174 child_source: InFile<ast::TypeAliasDef>,
175 ) -> Option<TypeAliasId> {
176 let data = db.impl_data(*self);
177 data.items
178 .iter()
179 .filter_map(|item| match item {
180 AssocItemId::TypeAliasId(it) => Some(*it),
181 _ => None,
182 })
183 .find(|func| {
184 let source = func.lookup(db).source(db);
185 same_source(&source, &child_source)
186 })
187 }
188}
189
190impl ChildFromSource<TypeAliasId, ast::TypeAliasDef> for ModuleId {
191 fn child_from_source(
192 &self,
193 db: &impl DefDatabase,
194 child_source: InFile<ast::TypeAliasDef>,
195 ) -> Option<TypeAliasId> {
196 let crate_def_map = db.crate_def_map(self.krate);
197 let res = crate_def_map[self.local_id]
198 .scope
199 .declarations()
200 .filter_map(|item| match item {
201 ModuleDefId::TypeAliasId(it) => Some(it),
202 _ => None,
203 })
204 .find(|func| {
205 let source = func.lookup(db).source(db);
206 same_source(&source, &child_source)
207 });
208 res
209 }
210}
211
212impl ChildFromSource<StaticId, ast::StaticDef> for ModuleId {
213 fn child_from_source(
214 &self,
215 db: &impl DefDatabase,
216 child_source: InFile<ast::StaticDef>,
217 ) -> Option<StaticId> {
218 let crate_def_map = db.crate_def_map(self.krate);
219 let res = crate_def_map[self.local_id]
220 .scope
221 .declarations()
222 .filter_map(|item| match item {
223 ModuleDefId::StaticId(it) => Some(it),
224 _ => None,
225 })
226 .find(|func| {
227 let source = func.lookup(db).source(db);
228 same_source(&source, &child_source)
229 });
230 res
231 }
232}
233
234impl ChildFromSource<StructFieldId, Either<ast::TupleFieldDef, ast::RecordFieldDef>> for VariantId {
235 fn child_from_source(
236 &self,
237 db: &impl DefDatabase,
238 child_source: InFile<Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
239 ) -> Option<StructFieldId> {
240 let arena_map = self.child_source(db);
241 let (local_id, _) = arena_map.as_ref().value.iter().find(|(_local_id, source)| {
242 child_source.file_id == arena_map.file_id
243 && match (source, &child_source.value) {
244 (Either::Left(a), Either::Left(b)) => AstPtr::new(a) == AstPtr::new(b),
245 (Either::Right(a), Either::Right(b)) => AstPtr::new(a) == AstPtr::new(b),
246 _ => false,
247 }
248 })?;
249 Some(StructFieldId { parent: *self, local_id })
250 }
251}
252
253impl ChildFromSource<EnumVariantId, ast::EnumVariant> for EnumId {
254 fn child_from_source(
255 &self,
256 db: &impl DefDatabase,
257 child_source: InFile<ast::EnumVariant>,
258 ) -> Option<EnumVariantId> {
259 let arena_map = self.child_source(db);
260 let (local_id, _) = arena_map.as_ref().value.iter().find(|(_local_id, source)| {
261 child_source.file_id == arena_map.file_id
262 && AstPtr::new(*source) == AstPtr::new(&child_source.value)
263 })?;
264 Some(EnumVariantId { parent: *self, local_id })
265 }
266}
267
268/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
269/// equal if they point to exactly the same object.
270///
271/// In general, we do not guarantee that we have exactly one instance of a
272/// syntax tree for each file. We probably should add such guarantee, but, for
273/// the time being, we will use identity-less AstPtr comparison.
274fn same_source<N: AstNode>(s1: &InFile<N>, s2: &InFile<N>) -> bool {
275 s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new)
276}
diff --git a/crates/ra_hir_def/src/dyn_map.rs b/crates/ra_hir_def/src/dyn_map.rs
new file mode 100644
index 000000000..6f269d7b0
--- /dev/null
+++ b/crates/ra_hir_def/src/dyn_map.rs
@@ -0,0 +1,108 @@
1//! This module defines a `DynMap` -- a container for heterogeneous maps.
2//!
3//! This means that `DynMap` stores a bunch of hash maps inside, and those maps
4//! can be of different types.
5//!
6//! It is used like this:
7//!
8//! ```
9//! // keys define submaps of a `DynMap`
10//! const STRING_TO_U32: Key<String, u32> = Key::new();
11//! const U32_TO_VEC: Key<u32, Vec<bool>> = Key::new();
12//!
13//! // Note: concrete type, no type params!
14//! let mut map = DynMap::new();
15//!
16//! // To access a specific map, index the `DynMap` by `Key`:
17//! map[STRING_TO_U32].insert("hello".to_string(), 92);
18//! let value = map[U32_TO_VEC].get(92);
19//! assert!(value.is_none());
20//! ```
21//!
22//! This is a work of fiction. Any similarities to Kotlin's `BindingContext` are
23//! a coincidence.
24use std::{
25 hash::Hash,
26 marker::PhantomData,
27 ops::{Index, IndexMut},
28};
29
30use anymap::Map;
31use rustc_hash::FxHashMap;
32
33pub struct Key<K, V, P = (K, V)> {
34 _phantom: PhantomData<(K, V, P)>,
35}
36
37impl<K, V, P> Key<K, V, P> {
38 pub(crate) const fn new() -> Key<K, V, P> {
39 Key { _phantom: PhantomData }
40 }
41}
42
43impl<K, V, P> Copy for Key<K, V, P> {}
44
45impl<K, V, P> Clone for Key<K, V, P> {
46 fn clone(&self) -> Key<K, V, P> {
47 *self
48 }
49}
50
51pub trait Policy {
52 type K;
53 type V;
54
55 fn insert(map: &mut DynMap, key: Self::K, value: Self::V);
56 fn get<'a>(map: &'a DynMap, key: &Self::K) -> Option<&'a Self::V>;
57}
58
59impl<K: Hash + Eq + 'static, V: 'static> Policy for (K, V) {
60 type K = K;
61 type V = V;
62 fn insert(map: &mut DynMap, key: K, value: V) {
63 map.map.entry::<FxHashMap<K, V>>().or_insert_with(Default::default).insert(key, value);
64 }
65 fn get<'a>(map: &'a DynMap, key: &K) -> Option<&'a V> {
66 map.map.get::<FxHashMap<K, V>>()?.get(key)
67 }
68}
69
70pub struct DynMap {
71 pub(crate) map: Map,
72}
73
74impl Default for DynMap {
75 fn default() -> Self {
76 DynMap { map: Map::new() }
77 }
78}
79
80#[repr(transparent)]
81pub struct KeyMap<KEY> {
82 map: DynMap,
83 _phantom: PhantomData<KEY>,
84}
85
86impl<P: Policy> KeyMap<Key<P::K, P::V, P>> {
87 pub fn insert(&mut self, key: P::K, value: P::V) {
88 P::insert(&mut self.map, key, value)
89 }
90 pub fn get(&self, key: &P::K) -> Option<&P::V> {
91 P::get(&self.map, key)
92 }
93}
94
95impl<P: Policy> Index<Key<P::K, P::V, P>> for DynMap {
96 type Output = KeyMap<Key<P::K, P::V, P>>;
97 fn index(&self, _key: Key<P::K, P::V, P>) -> &Self::Output {
98 // Safe due to `#[repr(transparent)]`.
99 unsafe { std::mem::transmute::<&DynMap, &KeyMap<Key<P::K, P::V, P>>>(self) }
100 }
101}
102
103impl<P: Policy> IndexMut<Key<P::K, P::V, P>> for DynMap {
104 fn index_mut(&mut self, _key: Key<P::K, P::V, P>) -> &mut Self::Output {
105 // Safe due to `#[repr(transparent)]`.
106 unsafe { std::mem::transmute::<&mut DynMap, &mut KeyMap<Key<P::K, P::V, P>>>(self) }
107 }
108}
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index 5f648ffc3..976cf72d0 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -4,21 +4,29 @@
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 hir_expand::{
9 name::{self, AsName, Name},
10 InFile,
11};
12use ra_arena::{map::ArenaMap, Arena};
13use ra_db::FileId;
8use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; 14use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
9 15
10use crate::{ 16use crate::{
17 child_by_source::ChildBySource,
11 db::DefDatabase, 18 db::DefDatabase,
19 dyn_map::DynMap,
20 keys,
21 src::HasChildSource,
12 src::HasSource, 22 src::HasSource,
13 type_ref::{TypeBound, TypeRef}, 23 type_ref::{TypeBound, TypeRef},
14 AdtId, AstItemDef, ContainerId, GenericDefId, Lookup, 24 AdtId, AstItemDef, GenericDefId, LocalTypeParamId, Lookup, TypeParamId,
15}; 25};
16 26
17/// Data about a generic parameter (to a function, struct, impl, ...). 27/// Data about a generic parameter (to a function, struct, impl, ...).
18#[derive(Clone, PartialEq, Eq, Debug)] 28#[derive(Clone, PartialEq, Eq, Debug)]
19pub struct GenericParam { 29pub struct TypeParamData {
20 // FIXME: give generic params proper IDs
21 pub idx: u32,
22 pub name: Name, 30 pub name: Name,
23 pub default: Option<TypeRef>, 31 pub default: Option<TypeRef>,
24} 32}
@@ -26,8 +34,8 @@ pub struct GenericParam {
26/// Data about the generic parameters of a function, struct, impl, etc. 34/// Data about the generic parameters of a function, struct, impl, etc.
27#[derive(Clone, PartialEq, Eq, Debug)] 35#[derive(Clone, PartialEq, Eq, Debug)]
28pub struct GenericParams { 36pub struct GenericParams {
29 pub parent_params: Option<Arc<GenericParams>>, 37 pub types: Arena<LocalTypeParamId, TypeParamData>,
30 pub params: Vec<GenericParam>, 38 // lifetimes: Arena<LocalLifetimeParamId, LifetimeParamData>,
31 pub where_predicates: Vec<WherePredicate>, 39 pub where_predicates: Vec<WherePredicate>,
32} 40}
33 41
@@ -41,63 +49,87 @@ pub struct WherePredicate {
41 pub bound: TypeBound, 49 pub bound: TypeBound,
42} 50}
43 51
52type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>;
53
44impl GenericParams { 54impl GenericParams {
45 pub(crate) fn generic_params_query( 55 pub(crate) fn generic_params_query(
46 db: &impl DefDatabase, 56 db: &impl DefDatabase,
47 def: GenericDefId, 57 def: GenericDefId,
48 ) -> Arc<GenericParams> { 58 ) -> Arc<GenericParams> {
49 let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it)); 59 let (params, _source_map) = GenericParams::new(db, def.into());
50 Arc::new(GenericParams::new(db, def.into(), parent_generics)) 60 Arc::new(params)
51 } 61 }
52 62
53 fn new( 63 fn new(db: &impl DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
54 db: &impl DefDatabase, 64 let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() };
55 def: GenericDefId, 65 let mut sm = ArenaMap::default();
56 parent_params: Option<Arc<GenericParams>>,
57 ) -> GenericParams {
58 let mut generics =
59 GenericParams { params: Vec::new(), parent_params, where_predicates: Vec::new() };
60 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
61 // FIXME: add `: Sized` bound for everything except for `Self` in traits 66 // FIXME: add `: Sized` bound for everything except for `Self` in traits
62 match def { 67 let file_id = match def {
63 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start), 68 GenericDefId::FunctionId(it) => {
64 GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start), 69 let src = it.lookup(db).source(db);
65 GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start), 70 generics.fill(&mut sm, &src.value);
66 GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), 71 src.file_id
72 }
73 GenericDefId::AdtId(AdtId::StructId(it)) => {
74 let src = it.source(db);
75 generics.fill(&mut sm, &src.value);
76 src.file_id
77 }
78 GenericDefId::AdtId(AdtId::UnionId(it)) => {
79 let src = it.source(db);
80 generics.fill(&mut sm, &src.value);
81 src.file_id
82 }
83 GenericDefId::AdtId(AdtId::EnumId(it)) => {
84 let src = it.source(db);
85 generics.fill(&mut sm, &src.value);
86 src.file_id
87 }
67 GenericDefId::TraitId(it) => { 88 GenericDefId::TraitId(it) => {
89 let src = it.source(db);
90
68 // traits get the Self type as an implicit first type parameter 91 // traits get the Self type as an implicit first type parameter
69 generics.params.push(GenericParam { 92 let self_param_id =
70 idx: start, 93 generics.types.alloc(TypeParamData { name: name::SELF_TYPE, default: None });
71 name: name::SELF_TYPE, 94 sm.insert(self_param_id, Either::Left(src.value.clone()));
72 default: None,
73 });
74 generics.fill(&it.source(db).value, start + 1);
75 // add super traits as bounds on Self 95 // add super traits as bounds on Self
76 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 96 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
77 let self_param = TypeRef::Path(name::SELF_TYPE.into()); 97 let self_param = TypeRef::Path(name::SELF_TYPE.into());
78 generics.fill_bounds(&it.source(db).value, self_param); 98 generics.fill_bounds(&src.value, self_param);
99
100 generics.fill(&mut sm, &src.value);
101 src.file_id
102 }
103 GenericDefId::TypeAliasId(it) => {
104 let src = it.lookup(db).source(db);
105 generics.fill(&mut sm, &src.value);
106 src.file_id
79 } 107 }
80 GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start),
81 // Note that we don't add `Self` here: in `impl`s, `Self` is not a 108 // Note that we don't add `Self` here: in `impl`s, `Self` is not a
82 // type-parameter, but rather is a type-alias for impl's target 109 // type-parameter, but rather is a type-alias for impl's target
83 // type, so this is handled by the resolver. 110 // type, so this is handled by the resolver.
84 GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start), 111 GenericDefId::ImplId(it) => {
85 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} 112 let src = it.source(db);
86 } 113 generics.fill(&mut sm, &src.value);
114 src.file_id
115 }
116 // We won't be using this ID anyway
117 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(),
118 };
87 119
88 generics 120 (generics, InFile::new(file_id, sm))
89 } 121 }
90 122
91 fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { 123 fn fill(&mut self, sm: &mut SourceMap, node: &dyn TypeParamsOwner) {
92 if let Some(params) = node.type_param_list() { 124 if let Some(params) = node.type_param_list() {
93 self.fill_params(params, start) 125 self.fill_params(sm, params)
94 } 126 }
95 if let Some(where_clause) = node.where_clause() { 127 if let Some(where_clause) = node.where_clause() {
96 self.fill_where_predicates(where_clause); 128 self.fill_where_predicates(where_clause);
97 } 129 }
98 } 130 }
99 131
100 fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) { 132 fn fill_bounds(&mut self, node: &dyn ast::TypeBoundsOwner, type_ref: TypeRef) {
101 for bound in 133 for bound in
102 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) 134 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
103 { 135 {
@@ -105,13 +137,14 @@ impl GenericParams {
105 } 137 }
106 } 138 }
107 139
108 fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { 140 fn fill_params(&mut self, sm: &mut SourceMap, params: ast::TypeParamList) {
109 for (idx, type_param) in params.type_params().enumerate() { 141 for type_param in params.type_params() {
110 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); 142 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
111 // FIXME: Use `Path::from_src` 143 // FIXME: Use `Path::from_src`
112 let default = type_param.default_type().map(TypeRef::from_ast); 144 let default = type_param.default_type().map(TypeRef::from_ast);
113 let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; 145 let param = TypeParamData { name: name.clone(), default };
114 self.params.push(param); 146 let param_id = self.types.alloc(param);
147 sm.insert(param_id, Either::Right(type_param.clone()));
115 148
116 let type_ref = TypeRef::Path(name.into()); 149 let type_ref = TypeRef::Path(name.into());
117 self.fill_bounds(&type_param, type_ref); 150 self.fill_bounds(&type_param, type_ref);
@@ -140,45 +173,31 @@ impl GenericParams {
140 self.where_predicates.push(WherePredicate { type_ref, bound }); 173 self.where_predicates.push(WherePredicate { type_ref, bound });
141 } 174 }
142 175
143 pub fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { 176 pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> {
144 self.params.iter().find(|p| &p.name == name) 177 self.types.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None })
145 }
146
147 pub fn count_parent_params(&self) -> usize {
148 self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0)
149 }
150
151 pub fn count_params_including_parent(&self) -> usize {
152 let parent_count = self.count_parent_params();
153 parent_count + self.params.len()
154 }
155
156 fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) {
157 if let Some(parent) = &self.parent_params {
158 parent.for_each_param(f);
159 }
160 self.params.iter().for_each(f);
161 } 178 }
179}
162 180
163 pub fn params_including_parent(&self) -> Vec<&GenericParam> { 181impl HasChildSource for GenericDefId {
164 let mut vec = Vec::with_capacity(self.count_params_including_parent()); 182 type ChildId = LocalTypeParamId;
165 self.for_each_param(&mut |p| vec.push(p)); 183 type Value = Either<ast::TraitDef, ast::TypeParam>;
166 vec 184 fn child_source(&self, db: &impl DefDatabase) -> InFile<SourceMap> {
185 let (_, sm) = GenericParams::new(db, *self);
186 sm
167 } 187 }
168} 188}
169 189
170fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> { 190impl ChildBySource for GenericDefId {
171 let container = match def { 191 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
172 GenericDefId::FunctionId(it) => it.lookup(db).container, 192 let mut res = DynMap::default();
173 GenericDefId::TypeAliasId(it) => it.lookup(db).container, 193 let arena_map = self.child_source(db);
174 GenericDefId::ConstId(it) => it.lookup(db).container, 194 let arena_map = arena_map.as_ref();
175 GenericDefId::EnumVariantId(it) => return Some(it.parent.into()), 195 for (local_id, src) in arena_map.value.iter() {
176 GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None, 196 let id = TypeParamId { parent: *self, local_id };
177 }; 197 if let Either::Right(type_param) = src {
178 198 res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id)
179 match container { 199 }
180 ContainerId::ImplId(it) => Some(it.into()), 200 }
181 ContainerId::TraitId(it) => Some(it.into()), 201 res
182 ContainerId::ModuleId(_) => None,
183 } 202 }
184} 203}
diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs
new file mode 100644
index 000000000..be702a4f8
--- /dev/null
+++ b/crates/ra_hir_def/src/keys.rs
@@ -0,0 +1,49 @@
1//! keys to be used with `DynMap`
2
3use std::marker::PhantomData;
4
5use hir_expand::InFile;
6use ra_syntax::{ast, AstNode, AstPtr};
7use rustc_hash::FxHashMap;
8
9use crate::{
10 dyn_map::{DynMap, Policy},
11 ConstId, EnumVariantId, FunctionId, StaticId, StructFieldId, TypeAliasId, TypeParamId,
12};
13
14type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>;
15
16pub const FUNCTION: Key<ast::FnDef, FunctionId> = Key::new();
17pub const CONST: Key<ast::ConstDef, ConstId> = Key::new();
18pub const STATIC: Key<ast::StaticDef, StaticId> = Key::new();
19pub const ENUM_VARIANT: Key<ast::EnumVariant, EnumVariantId> = Key::new();
20pub const TYPE_ALIAS: Key<ast::TypeAliasDef, TypeAliasId> = Key::new();
21pub const TUPLE_FIELD: Key<ast::TupleFieldDef, StructFieldId> = Key::new();
22pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new();
23pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
24
25/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
26/// equal if they point to exactly the same object.
27///
28/// In general, we do not guarantee that we have exactly one instance of a
29/// syntax tree for each file. We probably should add such guarantee, but, for
30/// the time being, we will use identity-less AstPtr comparison.
31pub struct AstPtrPolicy<AST, ID> {
32 _phantom: PhantomData<(AST, ID)>,
33}
34
35impl<AST: AstNode + 'static, ID: 'static> Policy for AstPtrPolicy<AST, ID> {
36 type K = InFile<AST>;
37 type V = ID;
38 fn insert(map: &mut DynMap, key: InFile<AST>, value: ID) {
39 let key = key.as_ref().map(AstPtr::new);
40 map.map
41 .entry::<FxHashMap<InFile<AstPtr<AST>>, ID>>()
42 .or_insert_with(Default::default)
43 .insert(key, value);
44 }
45 fn get<'a>(map: &'a DynMap, key: &InFile<AST>) -> Option<&'a ID> {
46 let key = key.as_ref().map(AstPtr::new);
47 map.map.get::<FxHashMap<InFile<AstPtr<AST>>, ID>>()?.get(&key)
48 }
49}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index e02622f62..569da4f28 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -16,6 +16,9 @@ pub mod builtin_type;
16pub mod diagnostics; 16pub mod diagnostics;
17pub mod per_ns; 17pub mod per_ns;
18 18
19pub mod dyn_map;
20pub mod keys;
21
19pub mod adt; 22pub mod adt;
20pub mod data; 23pub mod data;
21pub mod generics; 24pub mod generics;
@@ -30,7 +33,7 @@ mod trace;
30pub mod nameres; 33pub mod nameres;
31 34
32pub mod src; 35pub mod src;
33pub mod child_from_source; 36pub mod child_by_source;
34 37
35#[cfg(test)] 38#[cfg(test)]
36mod test_db; 39mod test_db;
@@ -315,6 +318,16 @@ macro_rules! impl_froms {
315} 318}
316 319
317#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 320#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
321pub struct TypeParamId {
322 pub parent: GenericDefId,
323 pub local_id: LocalTypeParamId,
324}
325
326#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
327pub struct LocalTypeParamId(RawId);
328impl_arena_id!(LocalTypeParamId);
329
330#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
318pub enum ContainerId { 331pub enum ContainerId {
319 ModuleId(ModuleId), 332 ModuleId(ModuleId),
320 ImplId(ImplId), 333 ImplId(ImplId),
@@ -512,6 +525,20 @@ impl HasModule for DefWithBodyId {
512 } 525 }
513} 526}
514 527
528impl HasModule for GenericDefId {
529 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
530 match self {
531 GenericDefId::FunctionId(it) => it.lookup(db).module(db),
532 GenericDefId::AdtId(it) => it.module(db),
533 GenericDefId::TraitId(it) => it.module(db),
534 GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
535 GenericDefId::ImplId(it) => it.module(db),
536 GenericDefId::EnumVariantId(it) => it.parent.module(db),
537 GenericDefId::ConstId(it) => it.lookup(db).module(db),
538 }
539 }
540}
541
515impl HasModule for StaticLoc { 542impl HasModule for StaticLoc {
516 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { 543 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId {
517 self.container 544 self.container
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 3b3f30eec..3ff071f9e 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -7,7 +7,7 @@ use hir_expand::{
7 builtin_derive::find_builtin_derive, 7 builtin_derive::find_builtin_derive,
8 builtin_macro::find_builtin_macro, 8 builtin_macro::find_builtin_macro,
9 name::{self, AsName, Name}, 9 name::{self, AsName, Name},
10 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, MacroFileKind, 10 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
11}; 11};
12use ra_cfg::CfgOptions; 12use ra_cfg::CfgOptions;
13use ra_db::{CrateId, FileId}; 13use ra_db::{CrateId, FileId};
@@ -624,7 +624,7 @@ where
624 self.macro_stack_monitor.increase(macro_def_id); 624 self.macro_stack_monitor.increase(macro_def_id);
625 625
626 if !self.macro_stack_monitor.is_poison(macro_def_id) { 626 if !self.macro_stack_monitor.is_poison(macro_def_id) {
627 let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items); 627 let file_id: HirFileId = macro_call_id.as_file();
628 let raw_items = self.db.raw_items(file_id); 628 let raw_items = self.db.raw_items(file_id);
629 let mod_dir = self.mod_dirs[&module_id].clone(); 629 let mod_dir = self.mod_dirs[&module_id].clone();
630 ModCollector { 630 ModCollector {
diff --git a/crates/ra_hir_def/src/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs
index 00e866bf9..3a5105028 100644
--- a/crates/ra_hir_def/src/per_ns.rs
+++ b/crates/ra_hir_def/src/per_ns.rs
@@ -11,8 +11,6 @@ use crate::ModuleDefId;
11pub struct PerNs { 11pub struct PerNs {
12 pub types: Option<ModuleDefId>, 12 pub types: Option<ModuleDefId>,
13 pub values: Option<ModuleDefId>, 13 pub values: Option<ModuleDefId>,
14 /// Since macros has different type, many methods simply ignore it.
15 /// We can only use special method like `get_macros` to access it.
16 pub macros: Option<MacroDefId>, 14 pub macros: Option<MacroDefId>,
17} 15}
18 16
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 7d4df222e..4c859e497 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -19,11 +19,12 @@ use crate::{
19 per_ns::PerNs, 19 per_ns::PerNs,
20 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, 20 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
21 GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, 21 GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId,
22 StructId, TraitId, TypeAliasId, 22 StructId, TraitId, TypeAliasId, TypeParamId,
23}; 23};
24 24
25#[derive(Debug, Clone, Default)] 25#[derive(Debug, Clone, Default)]
26pub struct Resolver { 26pub struct Resolver {
27 // FIXME: all usages generally call `.rev`, so maybe reverse once in consturciton?
27 scopes: Vec<Scope>, 28 scopes: Vec<Scope>,
28} 29}
29 30
@@ -58,7 +59,7 @@ enum Scope {
58#[derive(Debug, Clone, PartialEq, Eq, Hash)] 59#[derive(Debug, Clone, PartialEq, Eq, Hash)]
59pub enum TypeNs { 60pub enum TypeNs {
60 SelfType(ImplId), 61 SelfType(ImplId),
61 GenericParam(u32), 62 GenericParam(TypeParamId),
62 AdtId(AdtId), 63 AdtId(AdtId),
63 AdtSelfType(AdtId), 64 AdtSelfType(AdtId),
64 // Yup, enum variants are added to the types ns, but any usage of variant as 65 // Yup, enum variants are added to the types ns, but any usage of variant as
@@ -152,10 +153,13 @@ impl Resolver {
152 Scope::ExprScope(_) => continue, 153 Scope::ExprScope(_) => continue,
153 Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, 154 Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue,
154 155
155 Scope::GenericParams { params, .. } => { 156 Scope::GenericParams { params, def } => {
156 if let Some(param) = params.find_by_name(first_name) { 157 if let Some(local_id) = params.find_by_name(first_name) {
157 let idx = if path.segments.len() == 1 { None } else { Some(1) }; 158 let idx = if path.segments.len() == 1 { None } else { Some(1) };
158 return Some((TypeNs::GenericParam(param.idx), idx)); 159 return Some((
160 TypeNs::GenericParam(TypeParamId { local_id, parent: *def }),
161 idx,
162 ));
159 } 163 }
160 } 164 }
161 Scope::ImplBlockScope(impl_) => { 165 Scope::ImplBlockScope(impl_) => {
@@ -246,9 +250,9 @@ impl Resolver {
246 } 250 }
247 Scope::ExprScope(_) => continue, 251 Scope::ExprScope(_) => continue,
248 252
249 Scope::GenericParams { params, .. } if n_segments > 1 => { 253 Scope::GenericParams { params, def } if n_segments > 1 => {
250 if let Some(param) = params.find_by_name(first_name) { 254 if let Some(local_id) = params.find_by_name(first_name) {
251 let ty = TypeNs::GenericParam(param.idx); 255 let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def });
252 return Some(ResolveValueResult::Partial(ty, 1)); 256 return Some(ResolveValueResult::Partial(ty, 1));
253 } 257 }
254 } 258 }
@@ -368,6 +372,7 @@ impl Resolver {
368 ) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a { 372 ) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a {
369 self.scopes 373 self.scopes
370 .iter() 374 .iter()
375 .rev()
371 .filter_map(|scope| match scope { 376 .filter_map(|scope| match scope {
372 Scope::GenericParams { params, .. } => Some(params), 377 Scope::GenericParams { params, .. } => Some(params),
373 _ => None, 378 _ => None,
@@ -376,14 +381,14 @@ impl Resolver {
376 } 381 }
377 382
378 pub fn generic_def(&self) -> Option<GenericDefId> { 383 pub fn generic_def(&self) -> Option<GenericDefId> {
379 self.scopes.iter().find_map(|scope| match scope { 384 self.scopes.iter().rev().find_map(|scope| match scope {
380 Scope::GenericParams { def, .. } => Some(*def), 385 Scope::GenericParams { def, .. } => Some(*def),
381 _ => None, 386 _ => None,
382 }) 387 })
383 } 388 }
384 389
385 pub fn body_owner(&self) -> Option<DefWithBodyId> { 390 pub fn body_owner(&self) -> Option<DefWithBodyId> {
386 self.scopes.iter().find_map(|scope| match scope { 391 self.scopes.iter().rev().find_map(|scope| match scope {
387 Scope::ExprScope(it) => Some(it.owner), 392 Scope::ExprScope(it) => Some(it.owner),
388 _ => None, 393 _ => None,
389 }) 394 })
@@ -394,7 +399,7 @@ pub enum ScopeDef {
394 PerNs(PerNs), 399 PerNs(PerNs),
395 ImplSelfType(ImplId), 400 ImplSelfType(ImplId),
396 AdtSelfType(AdtId), 401 AdtSelfType(AdtId),
397 GenericParam(u32), 402 GenericParam(TypeParamId),
398 Local(PatId), 403 Local(PatId),
399} 404}
400 405
@@ -425,9 +430,12 @@ impl Scope {
425 }); 430 });
426 } 431 }
427 } 432 }
428 Scope::GenericParams { params, .. } => { 433 Scope::GenericParams { params, def } => {
429 for param in params.params.iter() { 434 for (local_id, param) in params.types.iter() {
430 f(param.name.clone(), ScopeDef::GenericParam(param.idx)) 435 f(
436 param.name.clone(),
437 ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }),
438 )
431 } 439 }
432 } 440 }
433 Scope::ImplBlockScope(i) => { 441 Scope::ImplBlockScope(i) => {
@@ -473,7 +481,7 @@ impl Resolver {
473 481
474 fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver { 482 fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver {
475 let params = db.generic_params(def); 483 let params = db.generic_params(def);
476 if params.params.is_empty() { 484 if params.types.is_empty() {
477 self 485 self
478 } else { 486 } else {
479 self.push_scope(Scope::GenericParams { def, params }) 487 self.push_scope(Scope::GenericParams { def, params })