aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Daniel Faria <[email protected]>2020-06-26 02:34:39 +0100
committerPaul Daniel Faria <[email protected]>2020-06-26 16:11:51 +0100
commit76755ce176222128c354647941cea65ac30ff4bd (patch)
treec79df926033b6eb94522c5dcf6f17734640eeb13
parentde9e964e4ac21897bd48adbe37f379d74422919f (diff)
Split glob import map to per-ns, switch ExprCollector to use a simpler push_res
-rw-r--r--crates/ra_hir_def/src/body/lower.rs6
-rw-r--r--crates/ra_hir_def/src/item_scope.rs77
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs14
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs46
4 files changed, 110 insertions, 33 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index d749c828d..3ced648e5 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -26,7 +26,7 @@ use crate::{
26 dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, 26 dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal,
27 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 27 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
28 }, 28 },
29 item_scope::{BuiltinShadowMode, ImportType}, 29 item_scope::BuiltinShadowMode,
30 item_tree::{FileItemTreeId, ItemTree, ItemTreeNode}, 30 item_tree::{FileItemTreeId, ItemTree, ItemTreeNode},
31 path::{GenericArgs, Path}, 31 path::{GenericArgs, Path},
32 type_ref::{Mutability, Rawness, TypeRef}, 32 type_ref::{Mutability, Rawness, TypeRef},
@@ -81,7 +81,6 @@ pub(super) fn lower(
81 map 81 map
82 }, 82 },
83 expander, 83 expander,
84 import_types: FxHashMap::default(),
85 } 84 }
86 .collect(params, body) 85 .collect(params, body)
87} 86}
@@ -94,7 +93,6 @@ struct ExprCollector<'a> {
94 source_map: BodySourceMap, 93 source_map: BodySourceMap,
95 94
96 item_trees: FxHashMap<HirFileId, Arc<ItemTree>>, 95 item_trees: FxHashMap<HirFileId, Arc<ItemTree>>,
97 import_types: FxHashMap<Name, ImportType>,
98} 96}
99 97
100impl ExprCollector<'_> { 98impl ExprCollector<'_> {
@@ -713,10 +711,8 @@ impl ExprCollector<'_> {
713 _ => true, 711 _ => true,
714 }; 712 };
715 self.body.item_scope.push_res( 713 self.body.item_scope.push_res(
716 &mut self.import_types,
717 name.as_name(), 714 name.as_name(),
718 crate::per_ns::PerNs::from_def(def, vis, has_constructor), 715 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
719 ImportType::Named,
720 ); 716 );
721 } 717 }
722 } 718 }
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs
index 511c08a8d..d0923df6d 100644
--- a/crates/ra_hir_def/src/item_scope.rs
+++ b/crates/ra_hir_def/src/item_scope.rs
@@ -4,12 +4,12 @@
4use hir_expand::name::Name; 4use hir_expand::name::Name;
5use once_cell::sync::Lazy; 5use once_cell::sync::Lazy;
6use ra_db::CrateId; 6use ra_db::CrateId;
7use rustc_hash::FxHashMap; 7use rustc_hash::{FxHashMap, FxHashSet};
8use test_utils::mark; 8use test_utils::mark;
9 9
10use crate::{ 10use 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)] 15#[derive(Copy, Clone)]
@@ -19,13 +19,6 @@ pub(crate) enum ImportType {
19} 19}
20 20
21impl ImportType { 21impl ImportType {
22 fn is_glob(&self) -> bool {
23 match self {
24 ImportType::Glob => true,
25 ImportType::Named => false,
26 }
27 }
28
29 fn is_named(&self) -> bool { 22 fn is_named(&self) -> bool {
30 match self { 23 match self {
31 ImportType::Glob => false, 24 ImportType::Glob => false,
@@ -34,6 +27,13 @@ impl ImportType {
34 } 27 }
35} 28}
36 29
30#[derive(Debug, Default)]
31pub struct PerNsGlobImports {
32 types: FxHashSet<(LocalModuleId, Name)>,
33 values: FxHashSet<(LocalModuleId, Name)>,
34 macros: FxHashSet<(LocalModuleId, Name)>,
35}
36
37#[derive(Debug, Default, PartialEq, Eq)] 37#[derive(Debug, Default, PartialEq, Eq)]
38pub struct ItemScope { 38pub struct ItemScope {
39 visible: FxHashMap<Name, PerNs>, 39 visible: FxHashMap<Name, PerNs>,
@@ -145,30 +145,65 @@ impl ItemScope {
145 self.legacy_macros.insert(name, mac); 145 self.legacy_macros.insert(name, mac);
146 } 146 }
147 147
148 pub(crate) fn push_res( 148 pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool {
149 let mut changed = false;
150 let existing = self.visible.entry(name).or_default();
151
152 if existing.types.is_none() && def.types.is_some() {
153 existing.types = def.types;
154 changed = true;
155 }
156
157 if existing.values.is_none() && def.values.is_some() {
158 existing.values = def.values;
159 changed = true;
160 }
161
162 if existing.macros.is_none() && def.macros.is_some() {
163 existing.macros = def.macros;
164 changed = true;
165 }
166
167 changed
168 }
169
170 pub(crate) fn push_res_with_import(
149 &mut self, 171 &mut self,
150 existing_import_map: &mut FxHashMap<Name, ImportType>, 172 glob_imports: &mut PerNsGlobImports,
151 name: Name, 173 lookup: (LocalModuleId, Name),
152 def: PerNs, 174 def: PerNs,
153 def_import_type: ImportType, 175 def_import_type: ImportType,
154 ) -> bool { 176 ) -> bool {
155 let mut changed = false; 177 let mut changed = false;
156 let existing = self.visible.entry(name.clone()).or_default(); 178 let existing = self.visible.entry(lookup.1.clone()).or_default();
157 let existing_import_type = existing_import_map.entry(name).or_insert(def_import_type);
158 179
159 macro_rules! check_changed { 180 macro_rules! check_changed {
160 ($changed:ident, ($existing:ident/$def:ident).$field:ident, $existing_import_type:ident, $def_import_type:ident) => { 181 (
182 $changed:ident,
183 ( $existing:ident / $def:ident ) . $field:ident,
184 $glob_imports:ident [ $lookup:ident ],
185 $def_import_type:ident
186 ) => {
161 match ($existing.$field, $def.$field) { 187 match ($existing.$field, $def.$field) {
162 (None, Some(_)) => { 188 (None, Some(_)) => {
163 *existing_import_type = $def_import_type; 189 match $def_import_type {
190 ImportType::Glob => {
191 $glob_imports.$field.insert($lookup.clone());
192 }
193 ImportType::Named => {
194 $glob_imports.$field.remove(&$lookup);
195 }
196 }
197
164 $existing.$field = $def.$field; 198 $existing.$field = $def.$field;
165 $changed = true; 199 $changed = true;
166 } 200 }
167 (Some(_), Some(_)) 201 (Some(_), Some(_))
168 if $existing_import_type.is_glob() && $def_import_type.is_named() => 202 if $glob_imports.$field.contains(&$lookup)
203 && $def_import_type.is_named() =>
169 { 204 {
170 mark::hit!(import_shadowed); 205 mark::hit!(import_shadowed);
171 *$existing_import_type = $def_import_type; 206 $glob_imports.$field.remove(&$lookup);
172 $existing.$field = $def.$field; 207 $existing.$field = $def.$field;
173 $changed = true; 208 $changed = true;
174 } 209 }
@@ -177,9 +212,9 @@ impl ItemScope {
177 }; 212 };
178 } 213 }
179 214
180 check_changed!(changed, (existing / def).types, existing_import_type, def_import_type); 215 check_changed!(changed, (existing / def).types, glob_imports[lookup], def_import_type);
181 check_changed!(changed, (existing / def).values, existing_import_type, def_import_type); 216 check_changed!(changed, (existing / def).values, glob_imports[lookup], def_import_type);
182 check_changed!(changed, (existing / def).macros, existing_import_type, def_import_type); 217 check_changed!(changed, (existing / def).macros, glob_imports[lookup], def_import_type);
183 218
184 changed 219 changed
185 } 220 }
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index f7b99e0be..e74f67b3d 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -20,7 +20,7 @@ use test_utils::mark;
20use crate::{ 20use crate::{
21 attr::Attrs, 21 attr::Attrs,
22 db::DefDatabase, 22 db::DefDatabase,
23 item_scope::ImportType, 23 item_scope::{ImportType, PerNsGlobImports},
24 item_tree::{ 24 item_tree::{
25 self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind, 25 self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind,
26 }, 26 },
@@ -81,7 +81,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
81 mod_dirs: FxHashMap::default(), 81 mod_dirs: FxHashMap::default(),
82 cfg_options, 82 cfg_options,
83 proc_macros, 83 proc_macros,
84 import_types: FxHashMap::default(), 84 from_glob_import: Default::default(),
85 }; 85 };
86 collector.collect(); 86 collector.collect();
87 collector.finish() 87 collector.finish()
@@ -188,7 +188,7 @@ struct DefCollector<'a> {
188 mod_dirs: FxHashMap<LocalModuleId, ModDir>, 188 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
189 cfg_options: &'a CfgOptions, 189 cfg_options: &'a CfgOptions,
190 proc_macros: Vec<(Name, ProcMacroExpander)>, 190 proc_macros: Vec<(Name, ProcMacroExpander)>,
191 import_types: FxHashMap<Name, ImportType>, 191 from_glob_import: PerNsGlobImports,
192} 192}
193 193
194impl DefCollector<'_> { 194impl DefCollector<'_> {
@@ -595,9 +595,9 @@ impl DefCollector<'_> {
595 let scope = &mut self.def_map.modules[module_id].scope; 595 let scope = &mut self.def_map.modules[module_id].scope;
596 let mut changed = false; 596 let mut changed = false;
597 for (name, res) in resolutions { 597 for (name, res) in resolutions {
598 changed |= scope.push_res( 598 changed |= scope.push_res_with_import(
599 &mut self.import_types, 599 &mut self.from_glob_import,
600 name.clone(), 600 (module_id, name.clone()),
601 res.with_visibility(vis), 601 res.with_visibility(vis),
602 import_type, 602 import_type,
603 ); 603 );
@@ -1184,7 +1184,7 @@ mod tests {
1184 mod_dirs: FxHashMap::default(), 1184 mod_dirs: FxHashMap::default(),
1185 cfg_options: &CfgOptions::default(), 1185 cfg_options: &CfgOptions::default(),
1186 proc_macros: Default::default(), 1186 proc_macros: Default::default(),
1187 import_types: FxHashMap::default(), 1187 from_glob_import: Default::default(),
1188 }; 1188 };
1189 collector.collect(); 1189 collector.collect();
1190 collector.def_map 1190 collector.def_map
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index d7ef9add6..7d8197f8b 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -1739,6 +1739,52 @@ fn main() {
1739 assert_eq!(t, "u32"); 1739 assert_eq!(t, "u32");
1740} 1740}
1741 1741
1742// This test is actually testing the shadowing behavior within ra_hir_def. It
1743// lives here because the testing infrastructure in ra_hir_def isn't currently
1744// capable of asserting the necessary conditions.
1745#[test]
1746fn should_be_shadowing_imports() {
1747 let t = type_at(
1748 r#"
1749mod a {
1750 pub fn foo() -> i8 {0}
1751 pub struct foo { a: i8 }
1752}
1753mod b { pub fn foo () -> u8 {0} }
1754mod c { pub struct foo { a: u8 } }
1755mod d {
1756 pub use super::a::*;
1757 pub use super::c::foo;
1758 pub use super::b::foo;
1759}
1760
1761fn main() {
1762 d::foo()<|>;
1763}"#,
1764 );
1765 assert_eq!(t, "u8");
1766
1767 let t = type_at(
1768 r#"
1769mod a {
1770 pub fn foo() -> i8 {0}
1771 pub struct foo { a: i8 }
1772}
1773mod b { pub fn foo () -> u8 {0} }
1774mod c { pub struct foo { a: u8 } }
1775mod d {
1776 pub use super::a::*;
1777 pub use super::c::foo;
1778 pub use super::b::foo;
1779}
1780
1781fn main() {
1782 d::foo{a:0<|>};
1783}"#,
1784 );
1785 assert_eq!(t, "u8");
1786}
1787
1742#[test] 1788#[test]
1743fn closure_return() { 1789fn closure_return() {
1744 assert_snapshot!( 1790 assert_snapshot!(