diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/attr.rs | 90 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 6 | ||||
-rw-r--r-- | crates/hir_def/src/body/scope.rs | 30 | ||||
-rw-r--r-- | crates/hir_def/src/db.rs | 11 | ||||
-rw-r--r-- | crates/hir_def/src/diagnostics.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/expr.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/find_path.rs | 48 | ||||
-rw-r--r-- | crates/hir_def/src/generics.rs | 44 | ||||
-rw-r--r-- | crates/hir_def/src/import_map.rs | 285 | ||||
-rw-r--r-- | crates/hir_def/src/item_scope.rs | 3 | ||||
-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 | 2 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 41 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/incremental.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/path.rs | 1 | ||||
-rw-r--r-- | crates/hir_def/src/path/lower.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/resolver.rs | 19 |
19 files changed, 436 insertions, 199 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 042e119b1..9e6426b31 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | use std::{ops, sync::Arc}; | 3 | use std::{ops, sync::Arc}; |
4 | 4 | ||
5 | use arena::map::ArenaMap; | ||
5 | use base_db::CrateId; | 6 | use base_db::CrateId; |
6 | use cfg::{CfgExpr, CfgOptions}; | 7 | use cfg::{CfgExpr, CfgOptions}; |
7 | use either::Either; | 8 | use either::Either; |
@@ -21,7 +22,8 @@ use crate::{ | |||
21 | nameres::ModuleSource, | 22 | nameres::ModuleSource, |
22 | path::{ModPath, PathKind}, | 23 | path::{ModPath, PathKind}, |
23 | src::HasChildSource, | 24 | src::HasChildSource, |
24 | AdtId, AttrDefId, Lookup, | 25 | AdtId, AttrDefId, EnumId, GenericParamId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, |
26 | VariantId, | ||
25 | }; | 27 | }; |
26 | 28 | ||
27 | /// Holds documentation | 29 | /// Holds documentation |
@@ -210,16 +212,10 @@ impl Attrs { | |||
210 | } | 212 | } |
211 | } | 213 | } |
212 | AttrDefId::FieldId(it) => { | 214 | AttrDefId::FieldId(it) => { |
213 | let src = it.parent.child_source(db); | 215 | return db.fields_attrs(it.parent)[it.local_id].clone(); |
214 | match &src.value[it.local_id] { | ||
215 | Either::Left(_tuple) => RawAttrs::default(), | ||
216 | Either::Right(record) => RawAttrs::from_attrs_owner(db, src.with_value(record)), | ||
217 | } | ||
218 | } | 216 | } |
219 | AttrDefId::EnumVariantId(var_id) => { | 217 | AttrDefId::EnumVariantId(it) => { |
220 | let src = var_id.parent.child_source(db); | 218 | return db.variants_attrs(it.parent)[it.local_id].clone(); |
221 | let src = src.as_ref().map(|it| &it[var_id.local_id]); | ||
222 | RawAttrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) | ||
223 | } | 219 | } |
224 | AttrDefId::AdtId(it) => match it { | 220 | AttrDefId::AdtId(it) => match it { |
225 | AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 221 | AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
@@ -235,11 +231,70 @@ impl Attrs { | |||
235 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 231 | 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), | 232 | 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), | 233 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
234 | AttrDefId::GenericParamId(it) => match it { | ||
235 | GenericParamId::TypeParamId(it) => { | ||
236 | let src = it.parent.child_source(db); | ||
237 | RawAttrs::from_attrs_owner( | ||
238 | db, | ||
239 | src.with_value( | ||
240 | src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _), | ||
241 | ), | ||
242 | ) | ||
243 | } | ||
244 | GenericParamId::LifetimeParamId(it) => { | ||
245 | let src = it.parent.child_source(db); | ||
246 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
247 | } | ||
248 | GenericParamId::ConstParamId(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 | }, | ||
238 | }; | 253 | }; |
239 | 254 | ||
240 | raw_attrs.filter(db, def.krate(db)) | 255 | raw_attrs.filter(db, def.krate(db)) |
241 | } | 256 | } |
242 | 257 | ||
258 | pub(crate) fn variants_attrs_query( | ||
259 | db: &dyn DefDatabase, | ||
260 | e: EnumId, | ||
261 | ) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>> { | ||
262 | let krate = e.lookup(db).container.module(db).krate; | ||
263 | let src = e.child_source(db); | ||
264 | let mut res = ArenaMap::default(); | ||
265 | |||
266 | for (id, var) in src.value.iter() { | ||
267 | let attrs = RawAttrs::from_attrs_owner(db, src.with_value(var as &dyn AttrsOwner)) | ||
268 | .filter(db, krate); | ||
269 | |||
270 | res.insert(id, attrs) | ||
271 | } | ||
272 | |||
273 | Arc::new(res) | ||
274 | } | ||
275 | |||
276 | pub(crate) fn fields_attrs_query( | ||
277 | db: &dyn DefDatabase, | ||
278 | v: VariantId, | ||
279 | ) -> Arc<ArenaMap<LocalFieldId, Attrs>> { | ||
280 | let krate = v.module(db).krate; | ||
281 | let src = v.child_source(db); | ||
282 | let mut res = ArenaMap::default(); | ||
283 | |||
284 | for (id, fld) in src.value.iter() { | ||
285 | let attrs = match fld { | ||
286 | Either::Left(_tuple) => Attrs::default(), | ||
287 | Either::Right(record) => { | ||
288 | RawAttrs::from_attrs_owner(db, src.with_value(record)).filter(db, krate) | ||
289 | } | ||
290 | }; | ||
291 | |||
292 | res.insert(id, attrs); | ||
293 | } | ||
294 | |||
295 | Arc::new(res) | ||
296 | } | ||
297 | |||
243 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { | 298 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { |
244 | AttrQuery { attrs: self, key } | 299 | AttrQuery { attrs: self, key } |
245 | } | 300 | } |
@@ -260,14 +315,13 @@ impl Attrs { | |||
260 | } | 315 | } |
261 | 316 | ||
262 | pub fn docs(&self) -> Option<Documentation> { | 317 | pub fn docs(&self) -> Option<Documentation> { |
263 | let docs = self | 318 | let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_ref()? { |
264 | .by_key("doc") | 319 | AttrInput::Literal(s) => Some(s), |
265 | .attrs() | 320 | AttrInput::TokenTree(_) => None, |
266 | .flat_map(|attr| match attr.input.as_ref()? { | 321 | }); |
267 | AttrInput::Literal(s) => Some(s), | 322 | // FIXME: Replace `Itertools::intersperse` with `Iterator::intersperse[_with]` until the |
268 | AttrInput::TokenTree(_) => None, | 323 | // libstd api gets stabilized (https://github.com/rust-lang/rust/issues/79524). |
269 | }) | 324 | let docs = Itertools::intersperse(docs, &SmolStr::new_inline("\n")) |
270 | .intersperse(&SmolStr::new_inline("\n")) | ||
271 | .map(|it| it.as_str()) | 325 | .map(|it| it.as_str()) |
272 | .collect::<String>(); | 326 | .collect::<String>(); |
273 | if docs.is_empty() { | 327 | if docs.is_empty() { |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 17c72779b..3dc33f248 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -581,7 +581,7 @@ impl ExprCollector<'_> { | |||
581 | match res.value { | 581 | match res.value { |
582 | Some((mark, expansion)) => { | 582 | Some((mark, expansion)) => { |
583 | // FIXME: Statements are too complicated to recover from error for now. | 583 | // FIXME: Statements are too complicated to recover from error for now. |
584 | // It is because we don't have any hygenine for local variable expansion right now. | 584 | // It is because we don't have any hygiene for local variable expansion right now. |
585 | if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() { | 585 | if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() { |
586 | self.expander.exit(self.db, mark); | 586 | self.expander.exit(self.db, mark); |
587 | collector(self, None); | 587 | collector(self, None); |
@@ -695,7 +695,7 @@ impl ExprCollector<'_> { | |||
695 | self.collect_stmts_items(block.statements()); | 695 | self.collect_stmts_items(block.statements()); |
696 | let statements = | 696 | let statements = |
697 | block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); | 697 | block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); |
698 | let tail = block.expr().map(|e| self.collect_expr(e)); | 698 | let tail = block.tail_expr().map(|e| self.collect_expr(e)); |
699 | self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr) | 699 | self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr) |
700 | } | 700 | } |
701 | 701 | ||
@@ -959,7 +959,7 @@ impl ExprCollector<'_> { | |||
959 | 959 | ||
960 | fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) { | 960 | fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) { |
961 | // Find the location of the `..`, if there is one. Note that we do not | 961 | // Find the location of the `..`, if there is one. Note that we do not |
962 | // consider the possiblity of there being multiple `..` here. | 962 | // consider the possibility of there being multiple `..` here. |
963 | let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_))); | 963 | let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_))); |
964 | // We want to skip the `..` pattern here, since we account for it above. | 964 | // We want to skip the `..` pattern here, since we account for it above. |
965 | let args = args | 965 | let args = args |
diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs index 9142bc05b..065785da7 100644 --- a/crates/hir_def/src/body/scope.rs +++ b/crates/hir_def/src/body/scope.rs | |||
@@ -194,7 +194,7 @@ mod tests { | |||
194 | let mut buf = String::new(); | 194 | let mut buf = String::new(); |
195 | let off: usize = offset.into(); | 195 | let off: usize = offset.into(); |
196 | buf.push_str(&code[..off]); | 196 | buf.push_str(&code[..off]); |
197 | buf.push_str("<|>marker"); | 197 | buf.push_str("$0marker"); |
198 | buf.push_str(&code[off..]); | 198 | buf.push_str(&code[off..]); |
199 | buf | 199 | buf |
200 | }; | 200 | }; |
@@ -231,7 +231,7 @@ mod tests { | |||
231 | r" | 231 | r" |
232 | fn quux(foo: i32) { | 232 | fn quux(foo: i32) { |
233 | let f = |bar, baz: i32| { | 233 | let f = |bar, baz: i32| { |
234 | <|> | 234 | $0 |
235 | }; | 235 | }; |
236 | }", | 236 | }", |
237 | &["bar", "baz", "foo"], | 237 | &["bar", "baz", "foo"], |
@@ -243,7 +243,7 @@ mod tests { | |||
243 | do_check( | 243 | do_check( |
244 | r" | 244 | r" |
245 | fn quux() { | 245 | fn quux() { |
246 | f(|x| <|> ); | 246 | f(|x| $0 ); |
247 | }", | 247 | }", |
248 | &["x"], | 248 | &["x"], |
249 | ); | 249 | ); |
@@ -254,7 +254,7 @@ mod tests { | |||
254 | do_check( | 254 | do_check( |
255 | r" | 255 | r" |
256 | fn quux() { | 256 | fn quux() { |
257 | z.f(|x| <|> ); | 257 | z.f(|x| $0 ); |
258 | }", | 258 | }", |
259 | &["x"], | 259 | &["x"], |
260 | ); | 260 | ); |
@@ -267,7 +267,7 @@ mod tests { | |||
267 | fn quux() { | 267 | fn quux() { |
268 | loop { | 268 | loop { |
269 | let x = (); | 269 | let x = (); |
270 | <|> | 270 | $0 |
271 | }; | 271 | }; |
272 | }", | 272 | }", |
273 | &["x"], | 273 | &["x"], |
@@ -281,7 +281,7 @@ mod tests { | |||
281 | fn quux() { | 281 | fn quux() { |
282 | match () { | 282 | match () { |
283 | Some(x) => { | 283 | Some(x) => { |
284 | <|> | 284 | $0 |
285 | } | 285 | } |
286 | }; | 286 | }; |
287 | }", | 287 | }", |
@@ -294,7 +294,7 @@ mod tests { | |||
294 | do_check( | 294 | do_check( |
295 | r" | 295 | r" |
296 | fn foo(x: String) { | 296 | fn foo(x: String) { |
297 | let x : &str = &x<|>; | 297 | let x : &str = &x$0; |
298 | }", | 298 | }", |
299 | &["x"], | 299 | &["x"], |
300 | ); | 300 | ); |
@@ -307,7 +307,7 @@ mod tests { | |||
307 | fn foo() { | 307 | fn foo() { |
308 | match Some(()) { | 308 | match Some(()) { |
309 | opt @ Some(unit) => { | 309 | opt @ Some(unit) => { |
310 | <|> | 310 | $0 |
311 | } | 311 | } |
312 | _ => {} | 312 | _ => {} |
313 | } | 313 | } |
@@ -330,7 +330,7 @@ fn foo() { | |||
330 | 330 | ||
331 | fn foo() { | 331 | fn foo() { |
332 | mac!(); | 332 | mac!(); |
333 | <|> | 333 | $0 |
334 | } | 334 | } |
335 | ", | 335 | ", |
336 | &[], | 336 | &[], |
@@ -343,7 +343,7 @@ fn foo() { | |||
343 | r" | 343 | r" |
344 | fn foo() { | 344 | fn foo() { |
345 | trait {} | 345 | trait {} |
346 | <|> | 346 | $0 |
347 | } | 347 | } |
348 | ", | 348 | ", |
349 | &[], | 349 | &[], |
@@ -391,7 +391,7 @@ fn foo(x: i32, y: u32) { | |||
391 | let z = x * 2; | 391 | let z = x * 2; |
392 | } | 392 | } |
393 | { | 393 | { |
394 | let t = x<|> * 3; | 394 | let t = x$0 * 3; |
395 | } | 395 | } |
396 | } | 396 | } |
397 | "#, | 397 | "#, |
@@ -404,7 +404,7 @@ fn foo(x: i32, y: u32) { | |||
404 | do_check_local_name( | 404 | do_check_local_name( |
405 | r#" | 405 | r#" |
406 | fn foo(x: String) { | 406 | fn foo(x: String) { |
407 | let x : &str = &x<|>; | 407 | let x : &str = &x$0; |
408 | } | 408 | } |
409 | "#, | 409 | "#, |
410 | 7, | 410 | 7, |
@@ -417,7 +417,7 @@ fn foo(x: String) { | |||
417 | r" | 417 | r" |
418 | fn foo(x: String) { | 418 | fn foo(x: String) { |
419 | let x : &str = &x; | 419 | let x : &str = &x; |
420 | x<|> | 420 | x$0 |
421 | } | 421 | } |
422 | ", | 422 | ", |
423 | 28, | 423 | 28, |
@@ -430,7 +430,7 @@ fn foo(x: String) { | |||
430 | r" | 430 | r" |
431 | fn foo() { | 431 | fn foo() { |
432 | if let Some(&from) = bar() { | 432 | if let Some(&from) = bar() { |
433 | from<|>; | 433 | from$0; |
434 | } | 434 | } |
435 | } | 435 | } |
436 | ", | 436 | ", |
@@ -446,7 +446,7 @@ fn foo() { | |||
446 | fn test() { | 446 | fn test() { |
447 | let foo: Option<f32> = None; | 447 | let foo: Option<f32> = None; |
448 | while let Option::Some(spam) = foo { | 448 | while let Option::Some(spam) = foo { |
449 | spam<|> | 449 | spam$0 |
450 | } | 450 | } |
451 | } | 451 | } |
452 | "#, | 452 | "#, |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index d1a459066..d3bf5b34c 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | //! Defines database & queries for name resolution. | 1 | //! Defines database & queries for name resolution. |
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use arena::map::ArenaMap; | ||
4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; | 5 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; |
5 | use hir_expand::{db::AstDatabase, HirFileId}; | 6 | use hir_expand::{db::AstDatabase, HirFileId}; |
6 | use syntax::SmolStr; | 7 | use syntax::SmolStr; |
@@ -16,8 +17,8 @@ use crate::{ | |||
16 | lang_item::{LangItemTarget, LangItems}, | 17 | lang_item::{LangItemTarget, LangItems}, |
17 | nameres::CrateDefMap, | 18 | nameres::CrateDefMap, |
18 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, | 19 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, |
19 | GenericDefId, ImplId, ImplLoc, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, | 20 | GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, StaticLoc, StructId, |
20 | TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, | 21 | StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId, |
21 | }; | 22 | }; |
22 | 23 | ||
23 | #[salsa::query_group(InternDatabaseStorage)] | 24 | #[salsa::query_group(InternDatabaseStorage)] |
@@ -92,6 +93,12 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
92 | #[salsa::invoke(GenericParams::generic_params_query)] | 93 | #[salsa::invoke(GenericParams::generic_params_query)] |
93 | fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>; | 94 | fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>; |
94 | 95 | ||
96 | #[salsa::invoke(Attrs::variants_attrs_query)] | ||
97 | fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>; | ||
98 | |||
99 | #[salsa::invoke(Attrs::fields_attrs_query)] | ||
100 | fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; | ||
101 | |||
95 | #[salsa::invoke(Attrs::attrs_query)] | 102 | #[salsa::invoke(Attrs::attrs_query)] |
96 | fn attrs(&self, def: AttrDefId) -> Attrs; | 103 | fn attrs(&self, def: AttrDefId) -> Attrs; |
97 | 104 | ||
diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs index c71266dc0..ab3f059ce 100644 --- a/crates/hir_def/src/diagnostics.rs +++ b/crates/hir_def/src/diagnostics.rs | |||
@@ -133,6 +133,10 @@ impl Diagnostic for InactiveCode { | |||
133 | // This diagnostic is shown when a procedural macro can not be found. This usually means that | 133 | // This diagnostic is shown when a procedural macro can not be found. This usually means that |
134 | // procedural macro support is simply disabled (and hence is only a weak hint instead of an error), | 134 | // procedural macro support is simply disabled (and hence is only a weak hint instead of an error), |
135 | // but can also indicate project setup problems. | 135 | // but can also indicate project setup problems. |
136 | // | ||
137 | // If you are seeing a lot of "proc macro not expanded" warnings, you can add this option to the | ||
138 | // `rust-analyzer.diagnostics.disabled` list to prevent them from showing. Alternatively you can | ||
139 | // enable support for procedural macros (see `rust-analyzer.procMacro.enable`). | ||
136 | #[derive(Debug, Clone, Eq, PartialEq)] | 140 | #[derive(Debug, Clone, Eq, PartialEq)] |
137 | pub struct UnresolvedProcMacro { | 141 | pub struct UnresolvedProcMacro { |
138 | pub file: HirFileId, | 142 | pub file: HirFileId, |
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs index 6a481769d..76f5721e5 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! This module describes hir-level representation of expressions. | 1 | //! This module describes hir-level representation of expressions. |
2 | //! | 2 | //! |
3 | //! This representaion is: | 3 | //! This representation is: |
4 | //! | 4 | //! |
5 | //! 1. Identity-based. Each expression has an `id`, so we can distinguish | 5 | //! 1. Identity-based. Each expression has an `id`, so we can distinguish |
6 | //! between different `1` in `1 + 1`. | 6 | //! between different `1` in `1 + 1`. |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 02613c4c4..4a212d291 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -410,7 +410,7 @@ mod tests { | |||
410 | let code = r#" | 410 | let code = r#" |
411 | //- /main.rs | 411 | //- /main.rs |
412 | struct S; | 412 | struct S; |
413 | <|> | 413 | $0 |
414 | "#; | 414 | "#; |
415 | check_found_path(code, "S", "S", "crate::S", "self::S"); | 415 | check_found_path(code, "S", "S", "crate::S", "self::S"); |
416 | } | 416 | } |
@@ -420,7 +420,7 @@ mod tests { | |||
420 | let code = r#" | 420 | let code = r#" |
421 | //- /main.rs | 421 | //- /main.rs |
422 | enum E { A } | 422 | enum E { A } |
423 | <|> | 423 | $0 |
424 | "#; | 424 | "#; |
425 | check_found_path(code, "E::A", "E::A", "E::A", "E::A"); | 425 | check_found_path(code, "E::A", "E::A", "E::A", "E::A"); |
426 | } | 426 | } |
@@ -432,7 +432,7 @@ mod tests { | |||
432 | mod foo { | 432 | mod foo { |
433 | pub struct S; | 433 | pub struct S; |
434 | } | 434 | } |
435 | <|> | 435 | $0 |
436 | "#; | 436 | "#; |
437 | check_found_path(code, "foo::S", "foo::S", "crate::foo::S", "self::foo::S"); | 437 | check_found_path(code, "foo::S", "foo::S", "crate::foo::S", "self::foo::S"); |
438 | } | 438 | } |
@@ -446,7 +446,7 @@ mod tests { | |||
446 | mod bar; | 446 | mod bar; |
447 | struct S; | 447 | struct S; |
448 | //- /foo/bar.rs | 448 | //- /foo/bar.rs |
449 | <|> | 449 | $0 |
450 | "#; | 450 | "#; |
451 | check_found_path(code, "super::S", "super::S", "crate::foo::S", "super::S"); | 451 | check_found_path(code, "super::S", "super::S", "crate::foo::S", "super::S"); |
452 | } | 452 | } |
@@ -457,7 +457,7 @@ mod tests { | |||
457 | //- /main.rs | 457 | //- /main.rs |
458 | mod foo; | 458 | mod foo; |
459 | //- /foo.rs | 459 | //- /foo.rs |
460 | <|> | 460 | $0 |
461 | "#; | 461 | "#; |
462 | check_found_path(code, "self", "self", "crate::foo", "self"); | 462 | check_found_path(code, "self", "self", "crate::foo", "self"); |
463 | } | 463 | } |
@@ -468,7 +468,7 @@ mod tests { | |||
468 | //- /main.rs | 468 | //- /main.rs |
469 | mod foo; | 469 | mod foo; |
470 | //- /foo.rs | 470 | //- /foo.rs |
471 | <|> | 471 | $0 |
472 | "#; | 472 | "#; |
473 | check_found_path(code, "crate", "crate", "crate", "crate"); | 473 | check_found_path(code, "crate", "crate", "crate", "crate"); |
474 | } | 474 | } |
@@ -480,7 +480,7 @@ mod tests { | |||
480 | mod foo; | 480 | mod foo; |
481 | struct S; | 481 | struct S; |
482 | //- /foo.rs | 482 | //- /foo.rs |
483 | <|> | 483 | $0 |
484 | "#; | 484 | "#; |
485 | check_found_path(code, "crate::S", "crate::S", "crate::S", "crate::S"); | 485 | check_found_path(code, "crate::S", "crate::S", "crate::S", "crate::S"); |
486 | } | 486 | } |
@@ -489,7 +489,7 @@ mod tests { | |||
489 | fn different_crate() { | 489 | fn different_crate() { |
490 | let code = r#" | 490 | let code = r#" |
491 | //- /main.rs crate:main deps:std | 491 | //- /main.rs crate:main deps:std |
492 | <|> | 492 | $0 |
493 | //- /std.rs crate:std | 493 | //- /std.rs crate:std |
494 | pub struct S; | 494 | pub struct S; |
495 | "#; | 495 | "#; |
@@ -501,7 +501,7 @@ mod tests { | |||
501 | let code = r#" | 501 | let code = r#" |
502 | //- /main.rs crate:main deps:std | 502 | //- /main.rs crate:main deps:std |
503 | extern crate std as std_renamed; | 503 | extern crate std as std_renamed; |
504 | <|> | 504 | $0 |
505 | //- /std.rs crate:std | 505 | //- /std.rs crate:std |
506 | pub struct S; | 506 | pub struct S; |
507 | "#; | 507 | "#; |
@@ -523,7 +523,7 @@ mod tests { | |||
523 | //- /main.rs crate:main deps:syntax | 523 | //- /main.rs crate:main deps:syntax |
524 | 524 | ||
525 | use syntax::ast; | 525 | use syntax::ast; |
526 | <|> | 526 | $0 |
527 | 527 | ||
528 | //- /lib.rs crate:syntax | 528 | //- /lib.rs crate:syntax |
529 | pub mod ast { | 529 | pub mod ast { |
@@ -543,7 +543,7 @@ mod tests { | |||
543 | let code = r#" | 543 | let code = r#" |
544 | //- /main.rs crate:main deps:syntax | 544 | //- /main.rs crate:main deps:syntax |
545 | 545 | ||
546 | <|> | 546 | $0 |
547 | 547 | ||
548 | //- /lib.rs crate:syntax | 548 | //- /lib.rs crate:syntax |
549 | pub mod ast { | 549 | pub mod ast { |
@@ -569,7 +569,7 @@ mod tests { | |||
569 | mod foo { pub(super) struct S; } | 569 | mod foo { pub(super) struct S; } |
570 | pub(crate) use foo::*; | 570 | pub(crate) use foo::*; |
571 | } | 571 | } |
572 | <|> | 572 | $0 |
573 | "#; | 573 | "#; |
574 | check_found_path(code, "bar::S", "bar::S", "crate::bar::S", "self::bar::S"); | 574 | check_found_path(code, "bar::S", "bar::S", "crate::bar::S", "self::bar::S"); |
575 | } | 575 | } |
@@ -582,7 +582,7 @@ mod tests { | |||
582 | mod foo { pub(super) struct S; } | 582 | mod foo { pub(super) struct S; } |
583 | pub(crate) use foo::S as U; | 583 | pub(crate) use foo::S as U; |
584 | } | 584 | } |
585 | <|> | 585 | $0 |
586 | "#; | 586 | "#; |
587 | check_found_path(code, "bar::U", "bar::U", "crate::bar::U", "self::bar::U"); | 587 | check_found_path(code, "bar::U", "bar::U", "crate::bar::U", "self::bar::U"); |
588 | } | 588 | } |
@@ -591,7 +591,7 @@ mod tests { | |||
591 | fn different_crate_reexport() { | 591 | fn different_crate_reexport() { |
592 | let code = r#" | 592 | let code = r#" |
593 | //- /main.rs crate:main deps:std | 593 | //- /main.rs crate:main deps:std |
594 | <|> | 594 | $0 |
595 | //- /std.rs crate:std deps:core | 595 | //- /std.rs crate:std deps:core |
596 | pub use core::S; | 596 | pub use core::S; |
597 | //- /core.rs crate:core | 597 | //- /core.rs crate:core |
@@ -604,7 +604,7 @@ mod tests { | |||
604 | fn prelude() { | 604 | fn prelude() { |
605 | let code = r#" | 605 | let code = r#" |
606 | //- /main.rs crate:main deps:std | 606 | //- /main.rs crate:main deps:std |
607 | <|> | 607 | $0 |
608 | //- /std.rs crate:std | 608 | //- /std.rs crate:std |
609 | pub mod prelude { pub struct S; } | 609 | pub mod prelude { pub struct S; } |
610 | #[prelude_import] | 610 | #[prelude_import] |
@@ -617,7 +617,7 @@ mod tests { | |||
617 | fn enum_variant_from_prelude() { | 617 | fn enum_variant_from_prelude() { |
618 | let code = r#" | 618 | let code = r#" |
619 | //- /main.rs crate:main deps:std | 619 | //- /main.rs crate:main deps:std |
620 | <|> | 620 | $0 |
621 | //- /std.rs crate:std | 621 | //- /std.rs crate:std |
622 | pub mod prelude { | 622 | pub mod prelude { |
623 | pub enum Option<T> { Some(T), None } | 623 | pub enum Option<T> { Some(T), None } |
@@ -637,7 +637,7 @@ mod tests { | |||
637 | pub mod foo; | 637 | pub mod foo; |
638 | pub mod baz; | 638 | pub mod baz; |
639 | struct S; | 639 | struct S; |
640 | <|> | 640 | $0 |
641 | //- /foo.rs | 641 | //- /foo.rs |
642 | pub mod bar { pub struct S; } | 642 | pub mod bar { pub struct S; } |
643 | //- /baz.rs | 643 | //- /baz.rs |
@@ -654,7 +654,7 @@ mod tests { | |||
654 | pub mod bar { pub struct S; } | 654 | pub mod bar { pub struct S; } |
655 | use bar::S; | 655 | use bar::S; |
656 | //- /foo.rs | 656 | //- /foo.rs |
657 | <|> | 657 | $0 |
658 | "#; | 658 | "#; |
659 | // crate::S would be shorter, but using private imports seems wrong | 659 | // crate::S would be shorter, but using private imports seems wrong |
660 | check_found_path(code, "crate::bar::S", "crate::bar::S", "crate::bar::S", "crate::bar::S"); | 660 | check_found_path(code, "crate::bar::S", "crate::bar::S", "crate::bar::S", "crate::bar::S"); |
@@ -668,7 +668,7 @@ mod tests { | |||
668 | pub mod bar; | 668 | pub mod bar; |
669 | pub mod baz; | 669 | pub mod baz; |
670 | //- /bar.rs | 670 | //- /bar.rs |
671 | <|> | 671 | $0 |
672 | //- /foo.rs | 672 | //- /foo.rs |
673 | pub use super::baz; | 673 | pub use super::baz; |
674 | pub struct S; | 674 | pub struct S; |
@@ -683,7 +683,7 @@ mod tests { | |||
683 | mark::check!(prefer_std_paths); | 683 | mark::check!(prefer_std_paths); |
684 | let code = r#" | 684 | let code = r#" |
685 | //- /main.rs crate:main deps:alloc,std | 685 | //- /main.rs crate:main deps:alloc,std |
686 | <|> | 686 | $0 |
687 | 687 | ||
688 | //- /std.rs crate:std deps:alloc | 688 | //- /std.rs crate:std deps:alloc |
689 | pub mod sync { | 689 | pub mod sync { |
@@ -711,7 +711,7 @@ mod tests { | |||
711 | //- /main.rs crate:main deps:core,std | 711 | //- /main.rs crate:main deps:core,std |
712 | #![no_std] | 712 | #![no_std] |
713 | 713 | ||
714 | <|> | 714 | $0 |
715 | 715 | ||
716 | //- /std.rs crate:std deps:core | 716 | //- /std.rs crate:std deps:core |
717 | 717 | ||
@@ -740,7 +740,7 @@ mod tests { | |||
740 | //- /main.rs crate:main deps:alloc,std | 740 | //- /main.rs crate:main deps:alloc,std |
741 | #![no_std] | 741 | #![no_std] |
742 | 742 | ||
743 | <|> | 743 | $0 |
744 | 744 | ||
745 | //- /std.rs crate:std deps:alloc | 745 | //- /std.rs crate:std deps:alloc |
746 | 746 | ||
@@ -767,7 +767,7 @@ mod tests { | |||
767 | fn prefer_shorter_paths_if_not_alloc() { | 767 | fn prefer_shorter_paths_if_not_alloc() { |
768 | let code = r#" | 768 | let code = r#" |
769 | //- /main.rs crate:main deps:megaalloc,std | 769 | //- /main.rs crate:main deps:megaalloc,std |
770 | <|> | 770 | $0 |
771 | 771 | ||
772 | //- /std.rs crate:std deps:megaalloc | 772 | //- /std.rs crate:std deps:megaalloc |
773 | pub mod sync { | 773 | pub mod sync { |
@@ -790,7 +790,7 @@ mod tests { | |||
790 | fn builtins_are_in_scope() { | 790 | fn builtins_are_in_scope() { |
791 | let code = r#" | 791 | let code = r#" |
792 | //- /main.rs | 792 | //- /main.rs |
793 | <|> | 793 | $0 |
794 | 794 | ||
795 | pub mod primitive { | 795 | pub mod primitive { |
796 | pub use u8; | 796 | pub use u8; |
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 c4dc894df..e5368b293 100644 --- a/crates/hir_def/src/import_map.rs +++ b/crates/hir_def/src/import_map.rs | |||
@@ -7,9 +7,8 @@ use fst::{self, Streamer}; | |||
7 | use hir_expand::name::Name; | 7 | use hir_expand::name::Name; |
8 | use indexmap::{map::Entry, IndexMap}; | 8 | use indexmap::{map::Entry, IndexMap}; |
9 | use itertools::Itertools; | 9 | use itertools::Itertools; |
10 | use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; | 10 | use rustc_hash::{FxHashSet, FxHasher}; |
11 | use smallvec::SmallVec; | 11 | use test_utils::mark; |
12 | use syntax::SmolStr; | ||
13 | 12 | ||
14 | use crate::{ | 13 | use crate::{ |
15 | db::DefDatabase, item_scope::ItemInNs, visibility::Visibility, AssocItemId, ModuleDefId, | 14 | db::DefDatabase, item_scope::ItemInNs, visibility::Visibility, AssocItemId, ModuleDefId, |
@@ -25,6 +24,8 @@ pub struct ImportInfo { | |||
25 | pub path: ImportPath, | 24 | pub path: ImportPath, |
26 | /// The module containing this item. | 25 | /// The module containing this item. |
27 | pub container: ModuleId, | 26 | pub container: ModuleId, |
27 | /// Whether the import is a trait associated item or not. | ||
28 | pub is_trait_assoc_item: bool, | ||
28 | } | 29 | } |
29 | 30 | ||
30 | #[derive(Debug, Clone, Eq, PartialEq)] | 31 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -64,10 +65,6 @@ pub struct ImportMap { | |||
64 | /// the index of the first one. | 65 | /// the index of the first one. |
65 | importables: Vec<ItemInNs>, | 66 | importables: Vec<ItemInNs>, |
66 | fst: fst::Map<Vec<u8>>, | 67 | fst: fst::Map<Vec<u8>>, |
67 | |||
68 | /// Maps names of associated items to the item's ID. Only includes items whose defining trait is | ||
69 | /// exported. | ||
70 | assoc_map: FxHashMap<SmolStr, SmallVec<[AssocItemId; 1]>>, | ||
71 | } | 68 | } |
72 | 69 | ||
73 | impl ImportMap { | 70 | impl ImportMap { |
@@ -108,14 +105,27 @@ impl ImportMap { | |||
108 | 105 | ||
109 | for item in per_ns.iter_items() { | 106 | for item in per_ns.iter_items() { |
110 | let path = mk_path(); | 107 | let path = mk_path(); |
108 | let path_len = path.len(); | ||
109 | let import_info = | ||
110 | ImportInfo { path, container: module, is_trait_assoc_item: false }; | ||
111 | |||
112 | if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { | ||
113 | import_map.collect_trait_assoc_items( | ||
114 | db, | ||
115 | tr, | ||
116 | matches!(item, ItemInNs::Types(_)), | ||
117 | &import_info, | ||
118 | ); | ||
119 | } | ||
120 | |||
111 | match import_map.map.entry(item) { | 121 | match import_map.map.entry(item) { |
112 | Entry::Vacant(entry) => { | 122 | Entry::Vacant(entry) => { |
113 | entry.insert(ImportInfo { path, container: module }); | 123 | entry.insert(import_info); |
114 | } | 124 | } |
115 | Entry::Occupied(mut entry) => { | 125 | Entry::Occupied(mut entry) => { |
116 | // If the new path is shorter, prefer that one. | 126 | // If the new path is shorter, prefer that one. |
117 | if path.len() < entry.get().path.len() { | 127 | if path_len < entry.get().path.len() { |
118 | *entry.get_mut() = ImportInfo { path, container: module }; | 128 | *entry.get_mut() = import_info; |
119 | } else { | 129 | } else { |
120 | continue; | 130 | continue; |
121 | } | 131 | } |
@@ -128,11 +138,6 @@ impl ImportMap { | |||
128 | if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { | 138 | if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { |
129 | worklist.push((mod_id, mk_path())); | 139 | worklist.push((mod_id, mk_path())); |
130 | } | 140 | } |
131 | |||
132 | // If we've added a path to a trait, add the trait's methods to the method map. | ||
133 | if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { | ||
134 | import_map.collect_trait_methods(db, tr); | ||
135 | } | ||
136 | } | 141 | } |
137 | } | 142 | } |
138 | } | 143 | } |
@@ -153,12 +158,10 @@ impl ImportMap { | |||
153 | } | 158 | } |
154 | } | 159 | } |
155 | 160 | ||
156 | let start = last_batch_start; | 161 | let key = fst_path(&importables[last_batch_start].1.path); |
157 | last_batch_start = idx + 1; | 162 | builder.insert(key, last_batch_start as u64).unwrap(); |
158 | |||
159 | let key = fst_path(&importables[start].1.path); | ||
160 | 163 | ||
161 | builder.insert(key, start as u64).unwrap(); | 164 | last_batch_start = idx + 1; |
162 | } | 165 | } |
163 | 166 | ||
164 | import_map.fst = fst::Map::new(builder.into_inner().unwrap()).unwrap(); | 167 | import_map.fst = fst::Map::new(builder.into_inner().unwrap()).unwrap(); |
@@ -176,10 +179,34 @@ impl ImportMap { | |||
176 | self.map.get(&item) | 179 | self.map.get(&item) |
177 | } | 180 | } |
178 | 181 | ||
179 | fn collect_trait_methods(&mut self, db: &dyn DefDatabase, tr: TraitId) { | 182 | fn collect_trait_assoc_items( |
180 | let data = db.trait_data(tr); | 183 | &mut self, |
181 | for (name, item) in data.items.iter() { | 184 | db: &dyn DefDatabase, |
182 | self.assoc_map.entry(name.to_string().into()).or_default().push(*item); | 185 | tr: TraitId, |
186 | is_type_in_ns: bool, | ||
187 | original_import_info: &ImportInfo, | ||
188 | ) { | ||
189 | for (assoc_item_name, item) in &db.trait_data(tr).items { | ||
190 | let module_def_id = match item { | ||
191 | AssocItemId::FunctionId(f) => ModuleDefId::from(*f), | ||
192 | AssocItemId::ConstId(c) => ModuleDefId::from(*c), | ||
193 | // cannot use associated type aliases directly: need a `<Struct as Trait>::TypeAlias` | ||
194 | // qualifier, ergo no need to store it for imports in import_map | ||
195 | AssocItemId::TypeAliasId(_) => { | ||
196 | mark::hit!(type_aliases_ignored); | ||
197 | continue; | ||
198 | } | ||
199 | }; | ||
200 | let assoc_item = if is_type_in_ns { | ||
201 | ItemInNs::Types(module_def_id) | ||
202 | } else { | ||
203 | ItemInNs::Values(module_def_id) | ||
204 | }; | ||
205 | |||
206 | let mut assoc_item_info = original_import_info.clone(); | ||
207 | assoc_item_info.path.segments.push(assoc_item_name.to_owned()); | ||
208 | assoc_item_info.is_trait_assoc_item = true; | ||
209 | self.map.insert(assoc_item, assoc_item_info); | ||
183 | } | 210 | } |
184 | } | 211 | } |
185 | } | 212 | } |
@@ -302,38 +329,38 @@ impl Query { | |||
302 | self.exclude_import_kinds.insert(import_kind); | 329 | self.exclude_import_kinds.insert(import_kind); |
303 | self | 330 | self |
304 | } | 331 | } |
305 | } | ||
306 | 332 | ||
307 | fn contains_query(query: &Query, input_path: &ImportPath, enforce_lowercase: bool) -> bool { | 333 | fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool { |
308 | let mut input = if query.name_only { | 334 | let mut input = if import.is_trait_assoc_item || self.name_only { |
309 | input_path.segments.last().unwrap().to_string() | 335 | import.path.segments.last().unwrap().to_string() |
310 | } else { | 336 | } else { |
311 | input_path.to_string() | 337 | import.path.to_string() |
312 | }; | 338 | }; |
313 | if enforce_lowercase || !query.case_sensitive { | 339 | if enforce_lowercase || !self.case_sensitive { |
314 | input.make_ascii_lowercase(); | 340 | input.make_ascii_lowercase(); |
315 | } | 341 | } |
316 | 342 | ||
317 | let query_string = | 343 | let query_string = |
318 | if !enforce_lowercase && query.case_sensitive { &query.query } else { &query.lowercased }; | 344 | if !enforce_lowercase && self.case_sensitive { &self.query } else { &self.lowercased }; |
319 | 345 | ||
320 | match query.search_mode { | 346 | match self.search_mode { |
321 | SearchMode::Equals => &input == query_string, | 347 | SearchMode::Equals => &input == query_string, |
322 | SearchMode::Contains => input.contains(query_string), | 348 | SearchMode::Contains => input.contains(query_string), |
323 | SearchMode::Fuzzy => { | 349 | SearchMode::Fuzzy => { |
324 | let mut unchecked_query_chars = query_string.chars(); | 350 | let mut unchecked_query_chars = query_string.chars(); |
325 | let mut mismatching_query_char = unchecked_query_chars.next(); | 351 | let mut mismatching_query_char = unchecked_query_chars.next(); |
326 | 352 | ||
327 | for input_char in input.chars() { | 353 | for input_char in input.chars() { |
328 | match mismatching_query_char { | 354 | match mismatching_query_char { |
329 | None => return true, | 355 | None => return true, |
330 | Some(matching_query_char) if matching_query_char == input_char => { | 356 | Some(matching_query_char) if matching_query_char == input_char => { |
331 | mismatching_query_char = unchecked_query_chars.next(); | 357 | mismatching_query_char = unchecked_query_chars.next(); |
358 | } | ||
359 | _ => (), | ||
332 | } | 360 | } |
333 | _ => (), | ||
334 | } | 361 | } |
362 | mismatching_query_char.is_none() | ||
335 | } | 363 | } |
336 | mismatching_query_char.is_none() | ||
337 | } | 364 | } |
338 | } | 365 | } |
339 | } | 366 | } |
@@ -366,13 +393,13 @@ pub fn search_dependencies<'a>( | |||
366 | let import_map = &import_maps[indexed_value.index]; | 393 | let import_map = &import_maps[indexed_value.index]; |
367 | let importables = &import_map.importables[indexed_value.value as usize..]; | 394 | let importables = &import_map.importables[indexed_value.value as usize..]; |
368 | 395 | ||
369 | // Path shared by the importable items in this group. | 396 | let common_importable_data = &import_map.map[&importables[0]]; |
370 | let common_importables_path = &import_map.map[&importables[0]].path; | 397 | if !query.import_matches(common_importable_data, true) { |
371 | if !contains_query(&query, common_importables_path, true) { | ||
372 | continue; | 398 | continue; |
373 | } | 399 | } |
374 | 400 | ||
375 | let common_importables_path_fst = fst_path(common_importables_path); | 401 | // Path shared by the importable items in this group. |
402 | let common_importables_path_fst = fst_path(&common_importable_data.path); | ||
376 | // Add the items from this `ModPath` group. Those are all subsequent items in | 403 | // Add the items from this `ModPath` group. Those are all subsequent items in |
377 | // `importables` whose paths match `path`. | 404 | // `importables` whose paths match `path`. |
378 | let iter = importables | 405 | let iter = importables |
@@ -387,7 +414,7 @@ pub fn search_dependencies<'a>( | |||
387 | }) | 414 | }) |
388 | .filter(|item| { | 415 | .filter(|item| { |
389 | !query.case_sensitive // we've already checked the common importables path case-insensitively | 416 | !query.case_sensitive // we've already checked the common importables path case-insensitively |
390 | || contains_query(&query, &import_map.map[item].path, false) | 417 | || query.import_matches(&import_map.map[item], false) |
391 | }); | 418 | }); |
392 | res.extend(iter); | 419 | res.extend(iter); |
393 | 420 | ||
@@ -398,19 +425,6 @@ pub fn search_dependencies<'a>( | |||
398 | } | 425 | } |
399 | } | 426 | } |
400 | 427 | ||
401 | // Add all exported associated items whose names match the query (exactly). | ||
402 | for map in &import_maps { | ||
403 | if let Some(v) = map.assoc_map.get(&*query.query) { | ||
404 | res.extend(v.iter().map(|&assoc| { | ||
405 | ItemInNs::Types(match assoc { | ||
406 | AssocItemId::FunctionId(it) => it.into(), | ||
407 | AssocItemId::ConstId(it) => it.into(), | ||
408 | AssocItemId::TypeAliasId(it) => it.into(), | ||
409 | }) | ||
410 | })); | ||
411 | } | ||
412 | } | ||
413 | |||
414 | res | 428 | res |
415 | } | 429 | } |
416 | 430 | ||
@@ -432,8 +446,9 @@ fn item_import_kind(item: ItemInNs) -> Option<ImportKind> { | |||
432 | mod tests { | 446 | mod tests { |
433 | use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; | 447 | use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; |
434 | use expect_test::{expect, Expect}; | 448 | use expect_test::{expect, Expect}; |
449 | use test_utils::mark; | ||
435 | 450 | ||
436 | use crate::{data::FunctionData, test_db::TestDB, AssocContainerId, Lookup}; | 451 | use crate::{test_db::TestDB, AssocContainerId, Lookup}; |
437 | 452 | ||
438 | use super::*; | 453 | use super::*; |
439 | 454 | ||
@@ -450,45 +465,66 @@ mod tests { | |||
450 | 465 | ||
451 | let actual = search_dependencies(db.upcast(), krate, query) | 466 | let actual = search_dependencies(db.upcast(), krate, query) |
452 | .into_iter() | 467 | .into_iter() |
453 | .filter_map(|item| { | 468 | .filter_map(|dependency| { |
454 | let mark = match item { | 469 | let dependency_krate = dependency.krate(db.upcast())?; |
455 | ItemInNs::Types(ModuleDefId::FunctionId(_)) | 470 | let dependency_imports = db.import_map(dependency_krate); |
456 | | ItemInNs::Values(ModuleDefId::FunctionId(_)) => "f", | 471 | |
457 | ItemInNs::Types(_) => "t", | 472 | let (path, mark) = match assoc_item_path(&db, &dependency_imports, dependency) { |
458 | ItemInNs::Values(_) => "v", | 473 | Some(assoc_item_path) => (assoc_item_path, "a"), |
459 | ItemInNs::Macros(_) => "m", | 474 | None => ( |
475 | dependency_imports.path_of(dependency)?.to_string(), | ||
476 | match dependency { | ||
477 | ItemInNs::Types(ModuleDefId::FunctionId(_)) | ||
478 | | ItemInNs::Values(ModuleDefId::FunctionId(_)) => "f", | ||
479 | ItemInNs::Types(_) => "t", | ||
480 | ItemInNs::Values(_) => "v", | ||
481 | ItemInNs::Macros(_) => "m", | ||
482 | }, | ||
483 | ), | ||
460 | }; | 484 | }; |
461 | item.krate(db.upcast()).map(|krate| { | 485 | |
462 | let map = db.import_map(krate); | 486 | Some(format!( |
463 | 487 | "{}::{} ({})\n", | |
464 | let path = match assoc_to_trait(&db, item) { | 488 | crate_graph[dependency_krate].display_name.as_ref()?, |
465 | Some(trait_) => { | 489 | path, |
466 | let mut full_path = map.path_of(trait_).unwrap().to_string(); | 490 | mark |
467 | if let ItemInNs::Types(ModuleDefId::FunctionId(function_id)) | 491 | )) |
468 | | ItemInNs::Values(ModuleDefId::FunctionId(function_id)) = item | ||
469 | { | ||
470 | full_path += &format!( | ||
471 | "::{}", | ||
472 | FunctionData::fn_data_query(&db, function_id).name | ||
473 | ); | ||
474 | } | ||
475 | full_path | ||
476 | } | ||
477 | None => map.path_of(item).unwrap().to_string(), | ||
478 | }; | ||
479 | |||
480 | format!( | ||
481 | "{}::{} ({})\n", | ||
482 | crate_graph[krate].display_name.as_ref().unwrap(), | ||
483 | path, | ||
484 | mark | ||
485 | ) | ||
486 | }) | ||
487 | }) | 492 | }) |
488 | .collect::<String>(); | 493 | .collect::<String>(); |
489 | expect.assert_eq(&actual) | 494 | expect.assert_eq(&actual) |
490 | } | 495 | } |
491 | 496 | ||
497 | fn assoc_item_path( | ||
498 | db: &dyn DefDatabase, | ||
499 | dependency_imports: &ImportMap, | ||
500 | dependency: ItemInNs, | ||
501 | ) -> Option<String> { | ||
502 | let dependency_assoc_item_id = match dependency { | ||
503 | ItemInNs::Types(ModuleDefId::FunctionId(id)) | ||
504 | | ItemInNs::Values(ModuleDefId::FunctionId(id)) => AssocItemId::from(id), | ||
505 | ItemInNs::Types(ModuleDefId::ConstId(id)) | ||
506 | | ItemInNs::Values(ModuleDefId::ConstId(id)) => AssocItemId::from(id), | ||
507 | ItemInNs::Types(ModuleDefId::TypeAliasId(id)) | ||
508 | | ItemInNs::Values(ModuleDefId::TypeAliasId(id)) => AssocItemId::from(id), | ||
509 | _ => return None, | ||
510 | }; | ||
511 | |||
512 | let trait_ = assoc_to_trait(db, dependency)?; | ||
513 | if let ModuleDefId::TraitId(tr) = trait_.as_module_def_id()? { | ||
514 | let trait_data = db.trait_data(tr); | ||
515 | let assoc_item_name = | ||
516 | trait_data.items.iter().find_map(|(assoc_item_name, assoc_item_id)| { | ||
517 | if &dependency_assoc_item_id == assoc_item_id { | ||
518 | Some(assoc_item_name) | ||
519 | } else { | ||
520 | None | ||
521 | } | ||
522 | })?; | ||
523 | return Some(format!("{}::{}", dependency_imports.path_of(trait_)?, assoc_item_name)); | ||
524 | } | ||
525 | None | ||
526 | } | ||
527 | |||
492 | fn assoc_to_trait(db: &dyn DefDatabase, item: ItemInNs) -> Option<ItemInNs> { | 528 | fn assoc_to_trait(db: &dyn DefDatabase, item: ItemInNs) -> Option<ItemInNs> { |
493 | let assoc: AssocItemId = match item { | 529 | let assoc: AssocItemId = match item { |
494 | ItemInNs::Types(it) | ItemInNs::Values(it) => match it { | 530 | ItemInNs::Types(it) | ItemInNs::Values(it) => match it { |
@@ -747,6 +783,37 @@ mod tests { | |||
747 | } | 783 | } |
748 | 784 | ||
749 | #[test] | 785 | #[test] |
786 | fn fuzzy_import_trait_and_assoc_items() { | ||
787 | mark::check!(type_aliases_ignored); | ||
788 | let ra_fixture = r#" | ||
789 | //- /main.rs crate:main deps:dep | ||
790 | //- /dep.rs crate:dep | ||
791 | pub mod fmt { | ||
792 | pub trait Display { | ||
793 | type FmtTypeAlias; | ||
794 | const FMT_CONST: bool; | ||
795 | |||
796 | fn format_function(); | ||
797 | fn format_method(&self); | ||
798 | } | ||
799 | } | ||
800 | "#; | ||
801 | |||
802 | check_search( | ||
803 | ra_fixture, | ||
804 | "main", | ||
805 | Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy), | ||
806 | expect![[r#" | ||
807 | dep::fmt (t) | ||
808 | dep::fmt::Display (t) | ||
809 | dep::fmt::Display::FMT_CONST (a) | ||
810 | dep::fmt::Display::format_function (a) | ||
811 | dep::fmt::Display::format_method (a) | ||
812 | "#]], | ||
813 | ); | ||
814 | } | ||
815 | |||
816 | #[test] | ||
750 | fn search_mode() { | 817 | fn search_mode() { |
751 | let ra_fixture = r#" | 818 | let ra_fixture = r#" |
752 | //- /main.rs crate:main deps:dep | 819 | //- /main.rs crate:main deps:dep |
@@ -782,8 +849,8 @@ mod tests { | |||
782 | dep::Fmt (v) | 849 | dep::Fmt (v) |
783 | dep::Fmt (m) | 850 | dep::Fmt (m) |
784 | dep::fmt::Display (t) | 851 | dep::fmt::Display (t) |
852 | dep::fmt::Display::fmt (a) | ||
785 | dep::format (f) | 853 | dep::format (f) |
786 | dep::fmt::Display::fmt (f) | ||
787 | "#]], | 854 | "#]], |
788 | ); | 855 | ); |
789 | 856 | ||
@@ -796,7 +863,7 @@ mod tests { | |||
796 | dep::Fmt (t) | 863 | dep::Fmt (t) |
797 | dep::Fmt (v) | 864 | dep::Fmt (v) |
798 | dep::Fmt (m) | 865 | dep::Fmt (m) |
799 | dep::fmt::Display::fmt (f) | 866 | dep::fmt::Display::fmt (a) |
800 | "#]], | 867 | "#]], |
801 | ); | 868 | ); |
802 | 869 | ||
@@ -810,7 +877,7 @@ mod tests { | |||
810 | dep::Fmt (v) | 877 | dep::Fmt (v) |
811 | dep::Fmt (m) | 878 | dep::Fmt (m) |
812 | dep::fmt::Display (t) | 879 | dep::fmt::Display (t) |
813 | dep::fmt::Display::fmt (f) | 880 | dep::fmt::Display::fmt (a) |
814 | "#]], | 881 | "#]], |
815 | ); | 882 | ); |
816 | } | 883 | } |
@@ -851,7 +918,7 @@ mod tests { | |||
851 | dep::Fmt (v) | 918 | dep::Fmt (v) |
852 | dep::Fmt (m) | 919 | dep::Fmt (m) |
853 | dep::fmt::Display (t) | 920 | dep::fmt::Display (t) |
854 | dep::fmt::Display::fmt (f) | 921 | dep::fmt::Display::fmt (a) |
855 | "#]], | 922 | "#]], |
856 | ); | 923 | ); |
857 | 924 | ||
@@ -864,7 +931,7 @@ mod tests { | |||
864 | dep::Fmt (t) | 931 | dep::Fmt (t) |
865 | dep::Fmt (v) | 932 | dep::Fmt (v) |
866 | dep::Fmt (m) | 933 | dep::Fmt (m) |
867 | dep::fmt::Display::fmt (f) | 934 | dep::fmt::Display::fmt (a) |
868 | "#]], | 935 | "#]], |
869 | ); | 936 | ); |
870 | } | 937 | } |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index 62ab3b2bd..2750e1c91 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -10,10 +10,9 @@ use once_cell::sync::Lazy; | |||
10 | use rustc_hash::{FxHashMap, FxHashSet}; | 10 | use rustc_hash::{FxHashMap, FxHashSet}; |
11 | use test_utils::mark; | 11 | use test_utils::mark; |
12 | 12 | ||
13 | use crate::ModuleId; | ||
14 | use crate::{ | 13 | use crate::{ |
15 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, | 14 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, |
16 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId, | 15 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, ModuleId, TraitId, |
17 | }; | 16 | }; |
18 | 17 | ||
19 | #[derive(Copy, Clone)] | 18 | #[derive(Copy, Clone)] |
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 9bf358775..5682e122d 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -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/collector.rs b/crates/hir_def/src/nameres/collector.rs index a636ec77d..f027fd48d 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -13,7 +13,7 @@ use hir_expand::{ | |||
13 | builtin_macro::find_builtin_macro, | 13 | builtin_macro::find_builtin_macro, |
14 | name::{AsName, Name}, | 14 | name::{AsName, Name}, |
15 | proc_macro::ProcMacroExpander, | 15 | proc_macro::ProcMacroExpander, |
16 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, | 16 | HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, |
17 | }; | 17 | }; |
18 | use hir_expand::{InFile, MacroCallLoc}; | 18 | use hir_expand::{InFile, MacroCallLoc}; |
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 19 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -267,7 +267,7 @@ impl DefCollector<'_> { | |||
267 | 267 | ||
268 | // Resolve all indeterminate resolved imports again | 268 | // Resolve all indeterminate resolved imports again |
269 | // As some of the macros will expand newly import shadowing partial resolved imports | 269 | // As some of the macros will expand newly import shadowing partial resolved imports |
270 | // FIXME: We maybe could skip this, if we handle the Indetermine imports in `resolve_imports` | 270 | // FIXME: We maybe could skip this, if we handle the indeterminate imports in `resolve_imports` |
271 | // correctly | 271 | // correctly |
272 | let partial_resolved = self.resolved_imports.iter().filter_map(|directive| { | 272 | let partial_resolved = self.resolved_imports.iter().filter_map(|directive| { |
273 | if let PartialResolvedImport::Indeterminate(_) = directive.status { | 273 | if let PartialResolvedImport::Indeterminate(_) = directive.status { |
@@ -402,7 +402,7 @@ impl DefCollector<'_> { | |||
402 | 402 | ||
403 | /// Define a proc macro | 403 | /// Define a proc macro |
404 | /// | 404 | /// |
405 | /// A proc macro is similar to normal macro scope, but it would not visiable in legacy textual scoped. | 405 | /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped. |
406 | /// And unconditionally exported. | 406 | /// And unconditionally exported. |
407 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { | 407 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { |
408 | self.update( | 408 | self.update( |
@@ -592,7 +592,7 @@ impl DefCollector<'_> { | |||
592 | // XXX: urgh, so this works by accident! Here, we look at | 592 | // XXX: urgh, so this works by accident! Here, we look at |
593 | // the enum data, and, in theory, this might require us to | 593 | // the enum data, and, in theory, this might require us to |
594 | // look back at the crate_def_map, creating a cycle. For | 594 | // look back at the crate_def_map, creating a cycle. For |
595 | // example, `enum E { crate::some_macro!(); }`. Luckely, the | 595 | // example, `enum E { crate::some_macro!(); }`. Luckily, the |
596 | // only kind of macro that is allowed inside enum is a | 596 | // only kind of macro that is allowed inside enum is a |
597 | // `cfg_macro`, and we don't need to run name resolution for | 597 | // `cfg_macro`, and we don't need to run name resolution for |
598 | // it, but this is sheer luck! | 598 | // it, but this is sheer luck! |
@@ -655,7 +655,7 @@ impl DefCollector<'_> { | |||
655 | &mut self, | 655 | &mut self, |
656 | module_id: LocalModuleId, | 656 | module_id: LocalModuleId, |
657 | resolutions: &[(Option<Name>, PerNs)], | 657 | resolutions: &[(Option<Name>, PerNs)], |
658 | // All resolutions are imported with this visibility; the visibilies in | 658 | // All resolutions are imported with this visibility; the visibilities in |
659 | // the `PerNs` values are ignored and overwritten | 659 | // the `PerNs` values are ignored and overwritten |
660 | vis: Visibility, | 660 | vis: Visibility, |
661 | import_type: ImportType, | 661 | import_type: ImportType, |
@@ -860,6 +860,37 @@ impl DefCollector<'_> { | |||
860 | } | 860 | } |
861 | 861 | ||
862 | fn finish(mut self) -> CrateDefMap { | 862 | fn finish(mut self) -> CrateDefMap { |
863 | // Emit diagnostics for all remaining unexpanded macros. | ||
864 | |||
865 | for directive in &self.unexpanded_macros { | ||
866 | let mut error = None; | ||
867 | directive.ast_id.as_call_id_with_errors( | ||
868 | self.db, | ||
869 | self.def_map.krate, | ||
870 | |path| { | ||
871 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | ||
872 | self.db, | ||
873 | ResolveMode::Other, | ||
874 | directive.module_id, | ||
875 | &path, | ||
876 | BuiltinShadowMode::Module, | ||
877 | ); | ||
878 | resolved_res.resolved_def.take_macros() | ||
879 | }, | ||
880 | &mut |e| { | ||
881 | error.get_or_insert(e); | ||
882 | }, | ||
883 | ); | ||
884 | |||
885 | if let Some(err) = error { | ||
886 | self.def_map.diagnostics.push(DefDiagnostic::macro_error( | ||
887 | directive.module_id, | ||
888 | MacroCallKind::FnLike(directive.ast_id.ast_id), | ||
889 | err.to_string(), | ||
890 | )); | ||
891 | } | ||
892 | } | ||
893 | |||
863 | // Emit diagnostics for all remaining unresolved imports. | 894 | // Emit diagnostics for all remaining unresolved imports. |
864 | 895 | ||
865 | // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't | 896 | // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't |
diff --git a/crates/hir_def/src/nameres/tests/incremental.rs b/crates/hir_def/src/nameres/tests/incremental.rs index 8981fa7c9..509e1bbbc 100644 --- a/crates/hir_def/src/nameres/tests/incremental.rs +++ b/crates/hir_def/src/nameres/tests/incremental.rs | |||
@@ -28,7 +28,7 @@ fn typing_inside_a_function_should_not_invalidate_def_map() { | |||
28 | check_def_map_is_not_recomputed( | 28 | check_def_map_is_not_recomputed( |
29 | r" | 29 | r" |
30 | //- /lib.rs | 30 | //- /lib.rs |
31 | mod foo;<|> | 31 | mod foo;$0 |
32 | 32 | ||
33 | use crate::foo::bar::Baz; | 33 | use crate::foo::bar::Baz; |
34 | 34 | ||
@@ -81,7 +81,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { | |||
81 | pub mod bar; | 81 | pub mod bar; |
82 | 82 | ||
83 | //- /foo/bar.rs | 83 | //- /foo/bar.rs |
84 | <|> | 84 | $0 |
85 | m!(X); | 85 | m!(X); |
86 | ", | 86 | ", |
87 | ); | 87 | ); |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index e2bf85bbc..3dd7c3cbb 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -305,6 +305,7 @@ pub use hir_expand::name as __name; | |||
305 | macro_rules! __known_path { | 305 | macro_rules! __known_path { |
306 | (core::iter::IntoIterator) => {}; | 306 | (core::iter::IntoIterator) => {}; |
307 | (core::result::Result) => {}; | 307 | (core::result::Result) => {}; |
308 | (core::option::Option) => {}; | ||
308 | (core::ops::Range) => {}; | 309 | (core::ops::Range) => {}; |
309 | (core::ops::RangeFrom) => {}; | 310 | (core::ops::RangeFrom) => {}; |
310 | (core::ops::RangeFull) => {}; | 311 | (core::ops::RangeFull) => {}; |
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 779754ada..61059c349 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -20,14 +20,14 @@ 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)] |
29 | pub struct Resolver { | 29 | pub struct Resolver { |
30 | // FIXME: all usages generally call `.rev`, so maybe reverse once in consturciton? | 30 | // FIXME: all usages generally call `.rev`, so maybe reverse once in construction? |
31 | scopes: Vec<Scope>, | 31 | scopes: Vec<Scope>, |
32 | } | 32 | } |
33 | 33 | ||
@@ -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_) => { |