aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
authorPaul Daniel Faria <[email protected]>2020-06-25 02:42:44 +0100
committerPaul Daniel Faria <[email protected]>2020-06-25 14:27:00 +0100
commit0b657ddbfe9754afce9811c70a4e61e4ea9efeaf (patch)
tree9a99332d1d2fa720fbb0da6af4122a5c4d6526f7 /crates/ra_hir_def
parent70d4829560b81e3f5dc8e624da702ed6d345c49c (diff)
Revert resolution of all glob imports first, replace with tracking of glob imports and shadowing when more specific
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/item_scope.rs20
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs84
-rw-r--r--crates/ra_hir_def/src/nameres/tests/globs.rs44
-rw-r--r--crates/ra_hir_def/src/per_ns.rs20
4 files changed, 119 insertions, 49 deletions
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs
index c81b966c3..0184b6af9 100644
--- a/crates/ra_hir_def/src/item_scope.rs
+++ b/crates/ra_hir_def/src/item_scope.rs
@@ -128,15 +128,19 @@ impl ItemScope {
128 let existing = self.visible.entry(name).or_default(); 128 let existing = self.visible.entry(name).or_default();
129 129
130 macro_rules! check_changed { 130 macro_rules! check_changed {
131 ($changed:ident, $existing:expr, $def:expr) => { 131 ($changed:ident, ($existing:ident/$def:ident).$field:ident) => {
132 match ($existing, $def) { 132 match ($existing.$field, $def.$field) {
133 (None, Some(_)) => { 133 (None, Some(_)) => {
134 $existing = $def; 134 $existing.from_glob = $def.from_glob;
135 $existing.$field = $def.$field;
135 $changed = true; 136 $changed = true;
136 } 137 }
137 (Some(e), Some(d)) if e.0 != d.0 => { 138 // Only update if the new def came from a specific import and the existing
139 // import came from a glob import.
140 (Some(_), Some(_)) if $existing.from_glob && !$def.from_glob => {
138 mark::hit!(import_shadowed); 141 mark::hit!(import_shadowed);
139 $existing = $def; 142 $existing.from_glob = $def.from_glob;
143 $existing.$field = $def.$field;
140 $changed = true; 144 $changed = true;
141 } 145 }
142 _ => {} 146 _ => {}
@@ -144,9 +148,9 @@ impl ItemScope {
144 }; 148 };
145 } 149 }
146 150
147 check_changed!(changed, existing.types, def.types); 151 check_changed!(changed, (existing / def).types);
148 check_changed!(changed, existing.values, def.values); 152 check_changed!(changed, (existing / def).values);
149 check_changed!(changed, existing.macros, def.macros); 153 check_changed!(changed, (existing / def).macros);
150 154
151 changed 155 changed
152 } 156 }
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 665dd106c..93f58e2c7 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -305,6 +305,7 @@ impl DefCollector<'_> {
305 self.def_map.root, 305 self.def_map.root,
306 &[(name, PerNs::macros(macro_, Visibility::Public))], 306 &[(name, PerNs::macros(macro_, Visibility::Public))],
307 Visibility::Public, 307 Visibility::Public,
308 false,
308 ); 309 );
309 } 310 }
310 } 311 }
@@ -330,6 +331,7 @@ impl DefCollector<'_> {
330 self.def_map.root, 331 self.def_map.root,
331 &[(name, PerNs::macros(macro_, Visibility::Public))], 332 &[(name, PerNs::macros(macro_, Visibility::Public))],
332 Visibility::Public, 333 Visibility::Public,
334 false,
333 ); 335 );
334 } 336 }
335 337
@@ -380,35 +382,25 @@ impl DefCollector<'_> {
380 382
381 while self.unresolved_imports.len() < n_previous_unresolved { 383 while self.unresolved_imports.len() < n_previous_unresolved {
382 n_previous_unresolved = self.unresolved_imports.len(); 384 n_previous_unresolved = self.unresolved_imports.len();
383 let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); 385 let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
384 for mut directive in &mut imports { 386 for mut directive in imports {
385 directive.status = self.resolve_import(directive.module_id, &directive.import); 387 directive.status = self.resolve_import(directive.module_id, &directive.import);
386 } 388 match directive.status {
387 389 PartialResolvedImport::Indeterminate(_) => {
388 let (glob_imports, non_glob_imports): (Vec<_>, Vec<_>) = 390 self.record_resolved_import(&directive);
389 imports.into_iter().partition(|directive| directive.import.is_glob); 391 // FIXME: For avoid performance regression,
390 let mut record = |imports: Vec<ImportDirective>| { 392 // we consider an imported resolved if it is indeterminate (i.e not all namespace resolved)
391 for directive in imports { 393 self.resolved_imports.push(directive)
392 match directive.status { 394 }
393 PartialResolvedImport::Indeterminate(_) => { 395 PartialResolvedImport::Resolved(_) => {
394 self.record_resolved_import(&directive); 396 self.record_resolved_import(&directive);
395 // FIXME: For avoid performance regression, 397 self.resolved_imports.push(directive)
396 // we consider an imported resolved if it is indeterminate (i.e not all namespace resolved) 398 }
397 self.resolved_imports.push(directive) 399 PartialResolvedImport::Unresolved => {
398 } 400 self.unresolved_imports.push(directive);
399 PartialResolvedImport::Resolved(_) => {
400 self.record_resolved_import(&directive);
401 self.resolved_imports.push(directive)
402 }
403 PartialResolvedImport::Unresolved => {
404 self.unresolved_imports.push(directive);
405 }
406 } 401 }
407 } 402 }
408 }; 403 }
409
410 record(glob_imports);
411 record(non_glob_imports);
412 } 404 }
413 } 405 }
414 406
@@ -486,7 +478,7 @@ impl DefCollector<'_> {
486 .filter(|(_, res)| !res.is_none()) 478 .filter(|(_, res)| !res.is_none())
487 .collect::<Vec<_>>(); 479 .collect::<Vec<_>>();
488 480
489 self.update(module_id, &items, vis); 481 self.update(module_id, &items, vis, true);
490 } else { 482 } else {
491 // glob import from same crate => we do an initial 483 // glob import from same crate => we do an initial
492 // import, and then need to propagate any further 484 // import, and then need to propagate any further
@@ -508,7 +500,7 @@ impl DefCollector<'_> {
508 .filter(|(_, res)| !res.is_none()) 500 .filter(|(_, res)| !res.is_none())
509 .collect::<Vec<_>>(); 501 .collect::<Vec<_>>();
510 502
511 self.update(module_id, &items, vis); 503 self.update(module_id, &items, vis, true);
512 // record the glob import in case we add further items 504 // record the glob import in case we add further items
513 let glob = self.glob_imports.entry(m.local_id).or_default(); 505 let glob = self.glob_imports.entry(m.local_id).or_default();
514 if !glob.iter().any(|(mid, _)| *mid == module_id) { 506 if !glob.iter().any(|(mid, _)| *mid == module_id) {
@@ -538,7 +530,7 @@ impl DefCollector<'_> {
538 (name, res) 530 (name, res)
539 }) 531 })
540 .collect::<Vec<_>>(); 532 .collect::<Vec<_>>();
541 self.update(module_id, &resolutions, vis); 533 self.update(module_id, &resolutions, vis, true);
542 } 534 }
543 Some(d) => { 535 Some(d) => {
544 log::debug!("glob import {:?} from non-module/enum {:?}", import, d); 536 log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
@@ -564,15 +556,21 @@ impl DefCollector<'_> {
564 } 556 }
565 } 557 }
566 558
567 self.update(module_id, &[(name, def)], vis); 559 self.update(module_id, &[(name, def)], vis, false);
568 } 560 }
569 None => mark::hit!(bogus_paths), 561 None => mark::hit!(bogus_paths),
570 } 562 }
571 } 563 }
572 } 564 }
573 565
574 fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)], vis: Visibility) { 566 fn update(
575 self.update_recursive(module_id, resolutions, vis, 0) 567 &mut self,
568 module_id: LocalModuleId,
569 resolutions: &[(Name, PerNs)],
570 vis: Visibility,
571 is_from_glob: bool,
572 ) {
573 self.update_recursive(module_id, resolutions, vis, is_from_glob, 0)
576 } 574 }
577 575
578 fn update_recursive( 576 fn update_recursive(
@@ -582,6 +580,9 @@ impl DefCollector<'_> {
582 // All resolutions are imported with this visibility; the visibilies in 580 // All resolutions are imported with this visibility; the visibilies in
583 // the `PerNs` values are ignored and overwritten 581 // the `PerNs` values are ignored and overwritten
584 vis: Visibility, 582 vis: Visibility,
583 // All resolutions are imported with this glob status; the glob status
584 // in the `PerNs` values are ignored and overwritten
585 is_from_glob: bool,
585 depth: usize, 586 depth: usize,
586 ) { 587 ) {
587 if depth > 100 { 588 if depth > 100 {
@@ -591,7 +592,8 @@ impl DefCollector<'_> {
591 let scope = &mut self.def_map.modules[module_id].scope; 592 let scope = &mut self.def_map.modules[module_id].scope;
592 let mut changed = false; 593 let mut changed = false;
593 for (name, res) in resolutions { 594 for (name, res) in resolutions {
594 changed |= scope.push_res(name.clone(), res.with_visibility(vis)); 595 changed |=
596 scope.push_res(name.clone(), res.with_visibility(vis).from_glob(is_from_glob));
595 } 597 }
596 598
597 if !changed { 599 if !changed {
@@ -610,7 +612,13 @@ impl DefCollector<'_> {
610 if !vis.is_visible_from_def_map(&self.def_map, glob_importing_module) { 612 if !vis.is_visible_from_def_map(&self.def_map, glob_importing_module) {
611 continue; 613 continue;
612 } 614 }
613 self.update_recursive(glob_importing_module, resolutions, glob_import_vis, depth + 1); 615 self.update_recursive(
616 glob_importing_module,
617 resolutions,
618 glob_import_vis,
619 true,
620 depth + 1,
621 );
614 } 622 }
615 } 623 }
616 624
@@ -932,6 +940,7 @@ impl ModCollector<'_, '_> {
932 self.module_id, 940 self.module_id,
933 &[(name.clone(), PerNs::from_def(id, vis, has_constructor))], 941 &[(name.clone(), PerNs::from_def(id, vis, has_constructor))],
934 vis, 942 vis,
943 false,
935 ) 944 )
936 } 945 }
937 } 946 }
@@ -1034,7 +1043,12 @@ impl ModCollector<'_, '_> {
1034 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; 1043 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res };
1035 let def: ModuleDefId = module.into(); 1044 let def: ModuleDefId = module.into();
1036 self.def_collector.def_map.modules[self.module_id].scope.define_def(def); 1045 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
1037 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis, false))], vis); 1046 self.def_collector.update(
1047 self.module_id,
1048 &[(name, PerNs::from_def(def, vis, false))],
1049 vis,
1050 false,
1051 );
1038 res 1052 res
1039 } 1053 }
1040 1054
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs
index d5a02137c..7f3d7509c 100644
--- a/crates/ra_hir_def/src/nameres/tests/globs.rs
+++ b/crates/ra_hir_def/src/nameres/tests/globs.rs
@@ -322,3 +322,47 @@ fn glob_shadowed_def_reversed() {
322 "### 322 "###
323 ); 323 );
324} 324}
325
326#[test]
327fn 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/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs
index 74665c588..e5cbca71d 100644
--- a/crates/ra_hir_def/src/per_ns.rs
+++ b/crates/ra_hir_def/src/per_ns.rs
@@ -9,6 +9,7 @@ use crate::{item_scope::ItemInNs, visibility::Visibility, ModuleDefId};
9 9
10#[derive(Debug, Copy, Clone, PartialEq, Eq)] 10#[derive(Debug, Copy, Clone, PartialEq, Eq)]
11pub struct PerNs { 11pub struct PerNs {
12 pub from_glob: bool,
12 pub types: Option<(ModuleDefId, Visibility)>, 13 pub types: Option<(ModuleDefId, Visibility)>,
13 pub values: Option<(ModuleDefId, Visibility)>, 14 pub values: Option<(ModuleDefId, Visibility)>,
14 pub macros: Option<(MacroDefId, Visibility)>, 15 pub macros: Option<(MacroDefId, Visibility)>,
@@ -16,29 +17,29 @@ pub struct PerNs {
16 17
17impl Default for PerNs { 18impl Default for PerNs {
18 fn default() -> Self { 19 fn default() -> Self {
19 PerNs { types: None, values: None, macros: None } 20 PerNs { from_glob: false, types: None, values: None, macros: None }
20 } 21 }
21} 22}
22 23
23impl PerNs { 24impl PerNs {
24 pub fn none() -> PerNs { 25 pub fn none() -> PerNs {
25 PerNs { types: None, values: None, macros: None } 26 PerNs { from_glob: false, types: None, values: None, macros: None }
26 } 27 }
27 28
28 pub fn values(t: ModuleDefId, v: Visibility) -> PerNs { 29 pub fn values(t: ModuleDefId, v: Visibility) -> PerNs {
29 PerNs { types: None, values: Some((t, v)), macros: None } 30 PerNs { from_glob: false, types: None, values: Some((t, v)), macros: None }
30 } 31 }
31 32
32 pub fn types(t: ModuleDefId, v: Visibility) -> PerNs { 33 pub fn types(t: ModuleDefId, v: Visibility) -> PerNs {
33 PerNs { types: Some((t, v)), values: None, macros: None } 34 PerNs { from_glob: false, types: Some((t, v)), values: None, macros: None }
34 } 35 }
35 36
36 pub fn both(types: ModuleDefId, values: ModuleDefId, v: Visibility) -> PerNs { 37 pub fn both(types: ModuleDefId, values: ModuleDefId, v: Visibility) -> PerNs {
37 PerNs { types: Some((types, v)), values: Some((values, v)), macros: None } 38 PerNs { from_glob: false, types: Some((types, v)), values: Some((values, v)), macros: None }
38 } 39 }
39 40
40 pub fn macros(macro_: MacroDefId, v: Visibility) -> PerNs { 41 pub fn macros(macro_: MacroDefId, v: Visibility) -> PerNs {
41 PerNs { types: None, values: None, macros: Some((macro_, v)) } 42 PerNs { from_glob: false, types: None, values: None, macros: Some((macro_, v)) }
42 } 43 }
43 44
44 pub fn is_none(&self) -> bool { 45 pub fn is_none(&self) -> bool {
@@ -63,6 +64,7 @@ impl PerNs {
63 64
64 pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { 65 pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs {
65 PerNs { 66 PerNs {
67 from_glob: self.from_glob,
66 types: self.types.filter(|(_, v)| f(*v)), 68 types: self.types.filter(|(_, v)| f(*v)),
67 values: self.values.filter(|(_, v)| f(*v)), 69 values: self.values.filter(|(_, v)| f(*v)),
68 macros: self.macros.filter(|(_, v)| f(*v)), 70 macros: self.macros.filter(|(_, v)| f(*v)),
@@ -71,6 +73,7 @@ impl PerNs {
71 73
72 pub fn with_visibility(self, vis: Visibility) -> PerNs { 74 pub fn with_visibility(self, vis: Visibility) -> PerNs {
73 PerNs { 75 PerNs {
76 from_glob: self.from_glob,
74 types: self.types.map(|(it, _)| (it, vis)), 77 types: self.types.map(|(it, _)| (it, vis)),
75 values: self.values.map(|(it, _)| (it, vis)), 78 values: self.values.map(|(it, _)| (it, vis)),
76 macros: self.macros.map(|(it, _)| (it, vis)), 79 macros: self.macros.map(|(it, _)| (it, vis)),
@@ -79,6 +82,7 @@ impl PerNs {
79 82
80 pub fn or(self, other: PerNs) -> PerNs { 83 pub fn or(self, other: PerNs) -> PerNs {
81 PerNs { 84 PerNs {
85 from_glob: self.from_glob,
82 types: self.types.or(other.types), 86 types: self.types.or(other.types),
83 values: self.values.or(other.values), 87 values: self.values.or(other.values),
84 macros: self.macros.or(other.macros), 88 macros: self.macros.or(other.macros),
@@ -92,4 +96,8 @@ impl PerNs {
92 .chain(self.values.map(|it| ItemInNs::Values(it.0)).into_iter()) 96 .chain(self.values.map(|it| ItemInNs::Values(it.0)).into_iter())
93 .chain(self.macros.map(|it| ItemInNs::Macros(it.0)).into_iter()) 97 .chain(self.macros.map(|it| ItemInNs::Macros(it.0)).into_iter())
94 } 98 }
99
100 pub fn from_glob(self, from_glob: bool) -> PerNs {
101 PerNs { from_glob, ..self }
102 }
95} 103}