diff options
-rw-r--r-- | crates/ra_hir_def/src/item_scope.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 84 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests/globs.rs | 44 | ||||
-rw-r--r-- | crates/ra_hir_def/src/per_ns.rs | 20 |
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] | ||
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/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)] |
11 | pub struct PerNs { | 11 | pub 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 | ||
17 | impl Default for PerNs { | 18 | impl 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 | ||
23 | impl PerNs { | 24 | impl 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 | } |