diff options
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 98 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/scope.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_scope.rs | 79 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 49 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests/globs.rs | 90 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests/mod_resolution.rs | 16 |
6 files changed, 264 insertions, 81 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 3ced648e5..a7e2e0982 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -5,7 +5,7 @@ use either::Either; | |||
5 | use hir_expand::{ | 5 | use hir_expand::{ |
6 | hygiene::Hygiene, | 6 | hygiene::Hygiene, |
7 | name::{name, AsName, Name}, | 7 | name::{name, AsName, Name}, |
8 | AstId, HirFileId, MacroDefId, MacroDefKind, | 8 | HirFileId, MacroDefId, MacroDefKind, |
9 | }; | 9 | }; |
10 | use ra_arena::Arena; | 10 | use ra_arena::Arena; |
11 | use ra_syntax::{ | 11 | use ra_syntax::{ |
@@ -27,7 +27,7 @@ use crate::{ | |||
27 | LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, | 27 | LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, |
28 | }, | 28 | }, |
29 | item_scope::BuiltinShadowMode, | 29 | item_scope::BuiltinShadowMode, |
30 | item_tree::{FileItemTreeId, ItemTree, ItemTreeNode}, | 30 | item_tree::{ItemTree, ItemTreeId, ItemTreeNode}, |
31 | path::{GenericArgs, Path}, | 31 | path::{GenericArgs, Path}, |
32 | type_ref::{Mutability, Rawness, TypeRef}, | 32 | type_ref::{Mutability, Rawness, TypeRef}, |
33 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, | 33 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, |
@@ -37,7 +37,7 @@ use crate::{ | |||
37 | use super::{ExprSource, PatSource}; | 37 | use super::{ExprSource, PatSource}; |
38 | use ast::AstChildren; | 38 | use ast::AstChildren; |
39 | use rustc_hash::FxHashMap; | 39 | use rustc_hash::FxHashMap; |
40 | use std::sync::Arc; | 40 | use std::{any::type_name, sync::Arc}; |
41 | 41 | ||
42 | pub(crate) struct LowerCtx { | 42 | pub(crate) struct LowerCtx { |
43 | hygiene: Hygiene, | 43 | hygiene: Hygiene, |
@@ -561,17 +561,30 @@ impl ExprCollector<'_> { | |||
561 | } | 561 | } |
562 | } | 562 | } |
563 | 563 | ||
564 | fn find_inner_item<S: ItemTreeNode>(&self, id: AstId<ast::ModuleItem>) -> FileItemTreeId<S> { | 564 | fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> Option<ItemTreeId<N>> { |
565 | let id = self.expander.ast_id(ast); | ||
565 | let tree = &self.item_trees[&id.file_id]; | 566 | let tree = &self.item_trees[&id.file_id]; |
566 | 567 | ||
567 | // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes | 568 | // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes |
568 | 569 | ||
569 | // Root file (non-macro). | 570 | // Root file (non-macro). |
570 | tree.all_inner_items() | 571 | let item_tree_id = tree |
572 | .all_inner_items() | ||
571 | .chain(tree.top_level_items().iter().copied()) | 573 | .chain(tree.top_level_items().iter().copied()) |
572 | .filter_map(|mod_item| mod_item.downcast::<S>()) | 574 | .filter_map(|mod_item| mod_item.downcast::<N>()) |
573 | .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value) | 575 | .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast()) |
574 | .unwrap_or_else(|| panic!("couldn't find inner item for {:?}", id)) | 576 | .or_else(|| { |
577 | log::debug!( | ||
578 | "couldn't find inner {} item for {:?} (AST: `{}` - {:?})", | ||
579 | type_name::<N>(), | ||
580 | id, | ||
581 | ast.syntax(), | ||
582 | ast.syntax(), | ||
583 | ); | ||
584 | None | ||
585 | })?; | ||
586 | |||
587 | Some(ItemTreeId::new(id.file_id, item_tree_id)) | ||
575 | } | 588 | } |
576 | 589 | ||
577 | fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { | 590 | fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { |
@@ -611,82 +624,45 @@ impl ExprCollector<'_> { | |||
611 | .filter_map(|item| { | 624 | .filter_map(|item| { |
612 | let (def, name): (ModuleDefId, Option<ast::Name>) = match item { | 625 | let (def, name): (ModuleDefId, Option<ast::Name>) = match item { |
613 | ast::ModuleItem::FnDef(def) => { | 626 | ast::ModuleItem::FnDef(def) => { |
614 | let ast_id = self.expander.ast_id(&def); | 627 | let id = self.find_inner_item(&def)?; |
615 | let id = self.find_inner_item(ast_id.map(|id| id.upcast())); | ||
616 | ( | 628 | ( |
617 | FunctionLoc { container: container.into(), id: ast_id.with_value(id) } | 629 | FunctionLoc { container: container.into(), id }.intern(self.db).into(), |
618 | .intern(self.db) | ||
619 | .into(), | ||
620 | def.name(), | 630 | def.name(), |
621 | ) | 631 | ) |
622 | } | 632 | } |
623 | ast::ModuleItem::TypeAliasDef(def) => { | 633 | ast::ModuleItem::TypeAliasDef(def) => { |
624 | let ast_id = self.expander.ast_id(&def); | 634 | let id = self.find_inner_item(&def)?; |
625 | let id = self.find_inner_item(ast_id.map(|id| id.upcast())); | ||
626 | ( | 635 | ( |
627 | TypeAliasLoc { container: container.into(), id: ast_id.with_value(id) } | 636 | TypeAliasLoc { container: container.into(), id }.intern(self.db).into(), |
628 | .intern(self.db) | ||
629 | .into(), | ||
630 | def.name(), | 637 | def.name(), |
631 | ) | 638 | ) |
632 | } | 639 | } |
633 | ast::ModuleItem::ConstDef(def) => { | 640 | ast::ModuleItem::ConstDef(def) => { |
634 | let ast_id = self.expander.ast_id(&def); | 641 | let id = self.find_inner_item(&def)?; |
635 | let id = self.find_inner_item(ast_id.map(|id| id.upcast())); | ||
636 | ( | 642 | ( |
637 | ConstLoc { container: container.into(), id: ast_id.with_value(id) } | 643 | ConstLoc { container: container.into(), id }.intern(self.db).into(), |
638 | .intern(self.db) | ||
639 | .into(), | ||
640 | def.name(), | 644 | def.name(), |
641 | ) | 645 | ) |
642 | } | 646 | } |
643 | ast::ModuleItem::StaticDef(def) => { | 647 | ast::ModuleItem::StaticDef(def) => { |
644 | let ast_id = self.expander.ast_id(&def); | 648 | let id = self.find_inner_item(&def)?; |
645 | let id = self.find_inner_item(ast_id.map(|id| id.upcast())); | 649 | (StaticLoc { container, id }.intern(self.db).into(), def.name()) |
646 | ( | ||
647 | StaticLoc { container, id: ast_id.with_value(id) } | ||
648 | .intern(self.db) | ||
649 | .into(), | ||
650 | def.name(), | ||
651 | ) | ||
652 | } | 650 | } |
653 | ast::ModuleItem::StructDef(def) => { | 651 | ast::ModuleItem::StructDef(def) => { |
654 | let ast_id = self.expander.ast_id(&def); | 652 | let id = self.find_inner_item(&def)?; |
655 | let id = self.find_inner_item(ast_id.map(|id| id.upcast())); | 653 | (StructLoc { container, id }.intern(self.db).into(), def.name()) |
656 | ( | ||
657 | StructLoc { container, id: ast_id.with_value(id) } | ||
658 | .intern(self.db) | ||
659 | .into(), | ||
660 | def.name(), | ||
661 | ) | ||
662 | } | 654 | } |
663 | ast::ModuleItem::EnumDef(def) => { | 655 | ast::ModuleItem::EnumDef(def) => { |
664 | let ast_id = self.expander.ast_id(&def); | 656 | let id = self.find_inner_item(&def)?; |
665 | let id = self.find_inner_item(ast_id.map(|id| id.upcast())); | 657 | (EnumLoc { container, id }.intern(self.db).into(), def.name()) |
666 | ( | ||
667 | EnumLoc { container, id: ast_id.with_value(id) }.intern(self.db).into(), | ||
668 | def.name(), | ||
669 | ) | ||
670 | } | 658 | } |
671 | ast::ModuleItem::UnionDef(def) => { | 659 | ast::ModuleItem::UnionDef(def) => { |
672 | let ast_id = self.expander.ast_id(&def); | 660 | let id = self.find_inner_item(&def)?; |
673 | let id = self.find_inner_item(ast_id.map(|id| id.upcast())); | 661 | (UnionLoc { container, id }.intern(self.db).into(), def.name()) |
674 | ( | ||
675 | UnionLoc { container, id: ast_id.with_value(id) } | ||
676 | .intern(self.db) | ||
677 | .into(), | ||
678 | def.name(), | ||
679 | ) | ||
680 | } | 662 | } |
681 | ast::ModuleItem::TraitDef(def) => { | 663 | ast::ModuleItem::TraitDef(def) => { |
682 | let ast_id = self.expander.ast_id(&def); | 664 | let id = self.find_inner_item(&def)?; |
683 | let id = self.find_inner_item(ast_id.map(|id| id.upcast())); | 665 | (TraitLoc { container, id }.intern(self.db).into(), def.name()) |
684 | ( | ||
685 | TraitLoc { container, id: ast_id.with_value(id) } | ||
686 | .intern(self.db) | ||
687 | .into(), | ||
688 | def.name(), | ||
689 | ) | ||
690 | } | 666 | } |
691 | ast::ModuleItem::ExternBlock(_) => return None, // FIXME: collect from extern blocks | 667 | ast::ModuleItem::ExternBlock(_) => return None, // FIXME: collect from extern blocks |
692 | ast::ModuleItem::ImplDef(_) | 668 | ast::ModuleItem::ImplDef(_) |
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index 81397b063..99e876683 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs | |||
@@ -337,6 +337,19 @@ fn foo() { | |||
337 | ); | 337 | ); |
338 | } | 338 | } |
339 | 339 | ||
340 | #[test] | ||
341 | fn broken_inner_item() { | ||
342 | do_check( | ||
343 | r" | ||
344 | fn foo() { | ||
345 | trait {} | ||
346 | <|> | ||
347 | } | ||
348 | ", | ||
349 | &[], | ||
350 | ); | ||
351 | } | ||
352 | |||
340 | fn do_check_local_name(ra_fixture: &str, expected_offset: u32) { | 353 | fn do_check_local_name(ra_fixture: &str, expected_offset: u32) { |
341 | let (db, position) = TestDB::with_position(ra_fixture); | 354 | let (db, position) = TestDB::with_position(ra_fixture); |
342 | let file_id = position.file_id; | 355 | let file_id = position.file_id; |
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index c81b966c3..4d446c707 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs | |||
@@ -4,14 +4,27 @@ | |||
4 | use hir_expand::name::Name; | 4 | use hir_expand::name::Name; |
5 | use once_cell::sync::Lazy; | 5 | use once_cell::sync::Lazy; |
6 | use ra_db::CrateId; | 6 | use ra_db::CrateId; |
7 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::{FxHashMap, FxHashSet}; |
8 | use test_utils::mark; | 8 | use test_utils::mark; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, | 11 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, |
12 | Lookup, MacroDefId, ModuleDefId, TraitId, | 12 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | #[derive(Copy, Clone)] | ||
16 | pub(crate) enum ImportType { | ||
17 | Glob, | ||
18 | Named, | ||
19 | } | ||
20 | |||
21 | #[derive(Debug, Default)] | ||
22 | pub struct PerNsGlobImports { | ||
23 | types: FxHashSet<(LocalModuleId, Name)>, | ||
24 | values: FxHashSet<(LocalModuleId, Name)>, | ||
25 | macros: FxHashSet<(LocalModuleId, Name)>, | ||
26 | } | ||
27 | |||
15 | #[derive(Debug, Default, PartialEq, Eq)] | 28 | #[derive(Debug, Default, PartialEq, Eq)] |
16 | pub struct ItemScope { | 29 | pub struct ItemScope { |
17 | visible: FxHashMap<Name, PerNs>, | 30 | visible: FxHashMap<Name, PerNs>, |
@@ -127,16 +140,62 @@ impl ItemScope { | |||
127 | let mut changed = false; | 140 | let mut changed = false; |
128 | let existing = self.visible.entry(name).or_default(); | 141 | let existing = self.visible.entry(name).or_default(); |
129 | 142 | ||
143 | if existing.types.is_none() && def.types.is_some() { | ||
144 | existing.types = def.types; | ||
145 | changed = true; | ||
146 | } | ||
147 | |||
148 | if existing.values.is_none() && def.values.is_some() { | ||
149 | existing.values = def.values; | ||
150 | changed = true; | ||
151 | } | ||
152 | |||
153 | if existing.macros.is_none() && def.macros.is_some() { | ||
154 | existing.macros = def.macros; | ||
155 | changed = true; | ||
156 | } | ||
157 | |||
158 | changed | ||
159 | } | ||
160 | |||
161 | pub(crate) fn push_res_with_import( | ||
162 | &mut self, | ||
163 | glob_imports: &mut PerNsGlobImports, | ||
164 | lookup: (LocalModuleId, Name), | ||
165 | def: PerNs, | ||
166 | def_import_type: ImportType, | ||
167 | ) -> bool { | ||
168 | let mut changed = false; | ||
169 | let existing = self.visible.entry(lookup.1.clone()).or_default(); | ||
170 | |||
130 | macro_rules! check_changed { | 171 | macro_rules! check_changed { |
131 | ($changed:ident, $existing:expr, $def:expr) => { | 172 | ( |
132 | match ($existing, $def) { | 173 | $changed:ident, |
174 | ( $existing:ident / $def:ident ) . $field:ident, | ||
175 | $glob_imports:ident [ $lookup:ident ], | ||
176 | $def_import_type:ident | ||
177 | ) => { | ||
178 | match ($existing.$field, $def.$field) { | ||
133 | (None, Some(_)) => { | 179 | (None, Some(_)) => { |
134 | $existing = $def; | 180 | match $def_import_type { |
181 | ImportType::Glob => { | ||
182 | $glob_imports.$field.insert($lookup.clone()); | ||
183 | } | ||
184 | ImportType::Named => { | ||
185 | $glob_imports.$field.remove(&$lookup); | ||
186 | } | ||
187 | } | ||
188 | |||
189 | $existing.$field = $def.$field; | ||
135 | $changed = true; | 190 | $changed = true; |
136 | } | 191 | } |
137 | (Some(e), Some(d)) if e.0 != d.0 => { | 192 | (Some(_), Some(_)) |
193 | if $glob_imports.$field.contains(&$lookup) | ||
194 | && matches!($def_import_type, ImportType::Named) => | ||
195 | { | ||
138 | mark::hit!(import_shadowed); | 196 | mark::hit!(import_shadowed); |
139 | $existing = $def; | 197 | $glob_imports.$field.remove(&$lookup); |
198 | $existing.$field = $def.$field; | ||
140 | $changed = true; | 199 | $changed = true; |
141 | } | 200 | } |
142 | _ => {} | 201 | _ => {} |
@@ -144,9 +203,9 @@ impl ItemScope { | |||
144 | }; | 203 | }; |
145 | } | 204 | } |
146 | 205 | ||
147 | check_changed!(changed, existing.types, def.types); | 206 | check_changed!(changed, (existing / def).types, glob_imports[lookup], def_import_type); |
148 | check_changed!(changed, existing.values, def.values); | 207 | check_changed!(changed, (existing / def).values, glob_imports[lookup], def_import_type); |
149 | check_changed!(changed, existing.macros, def.macros); | 208 | check_changed!(changed, (existing / def).macros, glob_imports[lookup], def_import_type); |
150 | 209 | ||
151 | changed | 210 | changed |
152 | } | 211 | } |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 2ced4f66b..a35ac1024 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -20,6 +20,7 @@ use test_utils::mark; | |||
20 | use crate::{ | 20 | use crate::{ |
21 | attr::Attrs, | 21 | attr::Attrs, |
22 | db::DefDatabase, | 22 | db::DefDatabase, |
23 | item_scope::{ImportType, PerNsGlobImports}, | ||
23 | item_tree::{ | 24 | item_tree::{ |
24 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind, | 25 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind, |
25 | }, | 26 | }, |
@@ -80,6 +81,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr | |||
80 | mod_dirs: FxHashMap::default(), | 81 | mod_dirs: FxHashMap::default(), |
81 | cfg_options, | 82 | cfg_options, |
82 | proc_macros, | 83 | proc_macros, |
84 | from_glob_import: Default::default(), | ||
83 | }; | 85 | }; |
84 | collector.collect(); | 86 | collector.collect(); |
85 | collector.finish() | 87 | collector.finish() |
@@ -186,6 +188,7 @@ struct DefCollector<'a> { | |||
186 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, | 188 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, |
187 | cfg_options: &'a CfgOptions, | 189 | cfg_options: &'a CfgOptions, |
188 | proc_macros: Vec<(Name, ProcMacroExpander)>, | 190 | proc_macros: Vec<(Name, ProcMacroExpander)>, |
191 | from_glob_import: PerNsGlobImports, | ||
189 | } | 192 | } |
190 | 193 | ||
191 | impl DefCollector<'_> { | 194 | impl DefCollector<'_> { |
@@ -305,6 +308,7 @@ impl DefCollector<'_> { | |||
305 | self.def_map.root, | 308 | self.def_map.root, |
306 | &[(name, PerNs::macros(macro_, Visibility::Public))], | 309 | &[(name, PerNs::macros(macro_, Visibility::Public))], |
307 | Visibility::Public, | 310 | Visibility::Public, |
311 | ImportType::Named, | ||
308 | ); | 312 | ); |
309 | } | 313 | } |
310 | } | 314 | } |
@@ -330,6 +334,7 @@ impl DefCollector<'_> { | |||
330 | self.def_map.root, | 334 | self.def_map.root, |
331 | &[(name, PerNs::macros(macro_, Visibility::Public))], | 335 | &[(name, PerNs::macros(macro_, Visibility::Public))], |
332 | Visibility::Public, | 336 | Visibility::Public, |
337 | ImportType::Named, | ||
333 | ); | 338 | ); |
334 | } | 339 | } |
335 | 340 | ||
@@ -383,7 +388,6 @@ impl DefCollector<'_> { | |||
383 | let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); | 388 | let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); |
384 | for mut directive in imports { | 389 | for mut directive in imports { |
385 | directive.status = self.resolve_import(directive.module_id, &directive.import); | 390 | directive.status = self.resolve_import(directive.module_id, &directive.import); |
386 | |||
387 | match directive.status { | 391 | match directive.status { |
388 | PartialResolvedImport::Indeterminate(_) => { | 392 | PartialResolvedImport::Indeterminate(_) => { |
389 | self.record_resolved_import(&directive); | 393 | self.record_resolved_import(&directive); |
@@ -477,7 +481,7 @@ impl DefCollector<'_> { | |||
477 | .filter(|(_, res)| !res.is_none()) | 481 | .filter(|(_, res)| !res.is_none()) |
478 | .collect::<Vec<_>>(); | 482 | .collect::<Vec<_>>(); |
479 | 483 | ||
480 | self.update(module_id, &items, vis); | 484 | self.update(module_id, &items, vis, ImportType::Glob); |
481 | } else { | 485 | } else { |
482 | // glob import from same crate => we do an initial | 486 | // glob import from same crate => we do an initial |
483 | // import, and then need to propagate any further | 487 | // import, and then need to propagate any further |
@@ -499,7 +503,7 @@ impl DefCollector<'_> { | |||
499 | .filter(|(_, res)| !res.is_none()) | 503 | .filter(|(_, res)| !res.is_none()) |
500 | .collect::<Vec<_>>(); | 504 | .collect::<Vec<_>>(); |
501 | 505 | ||
502 | self.update(module_id, &items, vis); | 506 | self.update(module_id, &items, vis, ImportType::Glob); |
503 | // record the glob import in case we add further items | 507 | // record the glob import in case we add further items |
504 | let glob = self.glob_imports.entry(m.local_id).or_default(); | 508 | let glob = self.glob_imports.entry(m.local_id).or_default(); |
505 | if !glob.iter().any(|(mid, _)| *mid == module_id) { | 509 | if !glob.iter().any(|(mid, _)| *mid == module_id) { |
@@ -529,7 +533,7 @@ impl DefCollector<'_> { | |||
529 | (name, res) | 533 | (name, res) |
530 | }) | 534 | }) |
531 | .collect::<Vec<_>>(); | 535 | .collect::<Vec<_>>(); |
532 | self.update(module_id, &resolutions, vis); | 536 | self.update(module_id, &resolutions, vis, ImportType::Glob); |
533 | } | 537 | } |
534 | Some(d) => { | 538 | Some(d) => { |
535 | log::debug!("glob import {:?} from non-module/enum {:?}", import, d); | 539 | log::debug!("glob import {:?} from non-module/enum {:?}", import, d); |
@@ -555,15 +559,21 @@ impl DefCollector<'_> { | |||
555 | } | 559 | } |
556 | } | 560 | } |
557 | 561 | ||
558 | self.update(module_id, &[(name, def)], vis); | 562 | self.update(module_id, &[(name, def)], vis, ImportType::Named); |
559 | } | 563 | } |
560 | None => mark::hit!(bogus_paths), | 564 | None => mark::hit!(bogus_paths), |
561 | } | 565 | } |
562 | } | 566 | } |
563 | } | 567 | } |
564 | 568 | ||
565 | fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)], vis: Visibility) { | 569 | fn update( |
566 | self.update_recursive(module_id, resolutions, vis, 0) | 570 | &mut self, |
571 | module_id: LocalModuleId, | ||
572 | resolutions: &[(Name, PerNs)], | ||
573 | vis: Visibility, | ||
574 | import_type: ImportType, | ||
575 | ) { | ||
576 | self.update_recursive(module_id, resolutions, vis, import_type, 0) | ||
567 | } | 577 | } |
568 | 578 | ||
569 | fn update_recursive( | 579 | fn update_recursive( |
@@ -573,6 +583,7 @@ impl DefCollector<'_> { | |||
573 | // All resolutions are imported with this visibility; the visibilies in | 583 | // All resolutions are imported with this visibility; the visibilies in |
574 | // the `PerNs` values are ignored and overwritten | 584 | // the `PerNs` values are ignored and overwritten |
575 | vis: Visibility, | 585 | vis: Visibility, |
586 | import_type: ImportType, | ||
576 | depth: usize, | 587 | depth: usize, |
577 | ) { | 588 | ) { |
578 | if depth > 100 { | 589 | if depth > 100 { |
@@ -582,7 +593,12 @@ impl DefCollector<'_> { | |||
582 | let scope = &mut self.def_map.modules[module_id].scope; | 593 | let scope = &mut self.def_map.modules[module_id].scope; |
583 | let mut changed = false; | 594 | let mut changed = false; |
584 | for (name, res) in resolutions { | 595 | for (name, res) in resolutions { |
585 | changed |= scope.push_res(name.clone(), res.with_visibility(vis)); | 596 | changed |= scope.push_res_with_import( |
597 | &mut self.from_glob_import, | ||
598 | (module_id, name.clone()), | ||
599 | res.with_visibility(vis), | ||
600 | import_type, | ||
601 | ); | ||
586 | } | 602 | } |
587 | 603 | ||
588 | if !changed { | 604 | if !changed { |
@@ -601,7 +617,13 @@ impl DefCollector<'_> { | |||
601 | if !vis.is_visible_from_def_map(&self.def_map, glob_importing_module) { | 617 | if !vis.is_visible_from_def_map(&self.def_map, glob_importing_module) { |
602 | continue; | 618 | continue; |
603 | } | 619 | } |
604 | self.update_recursive(glob_importing_module, resolutions, glob_import_vis, depth + 1); | 620 | self.update_recursive( |
621 | glob_importing_module, | ||
622 | resolutions, | ||
623 | glob_import_vis, | ||
624 | ImportType::Glob, | ||
625 | depth + 1, | ||
626 | ); | ||
605 | } | 627 | } |
606 | } | 628 | } |
607 | 629 | ||
@@ -923,6 +945,7 @@ impl ModCollector<'_, '_> { | |||
923 | self.module_id, | 945 | self.module_id, |
924 | &[(name.clone(), PerNs::from_def(id, vis, has_constructor))], | 946 | &[(name.clone(), PerNs::from_def(id, vis, has_constructor))], |
925 | vis, | 947 | vis, |
948 | ImportType::Named, | ||
926 | ) | 949 | ) |
927 | } | 950 | } |
928 | } | 951 | } |
@@ -1025,7 +1048,12 @@ impl ModCollector<'_, '_> { | |||
1025 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; | 1048 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; |
1026 | let def: ModuleDefId = module.into(); | 1049 | let def: ModuleDefId = module.into(); |
1027 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 1050 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
1028 | self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis, false))], vis); | 1051 | self.def_collector.update( |
1052 | self.module_id, | ||
1053 | &[(name, PerNs::from_def(def, vis, false))], | ||
1054 | vis, | ||
1055 | ImportType::Named, | ||
1056 | ); | ||
1029 | res | 1057 | res |
1030 | } | 1058 | } |
1031 | 1059 | ||
@@ -1154,6 +1182,7 @@ mod tests { | |||
1154 | mod_dirs: FxHashMap::default(), | 1182 | mod_dirs: FxHashMap::default(), |
1155 | cfg_options: &CfgOptions::default(), | 1183 | cfg_options: &CfgOptions::default(), |
1156 | proc_macros: Default::default(), | 1184 | proc_macros: Default::default(), |
1185 | from_glob_import: Default::default(), | ||
1157 | }; | 1186 | }; |
1158 | collector.collect(); | 1187 | collector.collect(); |
1159 | collector.def_map | 1188 | collector.def_map |
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs index 2f440975a..7f3d7509c 100644 --- a/crates/ra_hir_def/src/nameres/tests/globs.rs +++ b/crates/ra_hir_def/src/nameres/tests/globs.rs | |||
@@ -276,3 +276,93 @@ fn glob_shadowed_def() { | |||
276 | "### | 276 | "### |
277 | ); | 277 | ); |
278 | } | 278 | } |
279 | |||
280 | #[test] | ||
281 | fn glob_shadowed_def_reversed() { | ||
282 | let map = def_map( | ||
283 | r###" | ||
284 | //- /lib.rs | ||
285 | mod foo; | ||
286 | mod bar; | ||
287 | |||
288 | use bar::baz; | ||
289 | use foo::*; | ||
290 | |||
291 | use baz::Bar; | ||
292 | |||
293 | //- /foo.rs | ||
294 | pub mod baz { | ||
295 | pub struct Foo; | ||
296 | } | ||
297 | |||
298 | //- /bar.rs | ||
299 | pub mod baz { | ||
300 | pub struct Bar; | ||
301 | } | ||
302 | "###, | ||
303 | ); | ||
304 | assert_snapshot!(map, @r###" | ||
305 | ⋮crate | ||
306 | ⋮Bar: t v | ||
307 | ⋮bar: t | ||
308 | ⋮baz: t | ||
309 | ⋮foo: t | ||
310 | ⋮ | ||
311 | ⋮crate::bar | ||
312 | ⋮baz: t | ||
313 | ⋮ | ||
314 | ⋮crate::bar::baz | ||
315 | ⋮Bar: t v | ||
316 | ⋮ | ||
317 | ⋮crate::foo | ||
318 | ⋮baz: t | ||
319 | ⋮ | ||
320 | ⋮crate::foo::baz | ||
321 | ⋮Foo: t v | ||
322 | "### | ||
323 | ); | ||
324 | } | ||
325 | |||
326 | #[test] | ||
327 | fn glob_shadowed_def_dependencies() { | ||
328 | let map = def_map( | ||
329 | r###" | ||
330 | //- /lib.rs | ||
331 | mod a { pub mod foo { pub struct X; } } | ||
332 | mod b { pub use super::a::foo; } | ||
333 | mod c { pub mod foo { pub struct Y; } } | ||
334 | mod d { | ||
335 | use super::c::foo; | ||
336 | use super::b::*; | ||
337 | use foo::Y; | ||
338 | } | ||
339 | "###, | ||
340 | ); | ||
341 | assert_snapshot!(map, @r###" | ||
342 | ⋮crate | ||
343 | ⋮a: t | ||
344 | ⋮b: t | ||
345 | ⋮c: t | ||
346 | ⋮d: t | ||
347 | ⋮ | ||
348 | ⋮crate::d | ||
349 | ⋮Y: t v | ||
350 | ⋮foo: t | ||
351 | ⋮ | ||
352 | ⋮crate::c | ||
353 | ⋮foo: t | ||
354 | ⋮ | ||
355 | ⋮crate::c::foo | ||
356 | ⋮Y: t v | ||
357 | ⋮ | ||
358 | ⋮crate::b | ||
359 | ⋮foo: t | ||
360 | ⋮ | ||
361 | ⋮crate::a | ||
362 | ⋮foo: t | ||
363 | ⋮ | ||
364 | ⋮crate::a::foo | ||
365 | ⋮X: t v | ||
366 | "### | ||
367 | ); | ||
368 | } | ||
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs index e9a5e4cba..753684201 100644 --- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs +++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs | |||
@@ -335,6 +335,22 @@ fn module_resolution_relative_path_2() { | |||
335 | } | 335 | } |
336 | 336 | ||
337 | #[test] | 337 | #[test] |
338 | fn module_resolution_relative_path_outside_root() { | ||
339 | let map = def_map( | ||
340 | r###" | ||
341 | //- /main.rs | ||
342 | |||
343 | #[path="../../../../../outside.rs"] | ||
344 | mod foo; | ||
345 | "###, | ||
346 | ); | ||
347 | |||
348 | assert_snapshot!(map, @r###" | ||
349 | ⋮crate | ||
350 | "###); | ||
351 | } | ||
352 | |||
353 | #[test] | ||
338 | fn module_resolution_explicit_path_mod_rs_2() { | 354 | fn module_resolution_explicit_path_mod_rs_2() { |
339 | let map = def_map( | 355 | let map = def_map( |
340 | r###" | 356 | r###" |