diff options
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/hir_def/src/attr.rs | 36 | ||||
-rw-r--r-- | crates/hir_def/src/generics.rs | 44 | ||||
-rw-r--r-- | crates/hir_def/src/import_map.rs | 224 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 9 | ||||
-rw-r--r-- | crates/hir_def/src/keys.rs | 5 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 29 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/macros.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/path/lower.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/resolver.rs | 17 |
11 files changed, 300 insertions, 76 deletions
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml index a88b5f57e..e8b581e2f 100644 --- a/crates/hir_def/Cargo.toml +++ b/crates/hir_def/Cargo.toml | |||
@@ -17,7 +17,7 @@ either = "1.5.3" | |||
17 | anymap = "0.12.1" | 17 | anymap = "0.12.1" |
18 | drop_bomb = "0.1.4" | 18 | drop_bomb = "0.1.4" |
19 | fst = { version = "0.4", default-features = false } | 19 | fst = { version = "0.4", default-features = false } |
20 | itertools = "0.9.0" | 20 | itertools = "0.10.0" |
21 | indexmap = "1.4.0" | 21 | indexmap = "1.4.0" |
22 | smallvec = "1.4.0" | 22 | smallvec = "1.4.0" |
23 | 23 | ||
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 042e119b1..6b79e7bad 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -21,7 +21,7 @@ use crate::{ | |||
21 | nameres::ModuleSource, | 21 | nameres::ModuleSource, |
22 | path::{ModPath, PathKind}, | 22 | path::{ModPath, PathKind}, |
23 | src::HasChildSource, | 23 | src::HasChildSource, |
24 | AdtId, AttrDefId, Lookup, | 24 | AdtId, AttrDefId, GenericParamId, Lookup, |
25 | }; | 25 | }; |
26 | 26 | ||
27 | /// Holds documentation | 27 | /// Holds documentation |
@@ -235,6 +235,25 @@ impl Attrs { | |||
235 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 235 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
236 | AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 236 | AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
237 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 237 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
238 | AttrDefId::GenericParamId(it) => match it { | ||
239 | GenericParamId::TypeParamId(it) => { | ||
240 | let src = it.parent.child_source(db); | ||
241 | RawAttrs::from_attrs_owner( | ||
242 | db, | ||
243 | src.with_value( | ||
244 | src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _), | ||
245 | ), | ||
246 | ) | ||
247 | } | ||
248 | GenericParamId::LifetimeParamId(it) => { | ||
249 | let src = it.parent.child_source(db); | ||
250 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
251 | } | ||
252 | GenericParamId::ConstParamId(it) => { | ||
253 | let src = it.parent.child_source(db); | ||
254 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
255 | } | ||
256 | }, | ||
238 | }; | 257 | }; |
239 | 258 | ||
240 | raw_attrs.filter(db, def.krate(db)) | 259 | raw_attrs.filter(db, def.krate(db)) |
@@ -260,14 +279,13 @@ impl Attrs { | |||
260 | } | 279 | } |
261 | 280 | ||
262 | pub fn docs(&self) -> Option<Documentation> { | 281 | pub fn docs(&self) -> Option<Documentation> { |
263 | let docs = self | 282 | let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_ref()? { |
264 | .by_key("doc") | 283 | AttrInput::Literal(s) => Some(s), |
265 | .attrs() | 284 | AttrInput::TokenTree(_) => None, |
266 | .flat_map(|attr| match attr.input.as_ref()? { | 285 | }); |
267 | AttrInput::Literal(s) => Some(s), | 286 | // FIXME: Replace `Itertools::intersperse` with `Iterator::intersperse[_with]` until the |
268 | AttrInput::TokenTree(_) => None, | 287 | // libstd api gets stabilized (https://github.com/rust-lang/rust/issues/79524). |
269 | }) | 288 | let docs = Itertools::intersperse(docs, &SmolStr::new_inline("\n")) |
270 | .intersperse(&SmolStr::new_inline("\n")) | ||
271 | .map(|it| it.as_str()) | 289 | .map(|it| it.as_str()) |
272 | .collect::<String>(); | 290 | .collect::<String>(); |
273 | if docs.is_empty() { | 291 | if docs.is_empty() { |
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index bb8fca009..9b5b886c2 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs | |||
@@ -21,11 +21,11 @@ use crate::{ | |||
21 | keys, | 21 | keys, |
22 | src::{HasChildSource, HasSource}, | 22 | src::{HasChildSource, HasSource}, |
23 | type_ref::{LifetimeRef, TypeBound, TypeRef}, | 23 | type_ref::{LifetimeRef, TypeBound, TypeRef}, |
24 | AdtId, GenericDefId, LifetimeParamId, LocalLifetimeParamId, LocalTypeParamId, Lookup, | 24 | AdtId, ConstParamId, GenericDefId, LifetimeParamId, LocalConstParamId, LocalLifetimeParamId, |
25 | TypeParamId, | 25 | LocalTypeParamId, Lookup, TypeParamId, |
26 | }; | 26 | }; |
27 | 27 | ||
28 | /// Data about a generic parameter (to a function, struct, impl, ...). | 28 | /// Data about a generic type parameter (to a function, struct, impl, ...). |
29 | #[derive(Clone, PartialEq, Eq, Debug)] | 29 | #[derive(Clone, PartialEq, Eq, Debug)] |
30 | pub struct TypeParamData { | 30 | pub struct TypeParamData { |
31 | pub name: Option<Name>, | 31 | pub name: Option<Name>, |
@@ -33,12 +33,19 @@ pub struct TypeParamData { | |||
33 | pub provenance: TypeParamProvenance, | 33 | pub provenance: TypeParamProvenance, |
34 | } | 34 | } |
35 | 35 | ||
36 | /// Data about a generic parameter (to a function, struct, impl, ...). | 36 | /// Data about a generic lifetime parameter (to a function, struct, impl, ...). |
37 | #[derive(Clone, PartialEq, Eq, Debug)] | 37 | #[derive(Clone, PartialEq, Eq, Debug)] |
38 | pub struct LifetimeParamData { | 38 | pub struct LifetimeParamData { |
39 | pub name: Name, | 39 | pub name: Name, |
40 | } | 40 | } |
41 | 41 | ||
42 | /// Data about a generic const parameter (to a function, struct, impl, ...). | ||
43 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
44 | pub struct ConstParamData { | ||
45 | pub name: Name, | ||
46 | pub ty: TypeRef, | ||
47 | } | ||
48 | |||
42 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | 49 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
43 | pub enum TypeParamProvenance { | 50 | pub enum TypeParamProvenance { |
44 | TypeParamList, | 51 | TypeParamList, |
@@ -51,6 +58,7 @@ pub enum TypeParamProvenance { | |||
51 | pub struct GenericParams { | 58 | pub struct GenericParams { |
52 | pub types: Arena<TypeParamData>, | 59 | pub types: Arena<TypeParamData>, |
53 | pub lifetimes: Arena<LifetimeParamData>, | 60 | pub lifetimes: Arena<LifetimeParamData>, |
61 | pub consts: Arena<ConstParamData>, | ||
54 | pub where_predicates: Vec<WherePredicate>, | 62 | pub where_predicates: Vec<WherePredicate>, |
55 | } | 63 | } |
56 | 64 | ||
@@ -76,6 +84,7 @@ pub enum WherePredicateTypeTarget { | |||
76 | pub(crate) struct SourceMap { | 84 | pub(crate) struct SourceMap { |
77 | pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>, | 85 | pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>, |
78 | lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>, | 86 | lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>, |
87 | const_params: ArenaMap<LocalConstParamId, ast::ConstParam>, | ||
79 | } | 88 | } |
80 | 89 | ||
81 | impl GenericParams { | 90 | impl GenericParams { |
@@ -268,6 +277,13 @@ impl GenericParams { | |||
268 | let lifetime_ref = LifetimeRef::new_name(name); | 277 | let lifetime_ref = LifetimeRef::new_name(name); |
269 | self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); | 278 | self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); |
270 | } | 279 | } |
280 | for const_param in params.const_params() { | ||
281 | let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); | ||
282 | let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it)); | ||
283 | let param = ConstParamData { name, ty }; | ||
284 | let param_id = self.consts.alloc(param); | ||
285 | sm.const_params.insert(param_id, const_param.clone()); | ||
286 | } | ||
271 | } | 287 | } |
272 | 288 | ||
273 | fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) { | 289 | fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) { |
@@ -353,12 +369,16 @@ impl GenericParams { | |||
353 | }); | 369 | }); |
354 | } | 370 | } |
355 | 371 | ||
356 | pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { | 372 | pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { |
357 | self.types | 373 | self.types |
358 | .iter() | 374 | .iter() |
359 | .find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None }) | 375 | .find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None }) |
360 | } | 376 | } |
361 | 377 | ||
378 | pub fn find_const_by_name(&self, name: &Name) -> Option<LocalConstParamId> { | ||
379 | self.consts.iter().find_map(|(id, p)| if p.name == *name { Some(id) } else { None }) | ||
380 | } | ||
381 | |||
362 | pub fn find_trait_self_param(&self) -> Option<LocalTypeParamId> { | 382 | pub fn find_trait_self_param(&self) -> Option<LocalTypeParamId> { |
363 | self.types.iter().find_map(|(id, p)| { | 383 | self.types.iter().find_map(|(id, p)| { |
364 | if p.provenance == TypeParamProvenance::TraitSelf { | 384 | if p.provenance == TypeParamProvenance::TraitSelf { |
@@ -390,6 +410,16 @@ impl HasChildSource<LocalLifetimeParamId> for GenericDefId { | |||
390 | } | 410 | } |
391 | } | 411 | } |
392 | 412 | ||
413 | impl HasChildSource<LocalConstParamId> for GenericDefId { | ||
414 | type Value = ast::ConstParam; | ||
415 | fn child_source( | ||
416 | &self, | ||
417 | db: &dyn DefDatabase, | ||
418 | ) -> InFile<ArenaMap<LocalConstParamId, Self::Value>> { | ||
419 | GenericParams::new(db, *self).1.map(|source_maps| source_maps.const_params) | ||
420 | } | ||
421 | } | ||
422 | |||
393 | impl ChildBySource for GenericDefId { | 423 | impl ChildBySource for GenericDefId { |
394 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { | 424 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { |
395 | let mut res = DynMap::default(); | 425 | let mut res = DynMap::default(); |
@@ -406,6 +436,10 @@ impl ChildBySource for GenericDefId { | |||
406 | let id = LifetimeParamId { parent: *self, local_id }; | 436 | let id = LifetimeParamId { parent: *self, local_id }; |
407 | res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), id); | 437 | res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), id); |
408 | } | 438 | } |
439 | for (local_id, src) in sm.value.const_params.iter() { | ||
440 | let id = ConstParamId { parent: *self, local_id }; | ||
441 | res[keys::CONST_PARAM].insert(sm.with_value(src.clone()), id); | ||
442 | } | ||
409 | res | 443 | res |
410 | } | 444 | } |
411 | } | 445 | } |
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs index c0f108848..30b22f51d 100644 --- a/crates/hir_def/src/import_map.rs +++ b/crates/hir_def/src/import_map.rs | |||
@@ -238,32 +238,53 @@ pub enum ImportKind { | |||
238 | BuiltinType, | 238 | BuiltinType, |
239 | } | 239 | } |
240 | 240 | ||
241 | /// A way to match import map contents against the search query. | ||
242 | #[derive(Debug)] | ||
243 | pub enum SearchMode { | ||
244 | /// Import map entry should strictly match the query string. | ||
245 | Equals, | ||
246 | /// Import map entry should contain the query string. | ||
247 | Contains, | ||
248 | /// Import map entry should contain all letters from the query string, | ||
249 | /// in the same order, but not necessary adjacent. | ||
250 | Fuzzy, | ||
251 | } | ||
252 | |||
241 | #[derive(Debug)] | 253 | #[derive(Debug)] |
242 | pub struct Query { | 254 | pub struct Query { |
243 | query: String, | 255 | query: String, |
244 | lowercased: String, | 256 | lowercased: String, |
245 | anchor_end: bool, | 257 | name_only: bool, |
258 | search_mode: SearchMode, | ||
246 | case_sensitive: bool, | 259 | case_sensitive: bool, |
247 | limit: usize, | 260 | limit: usize, |
248 | exclude_import_kinds: FxHashSet<ImportKind>, | 261 | exclude_import_kinds: FxHashSet<ImportKind>, |
249 | } | 262 | } |
250 | 263 | ||
251 | impl Query { | 264 | impl Query { |
252 | pub fn new(query: &str) -> Self { | 265 | pub fn new(query: String) -> Self { |
266 | let lowercased = query.to_lowercase(); | ||
253 | Self { | 267 | Self { |
254 | lowercased: query.to_lowercase(), | 268 | query, |
255 | query: query.to_string(), | 269 | lowercased, |
256 | anchor_end: false, | 270 | name_only: false, |
271 | search_mode: SearchMode::Contains, | ||
257 | case_sensitive: false, | 272 | case_sensitive: false, |
258 | limit: usize::max_value(), | 273 | limit: usize::max_value(), |
259 | exclude_import_kinds: FxHashSet::default(), | 274 | exclude_import_kinds: FxHashSet::default(), |
260 | } | 275 | } |
261 | } | 276 | } |
262 | 277 | ||
263 | /// Only returns items whose paths end with the (case-insensitive) query string as their last | 278 | /// Matches entries' names only, ignoring the rest of |
264 | /// segment. | 279 | /// the qualifier. |
265 | pub fn anchor_end(self) -> Self { | 280 | /// Example: for `std::marker::PhantomData`, the name is `PhantomData`. |
266 | Self { anchor_end: true, ..self } | 281 | pub fn name_only(self) -> Self { |
282 | Self { name_only: true, ..self } | ||
283 | } | ||
284 | |||
285 | /// Specifies the way to search for the entries using the query. | ||
286 | pub fn search_mode(self, search_mode: SearchMode) -> Self { | ||
287 | Self { search_mode, ..self } | ||
267 | } | 288 | } |
268 | 289 | ||
269 | /// Limits the returned number of items to `limit`. | 290 | /// Limits the returned number of items to `limit`. |
@@ -283,6 +304,40 @@ impl Query { | |||
283 | } | 304 | } |
284 | } | 305 | } |
285 | 306 | ||
307 | fn contains_query(query: &Query, input_path: &ImportPath, enforce_lowercase: bool) -> bool { | ||
308 | let mut input = if query.name_only { | ||
309 | input_path.segments.last().unwrap().to_string() | ||
310 | } else { | ||
311 | input_path.to_string() | ||
312 | }; | ||
313 | if enforce_lowercase || !query.case_sensitive { | ||
314 | input.make_ascii_lowercase(); | ||
315 | } | ||
316 | |||
317 | let query_string = | ||
318 | if !enforce_lowercase && query.case_sensitive { &query.query } else { &query.lowercased }; | ||
319 | |||
320 | match query.search_mode { | ||
321 | SearchMode::Equals => &input == query_string, | ||
322 | SearchMode::Contains => input.contains(query_string), | ||
323 | SearchMode::Fuzzy => { | ||
324 | let mut unchecked_query_chars = query_string.chars(); | ||
325 | let mut mismatching_query_char = unchecked_query_chars.next(); | ||
326 | |||
327 | for input_char in input.chars() { | ||
328 | match mismatching_query_char { | ||
329 | None => return true, | ||
330 | Some(matching_query_char) if matching_query_char == input_char => { | ||
331 | mismatching_query_char = unchecked_query_chars.next(); | ||
332 | } | ||
333 | _ => (), | ||
334 | } | ||
335 | } | ||
336 | mismatching_query_char.is_none() | ||
337 | } | ||
338 | } | ||
339 | } | ||
340 | |||
286 | /// Searches dependencies of `krate` for an importable path matching `query`. | 341 | /// Searches dependencies of `krate` for an importable path matching `query`. |
287 | /// | 342 | /// |
288 | /// This returns a list of items that could be imported from dependencies of `krate`. | 343 | /// This returns a list of items that could be imported from dependencies of `krate`. |
@@ -312,39 +367,29 @@ pub fn search_dependencies<'a>( | |||
312 | let importables = &import_map.importables[indexed_value.value as usize..]; | 367 | let importables = &import_map.importables[indexed_value.value as usize..]; |
313 | 368 | ||
314 | // Path shared by the importable items in this group. | 369 | // Path shared by the importable items in this group. |
315 | let path = &import_map.map[&importables[0]].path; | 370 | let common_importables_path = &import_map.map[&importables[0]].path; |
316 | 371 | if !contains_query(&query, common_importables_path, true) { | |
317 | if query.anchor_end { | 372 | continue; |
318 | // Last segment must match query. | ||
319 | let last = path.segments.last().unwrap().to_string(); | ||
320 | if last.to_lowercase() != query.lowercased { | ||
321 | continue; | ||
322 | } | ||
323 | } | 373 | } |
324 | 374 | ||
375 | let common_importables_path_fst = fst_path(common_importables_path); | ||
325 | // Add the items from this `ModPath` group. Those are all subsequent items in | 376 | // Add the items from this `ModPath` group. Those are all subsequent items in |
326 | // `importables` whose paths match `path`. | 377 | // `importables` whose paths match `path`. |
327 | let iter = importables | 378 | let iter = importables |
328 | .iter() | 379 | .iter() |
329 | .copied() | 380 | .copied() |
330 | .take_while(|item| { | 381 | .take_while(|item| { |
331 | let item_path = &import_map.map[item].path; | 382 | common_importables_path_fst == fst_path(&import_map.map[item].path) |
332 | fst_path(item_path) == fst_path(path) | ||
333 | }) | 383 | }) |
334 | .filter(|&item| match item_import_kind(item) { | 384 | .filter(|&item| match item_import_kind(item) { |
335 | Some(import_kind) => !query.exclude_import_kinds.contains(&import_kind), | 385 | Some(import_kind) => !query.exclude_import_kinds.contains(&import_kind), |
336 | None => true, | 386 | None => true, |
387 | }) | ||
388 | .filter(|item| { | ||
389 | !query.case_sensitive // we've already checked the common importables path case-insensitively | ||
390 | || contains_query(&query, &import_map.map[item].path, false) | ||
337 | }); | 391 | }); |
338 | 392 | res.extend(iter); | |
339 | if query.case_sensitive { | ||
340 | // FIXME: This does not do a subsequence match. | ||
341 | res.extend(iter.filter(|item| { | ||
342 | let item_path = &import_map.map[item].path; | ||
343 | item_path.to_string().contains(&query.query) | ||
344 | })); | ||
345 | } else { | ||
346 | res.extend(iter); | ||
347 | } | ||
348 | 393 | ||
349 | if res.len() >= query.limit { | 394 | if res.len() >= query.limit { |
350 | res.truncate(query.limit); | 395 | res.truncate(query.limit); |
@@ -387,8 +432,9 @@ fn item_import_kind(item: ItemInNs) -> Option<ImportKind> { | |||
387 | mod tests { | 432 | mod tests { |
388 | use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; | 433 | use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; |
389 | use expect_test::{expect, Expect}; | 434 | use expect_test::{expect, Expect}; |
435 | use stdx::format_to; | ||
390 | 436 | ||
391 | use crate::{test_db::TestDB, AssocContainerId, Lookup}; | 437 | use crate::{data::FunctionData, test_db::TestDB, AssocContainerId, Lookup}; |
392 | 438 | ||
393 | use super::*; | 439 | use super::*; |
394 | 440 | ||
@@ -407,14 +453,32 @@ mod tests { | |||
407 | .into_iter() | 453 | .into_iter() |
408 | .filter_map(|item| { | 454 | .filter_map(|item| { |
409 | let mark = match item { | 455 | let mark = match item { |
456 | ItemInNs::Types(ModuleDefId::FunctionId(_)) | ||
457 | | ItemInNs::Values(ModuleDefId::FunctionId(_)) => "f", | ||
410 | ItemInNs::Types(_) => "t", | 458 | ItemInNs::Types(_) => "t", |
411 | ItemInNs::Values(_) => "v", | 459 | ItemInNs::Values(_) => "v", |
412 | ItemInNs::Macros(_) => "m", | 460 | ItemInNs::Macros(_) => "m", |
413 | }; | 461 | }; |
414 | let item = assoc_to_trait(&db, item); | ||
415 | item.krate(db.upcast()).map(|krate| { | 462 | item.krate(db.upcast()).map(|krate| { |
416 | let map = db.import_map(krate); | 463 | let map = db.import_map(krate); |
417 | let path = map.path_of(item).unwrap(); | 464 | |
465 | let path = match assoc_to_trait(&db, item) { | ||
466 | Some(trait_) => { | ||
467 | let mut full_path = map.path_of(trait_).unwrap().to_string(); | ||
468 | if let ItemInNs::Types(ModuleDefId::FunctionId(function_id)) | ||
469 | | ItemInNs::Values(ModuleDefId::FunctionId(function_id)) = item | ||
470 | { | ||
471 | format_to!( | ||
472 | full_path, | ||
473 | "::{}", | ||
474 | FunctionData::fn_data_query(&db, function_id).name, | ||
475 | ); | ||
476 | } | ||
477 | full_path | ||
478 | } | ||
479 | None => map.path_of(item).unwrap().to_string(), | ||
480 | }; | ||
481 | |||
418 | format!( | 482 | format!( |
419 | "{}::{} ({})\n", | 483 | "{}::{} ({})\n", |
420 | crate_graph[krate].display_name.as_ref().unwrap(), | 484 | crate_graph[krate].display_name.as_ref().unwrap(), |
@@ -427,15 +491,15 @@ mod tests { | |||
427 | expect.assert_eq(&actual) | 491 | expect.assert_eq(&actual) |
428 | } | 492 | } |
429 | 493 | ||
430 | fn assoc_to_trait(db: &dyn DefDatabase, item: ItemInNs) -> ItemInNs { | 494 | fn assoc_to_trait(db: &dyn DefDatabase, item: ItemInNs) -> Option<ItemInNs> { |
431 | let assoc: AssocItemId = match item { | 495 | let assoc: AssocItemId = match item { |
432 | ItemInNs::Types(it) | ItemInNs::Values(it) => match it { | 496 | ItemInNs::Types(it) | ItemInNs::Values(it) => match it { |
433 | ModuleDefId::TypeAliasId(it) => it.into(), | 497 | ModuleDefId::TypeAliasId(it) => it.into(), |
434 | ModuleDefId::FunctionId(it) => it.into(), | 498 | ModuleDefId::FunctionId(it) => it.into(), |
435 | ModuleDefId::ConstId(it) => it.into(), | 499 | ModuleDefId::ConstId(it) => it.into(), |
436 | _ => return item, | 500 | _ => return None, |
437 | }, | 501 | }, |
438 | _ => return item, | 502 | _ => return None, |
439 | }; | 503 | }; |
440 | 504 | ||
441 | let container = match assoc { | 505 | let container = match assoc { |
@@ -445,8 +509,8 @@ mod tests { | |||
445 | }; | 509 | }; |
446 | 510 | ||
447 | match container { | 511 | match container { |
448 | AssocContainerId::TraitId(it) => ItemInNs::Types(it.into()), | 512 | AssocContainerId::TraitId(it) => Some(ItemInNs::Types(it.into())), |
449 | _ => item, | 513 | _ => None, |
450 | } | 514 | } |
451 | } | 515 | } |
452 | 516 | ||
@@ -685,7 +749,7 @@ mod tests { | |||
685 | } | 749 | } |
686 | 750 | ||
687 | #[test] | 751 | #[test] |
688 | fn search() { | 752 | fn search_mode() { |
689 | let ra_fixture = r#" | 753 | let ra_fixture = r#" |
690 | //- /main.rs crate:main deps:dep | 754 | //- /main.rs crate:main deps:dep |
691 | //- /dep.rs crate:dep deps:tdep | 755 | //- /dep.rs crate:dep deps:tdep |
@@ -713,28 +777,96 @@ mod tests { | |||
713 | check_search( | 777 | check_search( |
714 | ra_fixture, | 778 | ra_fixture, |
715 | "main", | 779 | "main", |
716 | Query::new("fmt"), | 780 | Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy), |
717 | expect![[r#" | 781 | expect![[r#" |
718 | dep::fmt (t) | 782 | dep::fmt (t) |
719 | dep::Fmt (t) | 783 | dep::Fmt (t) |
720 | dep::Fmt (v) | 784 | dep::Fmt (v) |
721 | dep::Fmt (m) | 785 | dep::Fmt (m) |
722 | dep::fmt::Display (t) | 786 | dep::fmt::Display (t) |
723 | dep::format (v) | 787 | dep::format (f) |
788 | dep::fmt::Display::fmt (f) | ||
789 | "#]], | ||
790 | ); | ||
791 | |||
792 | check_search( | ||
793 | ra_fixture, | ||
794 | "main", | ||
795 | Query::new("fmt".to_string()).search_mode(SearchMode::Equals), | ||
796 | expect![[r#" | ||
797 | dep::fmt (t) | ||
798 | dep::Fmt (t) | ||
799 | dep::Fmt (v) | ||
800 | dep::Fmt (m) | ||
801 | dep::fmt::Display::fmt (f) | ||
802 | "#]], | ||
803 | ); | ||
804 | |||
805 | check_search( | ||
806 | ra_fixture, | ||
807 | "main", | ||
808 | Query::new("fmt".to_string()).search_mode(SearchMode::Contains), | ||
809 | expect![[r#" | ||
810 | dep::fmt (t) | ||
811 | dep::Fmt (t) | ||
812 | dep::Fmt (v) | ||
813 | dep::Fmt (m) | ||
724 | dep::fmt::Display (t) | 814 | dep::fmt::Display (t) |
815 | dep::fmt::Display::fmt (f) | ||
725 | "#]], | 816 | "#]], |
726 | ); | 817 | ); |
818 | } | ||
819 | |||
820 | #[test] | ||
821 | fn name_only() { | ||
822 | let ra_fixture = r#" | ||
823 | //- /main.rs crate:main deps:dep | ||
824 | //- /dep.rs crate:dep deps:tdep | ||
825 | use tdep::fmt as fmt_dep; | ||
826 | pub mod fmt { | ||
827 | pub trait Display { | ||
828 | fn fmt(); | ||
829 | } | ||
830 | } | ||
831 | #[macro_export] | ||
832 | macro_rules! Fmt { | ||
833 | () => {}; | ||
834 | } | ||
835 | pub struct Fmt; | ||
836 | |||
837 | pub fn format() {} | ||
838 | pub fn no() {} | ||
839 | |||
840 | //- /tdep.rs crate:tdep | ||
841 | pub mod fmt { | ||
842 | pub struct NotImportableFromMain; | ||
843 | } | ||
844 | "#; | ||
727 | 845 | ||
728 | check_search( | 846 | check_search( |
729 | ra_fixture, | 847 | ra_fixture, |
730 | "main", | 848 | "main", |
731 | Query::new("fmt").anchor_end(), | 849 | Query::new("fmt".to_string()), |
732 | expect![[r#" | 850 | expect![[r#" |
733 | dep::fmt (t) | 851 | dep::fmt (t) |
734 | dep::Fmt (t) | 852 | dep::Fmt (t) |
735 | dep::Fmt (v) | 853 | dep::Fmt (v) |
736 | dep::Fmt (m) | 854 | dep::Fmt (m) |
737 | dep::fmt::Display (t) | 855 | dep::fmt::Display (t) |
856 | dep::fmt::Display::fmt (f) | ||
857 | "#]], | ||
858 | ); | ||
859 | |||
860 | check_search( | ||
861 | ra_fixture, | ||
862 | "main", | ||
863 | Query::new("fmt".to_string()).name_only(), | ||
864 | expect![[r#" | ||
865 | dep::fmt (t) | ||
866 | dep::Fmt (t) | ||
867 | dep::Fmt (v) | ||
868 | dep::Fmt (m) | ||
869 | dep::fmt::Display::fmt (f) | ||
738 | "#]], | 870 | "#]], |
739 | ); | 871 | ); |
740 | } | 872 | } |
@@ -752,7 +884,7 @@ mod tests { | |||
752 | check_search( | 884 | check_search( |
753 | ra_fixture, | 885 | ra_fixture, |
754 | "main", | 886 | "main", |
755 | Query::new("FMT"), | 887 | Query::new("FMT".to_string()), |
756 | expect![[r#" | 888 | expect![[r#" |
757 | dep::fmt (t) | 889 | dep::fmt (t) |
758 | dep::fmt (v) | 890 | dep::fmt (v) |
@@ -764,7 +896,7 @@ mod tests { | |||
764 | check_search( | 896 | check_search( |
765 | ra_fixture, | 897 | ra_fixture, |
766 | "main", | 898 | "main", |
767 | Query::new("FMT").case_sensitive(), | 899 | Query::new("FMT".to_string()).case_sensitive(), |
768 | expect![[r#" | 900 | expect![[r#" |
769 | dep::FMT (t) | 901 | dep::FMT (t) |
770 | dep::FMT (v) | 902 | dep::FMT (v) |
@@ -793,7 +925,7 @@ mod tests { | |||
793 | pub fn no() {} | 925 | pub fn no() {} |
794 | "#, | 926 | "#, |
795 | "main", | 927 | "main", |
796 | Query::new("").limit(2), | 928 | Query::new("".to_string()).limit(2), |
797 | expect![[r#" | 929 | expect![[r#" |
798 | dep::fmt (t) | 930 | dep::fmt (t) |
799 | dep::Fmt (t) | 931 | dep::Fmt (t) |
@@ -814,7 +946,7 @@ mod tests { | |||
814 | check_search( | 946 | check_search( |
815 | ra_fixture, | 947 | ra_fixture, |
816 | "main", | 948 | "main", |
817 | Query::new("FMT"), | 949 | Query::new("FMT".to_string()), |
818 | expect![[r#" | 950 | expect![[r#" |
819 | dep::fmt (t) | 951 | dep::fmt (t) |
820 | dep::fmt (v) | 952 | dep::fmt (v) |
@@ -826,7 +958,7 @@ mod tests { | |||
826 | check_search( | 958 | check_search( |
827 | ra_fixture, | 959 | ra_fixture, |
828 | "main", | 960 | "main", |
829 | Query::new("FMT").exclude_import_kind(ImportKind::Adt), | 961 | Query::new("FMT".to_string()).exclude_import_kind(ImportKind::Adt), |
830 | expect![[r#""#]], | 962 | expect![[r#""#]], |
831 | ); | 963 | ); |
832 | } | 964 | } |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 100dbf5d6..b6f510731 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -260,6 +260,7 @@ impl GenericParamsStorage { | |||
260 | fn alloc(&mut self, params: GenericParams) -> GenericParamsId { | 260 | fn alloc(&mut self, params: GenericParams) -> GenericParamsId { |
261 | if params.types.is_empty() | 261 | if params.types.is_empty() |
262 | && params.lifetimes.is_empty() | 262 | && params.lifetimes.is_empty() |
263 | && params.consts.is_empty() | ||
263 | && params.where_predicates.is_empty() | 264 | && params.where_predicates.is_empty() |
264 | { | 265 | { |
265 | return GenericParamsId::EMPTY; | 266 | return GenericParamsId::EMPTY; |
@@ -269,8 +270,12 @@ impl GenericParamsStorage { | |||
269 | } | 270 | } |
270 | } | 271 | } |
271 | 272 | ||
272 | static EMPTY_GENERICS: GenericParams = | 273 | static EMPTY_GENERICS: GenericParams = GenericParams { |
273 | GenericParams { types: Arena::new(), lifetimes: Arena::new(), where_predicates: Vec::new() }; | 274 | types: Arena::new(), |
275 | lifetimes: Arena::new(), | ||
276 | consts: Arena::new(), | ||
277 | where_predicates: Vec::new(), | ||
278 | }; | ||
274 | 279 | ||
275 | #[derive(Default, Debug, Eq, PartialEq)] | 280 | #[derive(Default, Debug, Eq, PartialEq)] |
276 | struct ItemTreeData { | 281 | struct ItemTreeData { |
diff --git a/crates/hir_def/src/keys.rs b/crates/hir_def/src/keys.rs index 9c585de2c..89b3ed868 100644 --- a/crates/hir_def/src/keys.rs +++ b/crates/hir_def/src/keys.rs | |||
@@ -8,8 +8,8 @@ use syntax::{ast, AstNode, AstPtr}; | |||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | dyn_map::{DynMap, Policy}, | 10 | dyn_map::{DynMap, Policy}, |
11 | ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, StaticId, | 11 | ConstId, ConstParamId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, |
12 | StructId, TraitId, TypeAliasId, TypeParamId, UnionId, | 12 | StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; | 15 | pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; |
@@ -29,6 +29,7 @@ pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new(); | |||
29 | pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); | 29 | pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); |
30 | pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); | 30 | pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); |
31 | pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new(); | 31 | pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new(); |
32 | pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new(); | ||
32 | 33 | ||
33 | pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); | 34 | pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); |
34 | 35 | ||
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index ba09a9126..211cb2faf 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -232,6 +232,13 @@ pub struct LifetimeParamId { | |||
232 | pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>; | 232 | pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>; |
233 | 233 | ||
234 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 234 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
235 | pub struct ConstParamId { | ||
236 | pub parent: GenericDefId, | ||
237 | pub local_id: LocalConstParamId, | ||
238 | } | ||
239 | pub type LocalConstParamId = Idx<generics::ConstParamData>; | ||
240 | |||
241 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
235 | pub enum ContainerId { | 242 | pub enum ContainerId { |
236 | ModuleId(ModuleId), | 243 | ModuleId(ModuleId), |
237 | DefWithBodyId(DefWithBodyId), | 244 | DefWithBodyId(DefWithBodyId), |
@@ -254,6 +261,15 @@ pub enum AdtId { | |||
254 | } | 261 | } |
255 | impl_from!(StructId, UnionId, EnumId for AdtId); | 262 | impl_from!(StructId, UnionId, EnumId for AdtId); |
256 | 263 | ||
264 | /// A generic param | ||
265 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
266 | pub enum GenericParamId { | ||
267 | TypeParamId(TypeParamId), | ||
268 | LifetimeParamId(LifetimeParamId), | ||
269 | ConstParamId(ConstParamId), | ||
270 | } | ||
271 | impl_from!(TypeParamId, LifetimeParamId, ConstParamId for GenericParamId); | ||
272 | |||
257 | /// The defs which can be visible in the module. | 273 | /// The defs which can be visible in the module. |
258 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 274 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
259 | pub enum ModuleDefId { | 275 | pub enum ModuleDefId { |
@@ -350,6 +366,7 @@ pub enum AttrDefId { | |||
350 | TypeAliasId(TypeAliasId), | 366 | TypeAliasId(TypeAliasId), |
351 | MacroDefId(MacroDefId), | 367 | MacroDefId(MacroDefId), |
352 | ImplId(ImplId), | 368 | ImplId(ImplId), |
369 | GenericParamId(GenericParamId), | ||
353 | } | 370 | } |
354 | 371 | ||
355 | impl_from!( | 372 | impl_from!( |
@@ -363,7 +380,8 @@ impl_from!( | |||
363 | TraitId, | 380 | TraitId, |
364 | TypeAliasId, | 381 | TypeAliasId, |
365 | MacroDefId, | 382 | MacroDefId, |
366 | ImplId | 383 | ImplId, |
384 | GenericParamId | ||
367 | for AttrDefId | 385 | for AttrDefId |
368 | ); | 386 | ); |
369 | 387 | ||
@@ -488,6 +506,15 @@ impl AttrDefId { | |||
488 | AttrDefId::TraitId(it) => it.lookup(db).container.module(db).krate, | 506 | AttrDefId::TraitId(it) => it.lookup(db).container.module(db).krate, |
489 | AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate, | 507 | AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate, |
490 | AttrDefId::ImplId(it) => it.lookup(db).container.module(db).krate, | 508 | AttrDefId::ImplId(it) => it.lookup(db).container.module(db).krate, |
509 | AttrDefId::GenericParamId(it) => { | ||
510 | match it { | ||
511 | GenericParamId::TypeParamId(it) => it.parent, | ||
512 | GenericParamId::LifetimeParamId(it) => it.parent, | ||
513 | GenericParamId::ConstParamId(it) => it.parent, | ||
514 | } | ||
515 | .module(db) | ||
516 | .krate | ||
517 | } | ||
491 | // FIXME: `MacroDefId` should store the defining module, then this can implement | 518 | // FIXME: `MacroDefId` should store the defining module, then this can implement |
492 | // `HasModule` | 519 | // `HasModule` |
493 | AttrDefId::MacroDefId(it) => it.krate, | 520 | AttrDefId::MacroDefId(it) => it.krate, |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index ffd0381d4..5682e122d 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -249,7 +249,7 @@ impl CrateDefMap { | |||
249 | buf.push_str(" _"); | 249 | buf.push_str(" _"); |
250 | } | 250 | } |
251 | 251 | ||
252 | buf.push_str("\n"); | 252 | buf.push('\n'); |
253 | } | 253 | } |
254 | 254 | ||
255 | for (name, child) in map.modules[module].children.iter() { | 255 | for (name, child) in map.modules[module].children.iter() { |
@@ -454,7 +454,7 @@ mod diagnostics { | |||
454 | }); | 454 | }); |
455 | for token in tokens { | 455 | for token in tokens { |
456 | if token.kind() == SyntaxKind::IDENT | 456 | if token.kind() == SyntaxKind::IDENT |
457 | && token.to_string() == *name | 457 | && token.text() == name.as_str() |
458 | { | 458 | { |
459 | precise_location = Some(token.text_range()); | 459 | precise_location = Some(token.text_range()); |
460 | break 'outer; | 460 | break 'outer; |
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs index f9bf5bc72..e5e9e8ca1 100644 --- a/crates/hir_def/src/nameres/tests/macros.rs +++ b/crates/hir_def/src/nameres/tests/macros.rs | |||
@@ -677,7 +677,7 @@ fn macro_expansion_overflow() { | |||
677 | r#" | 677 | r#" |
678 | macro_rules! a { | 678 | macro_rules! a { |
679 | ($e:expr; $($t:tt)*) => { | 679 | ($e:expr; $($t:tt)*) => { |
680 | b!($($t)*); | 680 | b!(static = (); $($t)*); |
681 | }; | 681 | }; |
682 | () => {}; | 682 | () => {}; |
683 | } | 683 | } |
@@ -689,7 +689,7 @@ macro_rules! b { | |||
689 | () => {}; | 689 | () => {}; |
690 | } | 690 | } |
691 | 691 | ||
692 | b! { static = #[] (); } | 692 | b! { static = #[] ();} |
693 | "#, | 693 | "#, |
694 | expect![[r#" | 694 | expect![[r#" |
695 | crate | 695 | crate |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index 8a01e6eea..9518ac109 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -123,7 +123,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
123 | // We follow what it did anyway :) | 123 | // We follow what it did anyway :) |
124 | if segments.len() == 1 && kind == PathKind::Plain { | 124 | if segments.len() == 1 && kind == PathKind::Plain { |
125 | if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { | 125 | if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { |
126 | if let Some(crate_id) = hygiene.local_inner_macros() { | 126 | if let Some(crate_id) = hygiene.local_inner_macros(path) { |
127 | kind = PathKind::DollarCrate(crate_id); | 127 | kind = PathKind::DollarCrate(crate_id); |
128 | } | 128 | } |
129 | } | 129 | } |
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index f8cc5e075..129f1dbac 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -20,9 +20,9 @@ use crate::{ | |||
20 | path::{ModPath, PathKind}, | 20 | path::{ModPath, PathKind}, |
21 | per_ns::PerNs, | 21 | per_ns::PerNs, |
22 | visibility::{RawVisibility, Visibility}, | 22 | visibility::{RawVisibility, Visibility}, |
23 | AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, | 23 | AdtId, AssocContainerId, ConstId, ConstParamId, ContainerId, DefWithBodyId, EnumId, |
24 | FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, | 24 | EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, |
25 | StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, | 25 | ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, |
26 | }; | 26 | }; |
27 | 27 | ||
28 | #[derive(Debug, Clone, Default)] | 28 | #[derive(Debug, Clone, Default)] |
@@ -93,6 +93,7 @@ pub enum ValueNs { | |||
93 | StaticId(StaticId), | 93 | StaticId(StaticId), |
94 | StructId(StructId), | 94 | StructId(StructId), |
95 | EnumVariantId(EnumVariantId), | 95 | EnumVariantId(EnumVariantId), |
96 | GenericParam(ConstParamId), | ||
96 | } | 97 | } |
97 | 98 | ||
98 | impl Resolver { | 99 | impl Resolver { |
@@ -163,7 +164,7 @@ impl Resolver { | |||
163 | } | 164 | } |
164 | 165 | ||
165 | Scope::GenericParams { params, def } => { | 166 | Scope::GenericParams { params, def } => { |
166 | if let Some(local_id) = params.find_by_name(first_name) { | 167 | if let Some(local_id) = params.find_type_by_name(first_name) { |
167 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; | 168 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; |
168 | return Some(( | 169 | return Some(( |
169 | TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), | 170 | TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), |
@@ -285,11 +286,17 @@ impl Resolver { | |||
285 | Scope::ExprScope(_) => continue, | 286 | Scope::ExprScope(_) => continue, |
286 | 287 | ||
287 | Scope::GenericParams { params, def } if n_segments > 1 => { | 288 | Scope::GenericParams { params, def } if n_segments > 1 => { |
288 | if let Some(local_id) = params.find_by_name(first_name) { | 289 | if let Some(local_id) = params.find_type_by_name(first_name) { |
289 | let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def }); | 290 | let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def }); |
290 | return Some(ResolveValueResult::Partial(ty, 1)); | 291 | return Some(ResolveValueResult::Partial(ty, 1)); |
291 | } | 292 | } |
292 | } | 293 | } |
294 | Scope::GenericParams { params, def } if n_segments == 1 => { | ||
295 | if let Some(local_id) = params.find_const_by_name(first_name) { | ||
296 | let val = ValueNs::GenericParam(ConstParamId { local_id, parent: *def }); | ||
297 | return Some(ResolveValueResult::ValueNs(val)); | ||
298 | } | ||
299 | } | ||
293 | Scope::GenericParams { .. } => continue, | 300 | Scope::GenericParams { .. } => continue, |
294 | 301 | ||
295 | Scope::ImplDefScope(impl_) => { | 302 | Scope::ImplDefScope(impl_) => { |