From e0f305a6bf710f64f789f909da93a8c362823b67 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Sat, 7 Sep 2019 00:55:58 +0800 Subject: Support textual scoped macros --- crates/ra_hir/src/nameres.rs | 5 ++ crates/ra_hir/src/nameres/collector.rs | 84 +++++++++++++++++----------- crates/ra_hir/src/nameres/raw.rs | 12 +++- crates/ra_hir/src/nameres/tests/macros.rs | 91 +++++++++++++++++++++++++++++++ 4 files changed, 158 insertions(+), 34 deletions(-) diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 7de422128..e6bf0e90c 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -139,6 +139,7 @@ pub(crate) struct ModuleData { pub struct ModuleScope { items: FxHashMap, macros: FxHashMap, + textual_macros: FxHashMap, } static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { @@ -164,6 +165,7 @@ impl ModuleScope { _ => None, }) } + /// It resolves in module scope. Textual scoped macros are ignored here. fn get_item_or_macro(&self, name: &Name) -> Option { match (self.get(name), self.macros.get(name)) { (Some(item), _) if !item.def.is_none() => Some(Either::A(item.def)), @@ -171,6 +173,9 @@ impl ModuleScope { _ => None, } } + fn get_textual_macro(&self, name: &Name) -> Option { + self.textual_macros.get(name).copied() + } } type ItemOrMacro = Either, MacroDef>; diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index 1c0d4369e..f897547e3 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -40,7 +40,6 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C glob_imports: FxHashMap::default(), unresolved_imports: Vec::new(), unexpanded_macros: Vec::new(), - global_macro_scope: FxHashMap::default(), macro_stack_monitor: MacroStackMonitor::default(), }; collector.collect(); @@ -82,7 +81,6 @@ struct DefCollector { glob_imports: FxHashMap>, unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, unexpanded_macros: Vec<(CrateModuleId, AstId, Path)>, - global_macro_scope: FxHashMap, /// Some macro use `$tt:tt which mean we have to handle the macro perfectly /// To prevent stack overflow, we add a deep counter here for prevent that. @@ -136,20 +134,6 @@ where macro_id: MacroDefId, export: bool, ) { - // macro-by-example in Rust have completely weird name resolution logic, - // unlike anything else in the language. We'd don't fully implement yet, - // just give a somewhat precise approximation. - // - // Specifically, we store a set of visible macros in each module, just - // like how we do with usual items. This is wrong, however, because - // macros can be shadowed and their scopes are mostly unrelated to - // modules. To paper over the second problem, we also maintain - // `global_macro_scope` which works when we construct `CrateDefMap`, but - // is completely ignored in expressions. - // - // What we should do is that, in CrateDefMap, we should maintain a - // separate tower of macro scopes, with ids. Then, for each item in the - // module, we need to store it's macro scope. let def = Either::B(MacroDef { id: macro_id }); // In Rust, `#[macro_export]` macros are unconditionally visible at the @@ -162,13 +146,35 @@ where self.def_map.exported_macros.insert(name.clone(), macro_id); } self.update(module_id, None, &[(name.clone(), def)]); - self.global_macro_scope.insert(name, macro_id); + self.define_textual_macro(module_id, name.clone(), macro_id); + } + + /// Define a macro in current textual scope. + /// + /// We use a map `textual_macros` to store all textual macros visable per module. + /// It will clone all macros from parent textual scope, whose definition is prior to + /// the definition of current module. + /// And also, `macro_use` on a module will import all textual macros visable inside to + /// current textual scope, with possible shadowing. + /// + /// In a single module, the order of definition/usage of textual scoped macros matters. + /// But we ignore it here to make it easy to implement. + fn define_textual_macro(&mut self, module_id: CrateModuleId, name: Name, macro_id: MacroDefId) { + // Always shadowing + self.def_map.modules[module_id] + .scope + .textual_macros + .insert(name, MacroDef { id: macro_id }); } /// Import macros from `#[macro_use] extern crate`. /// /// They are non-scoped, and will only be inserted into mutable `global_macro_scope`. - fn import_macros_from_extern_crate(&mut self, import: &raw::ImportData) { + fn import_macros_from_extern_crate( + &mut self, + current_module_id: CrateModuleId, + import: &raw::ImportData, + ) { log::debug!( "importing macros from extern crate: {:?} ({:?})", import, @@ -184,14 +190,14 @@ where if let Some(ModuleDef::Module(m)) = res.take_types() { tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use); - self.import_all_macros_exported(m); + self.import_all_macros_exported(current_module_id, m); } } - fn import_all_macros_exported(&mut self, module: Module) { + fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, module: Module) { let item_map = self.db.crate_def_map(module.krate); for (name, ¯o_id) in &item_map.exported_macros { - self.global_macro_scope.insert(name.clone(), macro_id); + self.define_textual_macro(current_module_id, name.clone(), macro_id); } } @@ -528,7 +534,7 @@ where if let Some(prelude_module) = self.def_collector.def_map.prelude { if prelude_module.krate != self.def_collector.def_map.krate { tested_by!(prelude_is_macro_use); - self.def_collector.import_all_macros_exported(prelude_module); + self.def_collector.import_all_macros_exported(self.module_id, prelude_module); } } @@ -539,7 +545,7 @@ where if let raw::RawItem::Import(import_id) = *item { let import = self.raw_items[import_id].clone(); if import.is_extern_crate && import.is_macro_use { - self.def_collector.import_macros_from_extern_crate(&import); + self.def_collector.import_macros_from_extern_crate(self.module_id, &import); } } } @@ -561,10 +567,11 @@ where fn collect_module(&mut self, module: &raw::ModuleData) { match module { // inline module, just recurse - raw::ModuleData::Definition { name, items, ast_id, attr_path } => { + raw::ModuleData::Definition { name, items, ast_id, attr_path, is_macro_use } => { let module_id = self.push_child_module(name.clone(), ast_id.with_file_id(self.file_id), None); let parent_module = ParentModule { name, attr_path: attr_path.as_ref() }; + ModCollector { def_collector: &mut *self.def_collector, module_id, @@ -573,9 +580,12 @@ where parent_module: Some(parent_module), } .collect(&*items); + if *is_macro_use { + self.import_all_textual_macros(module_id); + } } // out of line module, resolve, parse and recurse - raw::ModuleData::Declaration { name, ast_id, attr_path } => { + raw::ModuleData::Declaration { name, ast_id, attr_path, is_macro_use } => { let ast_id = ast_id.with_file_id(self.file_id); let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); match resolve_submodule( @@ -596,7 +606,10 @@ where raw_items: &raw_items, parent_module: None, } - .collect(raw_items.items()) + .collect(raw_items.items()); + if *is_macro_use { + self.import_all_textual_macros(module_id); + } } Err(candidate) => self.def_collector.def_map.diagnostics.push( DefDiagnostic::UnresolvedModule { @@ -621,6 +634,7 @@ where modules[res].parent = Some(self.module_id); modules[res].declaration = Some(declaration); modules[res].definition = definition; + modules[res].scope.textual_macros = modules[self.module_id].scope.textual_macros.clone(); modules[self.module_id].children.insert(name.clone(), res); let resolution = Resolution { def: PerNs::types( @@ -674,12 +688,12 @@ where let ast_id = mac.ast_id.with_file_id(self.file_id); - // Case 2: try to expand macro_rules from this crate, triggering + // Case 2: try to resolve in textual scope and expand macro_rules, triggering // recursive item collection. - if let Some(macro_id) = - mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(&name)) - { - let def = *macro_id; + if let Some(macro_def) = mac.path.as_ident().and_then(|name| { + self.def_collector.def_map[self.module_id].scope.get_textual_macro(&name) + }) { + let def = macro_def.id; let macro_call_id = MacroCallLoc { def, ast_id }.id(self.def_collector.db); self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, def); @@ -689,6 +703,13 @@ where // Case 3: path to a macro from another crate, expand during name resolution self.def_collector.unexpanded_macros.push((self.module_id, ast_id, mac.path.clone())) } + + fn import_all_textual_macros(&mut self, module_id: CrateModuleId) { + let macros = self.def_collector.def_map[module_id].scope.textual_macros.clone(); + for (name, macro_) in macros { + self.def_collector.define_textual_macro(self.module_id, name.clone(), macro_.id); + } + } } fn is_macro_rules(path: &Path) -> bool { @@ -715,7 +736,6 @@ mod tests { glob_imports: FxHashMap::default(), unresolved_imports: Vec::new(), unexpanded_macros: Vec::new(), - global_macro_scope: FxHashMap::default(), macro_stack_monitor: monitor, }; collector.collect(); diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index 7963736e0..c646d3d00 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs @@ -134,12 +134,14 @@ pub(super) enum ModuleData { name: Name, ast_id: FileAstId, attr_path: Option, + is_macro_use: bool, }, Definition { name: Name, ast_id: FileAstId, items: Vec, attr_path: Option, + is_macro_use: bool, }, } @@ -267,10 +269,15 @@ impl RawItemsCollector { }; let ast_id = self.source_ast_id_map.ast_id(&module); + let is_macro_use = module.has_atom_attr("macro_use"); if module.has_semi() { let attr_path = extract_mod_path_attribute(&module); - let item = - self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id, attr_path }); + let item = self.raw_items.modules.alloc(ModuleData::Declaration { + name, + ast_id, + attr_path, + is_macro_use, + }); self.push_item(current_module, RawItem::Module(item)); return; } @@ -282,6 +289,7 @@ impl RawItemsCollector { ast_id, items: Vec::new(), attr_path, + is_macro_use, }); self.process_module(Some(item), item_list); self.push_item(current_module, RawItem::Module(item)); diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs index c62152d26..8f0db95f2 100644 --- a/crates/ra_hir/src/nameres/tests/macros.rs +++ b/crates/ra_hir/src/nameres/tests/macros.rs @@ -277,3 +277,94 @@ fn prelude_cycle() { ⋮crate::foo "###); } + +#[test] +fn plain_macros_are_textual_scoped_between_modules() { + let map = def_map( + r#" + //- /main.rs + mod m1; + bar!(NotFoundNotMacroUse); + + mod m2 { + foo!(NotFoundBeforeInside2); + } + + macro_rules! foo { + ($x:ident) => { struct $x; } + } + foo!(Ok); + + mod m3; + foo!(OkShadowStop); + bar!(NotFoundMacroUseStop); + + #[macro_use] + mod m5 { + #[macro_use] + mod m6 { + macro_rules! foo { + ($x:ident) => { fn $x() {} } + } + } + } + foo!(ok_double_macro_use_shadow); + + //- /m1.rs + foo!(NotFoundBeforeInside1); + macro_rules! bar { + ($x:ident) => { struct $x; } + } + + //- /m3/mod.rs + foo!(OkAfterInside); + macro_rules! foo { + ($x:ident) => { fn $x() {} } + } + foo!(ok_shadow); + + #[macro_use] + mod m4; + bar!(OkMacroUse); + + //- /m3/m4.rs + foo!(ok_shadow_deep); + macro_rules! bar { + ($x:ident) => { struct $x; } + } + "#, + ); + assert_snapshot!(map, @r###" + ⋮crate + ⋮Ok: t v + ⋮OkShadowStop: t v + ⋮foo: m + ⋮m1: t + ⋮m2: t + ⋮m3: t + ⋮m5: t + ⋮ok_double_macro_use_shadow: v + ⋮ + ⋮crate::m1 + ⋮bar: m + ⋮ + ⋮crate::m5 + ⋮m6: t + ⋮ + ⋮crate::m5::m6 + ⋮foo: m + ⋮ + ⋮crate::m2 + ⋮ + ⋮crate::m3 + ⋮OkAfterInside: t v + ⋮OkMacroUse: t v + ⋮foo: m + ⋮m4: t + ⋮ok_shadow: v + ⋮ + ⋮crate::m3::m4 + ⋮bar: m + ⋮ok_shadow_deep: v + "###); +} -- cgit v1.2.3 From 26b092bd3b431559d7aafbf42882f978c0bb3dab Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Sat, 7 Sep 2019 02:44:26 +0800 Subject: Resolve textual scoped macros inside item --- crates/ra_hir/src/nameres.rs | 7 ++++++- crates/ra_hir/src/nameres/collector.rs | 16 +++++++------- crates/ra_hir/src/nameres/tests/macros.rs | 16 +++++++++++++- crates/ra_hir/src/ty/tests.rs | 35 +++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 9 deletions(-) diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index e6bf0e90c..befbb2a9b 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -489,16 +489,21 @@ impl CrateDefMap { name: &Name, ) -> ItemOrMacro { // Resolve in: + // - textual scoped macros // - current module / scope // - extern prelude // - std prelude + let from_textual_mcro = self[module] + .scope + .get_textual_macro(name) + .map_or_else(|| Either::A(PerNs::none()), Either::B); let from_scope = self[module].scope.get_item_or_macro(name).unwrap_or_else(|| Either::A(PerNs::none())); let from_extern_prelude = self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); let from_prelude = self.resolve_in_prelude(db, name); - or(from_scope, or(Either::A(from_extern_prelude), from_prelude)) + or(from_textual_mcro, or(from_scope, or(Either::A(from_extern_prelude), from_prelude))) } fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index f897547e3..10c32ffa1 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -14,8 +14,8 @@ use crate::{ raw, CrateDefMap, CrateModuleId, ItemOrMacro, ModuleData, ModuleDef, PerNs, ReachedFixedPoint, Resolution, ResolveMode, }, - AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, Static, Struct, Trait, - TypeAlias, Union, + AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, PathKind, Static, + Struct, Trait, TypeAlias, Union, }; pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { @@ -156,9 +156,6 @@ where /// the definition of current module. /// And also, `macro_use` on a module will import all textual macros visable inside to /// current textual scope, with possible shadowing. - /// - /// In a single module, the order of definition/usage of textual scoped macros matters. - /// But we ignore it here to make it easy to implement. fn define_textual_macro(&mut self, module_id: CrateModuleId, name: Name, macro_id: MacroDefId) { // Always shadowing self.def_map.modules[module_id] @@ -700,8 +697,13 @@ where return; } - // Case 3: path to a macro from another crate, expand during name resolution - self.def_collector.unexpanded_macros.push((self.module_id, ast_id, mac.path.clone())) + // Case 3: resolve in module scope, expand during name resolution. + // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only. + let mut path = mac.path.clone(); + if path.is_ident() { + path.kind = PathKind::Self_; + } + self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path)); } fn import_all_textual_macros(&mut self, module_id: CrateModuleId) { diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs index 8f0db95f2..a894c6836 100644 --- a/crates/ra_hir/src/nameres/tests/macros.rs +++ b/crates/ra_hir/src/nameres/tests/macros.rs @@ -279,7 +279,7 @@ fn prelude_cycle() { } #[test] -fn plain_macros_are_textual_scoped_between_modules() { +fn plain_macros_are_textual_scoped() { let map = def_map( r#" //- /main.rs @@ -310,6 +310,15 @@ fn plain_macros_are_textual_scoped_between_modules() { } foo!(ok_double_macro_use_shadow); + baz!(NotFoundBefore); + #[macro_use] + mod m7 { + macro_rules! baz { + ($x:ident) => { struct $x; } + } + } + baz!(OkAfter); + //- /m1.rs foo!(NotFoundBeforeInside1); macro_rules! bar { @@ -337,14 +346,19 @@ fn plain_macros_are_textual_scoped_between_modules() { assert_snapshot!(map, @r###" ⋮crate ⋮Ok: t v + ⋮OkAfter: t v ⋮OkShadowStop: t v ⋮foo: m ⋮m1: t ⋮m2: t ⋮m3: t ⋮m5: t + ⋮m7: t ⋮ok_double_macro_use_shadow: v ⋮ + ⋮crate::m7 + ⋮baz: m + ⋮ ⋮crate::m1 ⋮bar: m ⋮ diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index c4bddde85..f2d5b115e 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -2803,6 +2803,41 @@ fn main() { ); } +#[test] +fn infer_textual_scoped_macros_expanded() { + assert_snapshot!( + infer(r#" +struct Foo(Vec); + +#[macro_use] +mod m { + macro_rules! foo { + ($($item:expr),*) => { + { + Foo(vec![$($item,)*]) + } + }; + } +} + +fn main() { + let x = foo!(1,2); + let y = crate::foo!(1,2); +} +"#), + @r###" + ![0; 17) '{Foo(v...,2,])}': Foo + ![1; 4) 'Foo': Foo({unknown}) -> Foo + ![1; 16) 'Foo(vec![1,2,])': Foo + ![5; 15) 'vec![1,2,]': {unknown} + [195; 251) '{ ...,2); }': () + [205; 206) 'x': Foo + [228; 229) 'y': {unknown} + [232; 248) 'crate:...!(1,2)': {unknown} + "### + ); +} + #[ignore] #[test] fn method_resolution_trait_before_autoref() { -- cgit v1.2.3 From c90256429bf41958ff6c7390dfd5fa25123eabb3 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Sat, 7 Sep 2019 22:46:44 +0800 Subject: Replace with immutable map to avoid heavy cloning --- Cargo.lock | 27 +++++++++++++++++++++++++++ crates/ra_hir/Cargo.toml | 1 + crates/ra_hir/src/nameres.rs | 7 +++++-- crates/ra_hir/src/nameres/collector.rs | 3 +++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f93f11a82..7f329c4db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -484,6 +484,16 @@ dependencies = [ "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "im" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sized-chunks 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "indexmap" version = "1.1.0" @@ -1006,6 +1016,7 @@ dependencies = [ "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)", "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git)", "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "im 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1550,6 +1561,14 @@ dependencies = [ "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sized-chunks" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "slab" version = "0.4.2" @@ -1684,6 +1703,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicase" version = "2.5.1" @@ -1893,6 +1917,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +"checksum im 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8db49f8bc08d5cc4e2bb0f7d25a6d1db2c79bc6f7d7c86c96c657eb3d214125f" "checksum indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4d6d89e0948bf10c08b9ecc8ac5b83f07f857ebe2c0cbe38de15b4e4f510356" "checksum indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c60da1c9abea75996b70a931bba6c750730399005b61ccd853cee50ef3d0d0c" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" @@ -1987,6 +2012,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" "checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" +"checksum sized-chunks 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f01db57d7ee89c8e053245deb77040a6cc8508311f381c88749c33d4b9b78785" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum smol_str 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "590700be3630457c56f8c73c0ea39881476ad7076cd84057d44f4f38f79914fb" @@ -2002,6 +2028,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index d9bed4dda..f955dc3e6 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml @@ -6,6 +6,7 @@ authors = ["rust-analyzer developers"] [dependencies] arrayvec = "0.4.10" +im = "13.0.0" log = "0.4.5" relative-path = "0.4.0" rustc-hash = "1.0" diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index befbb2a9b..7e5138d05 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -54,6 +54,7 @@ mod mod_resolution; #[cfg(test)] mod tests; +use std::hash::BuildHasherDefault; use std::sync::Arc; use once_cell::sync::Lazy; @@ -61,7 +62,7 @@ use ra_arena::{impl_arena_id, Arena, RawId}; use ra_db::{Edition, FileId}; use ra_prof::profile; use ra_syntax::ast; -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; use test_utils::tested_by; use crate::{ @@ -73,6 +74,8 @@ use crate::{ AstId, BuiltinType, Crate, HirFileId, MacroDef, Module, ModuleDef, Name, Path, PathKind, Trait, }; +pub(crate) type ImmFxHashMap = im::HashMap>; + pub(crate) use self::raw::{ImportSourceMap, RawItems}; pub use self::{ @@ -139,7 +142,7 @@ pub(crate) struct ModuleData { pub struct ModuleScope { items: FxHashMap, macros: FxHashMap, - textual_macros: FxHashMap, + textual_macros: ImmFxHashMap, } static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index 10c32ffa1..3803c7185 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -631,6 +631,7 @@ where modules[res].parent = Some(self.module_id); modules[res].declaration = Some(declaration); modules[res].definition = definition; + // Cloning immutable map is lazy and fast modules[res].scope.textual_macros = modules[self.module_id].scope.textual_macros.clone(); modules[self.module_id].children.insert(name.clone(), res); let resolution = Resolution { @@ -707,6 +708,8 @@ where } fn import_all_textual_macros(&mut self, module_id: CrateModuleId) { + // `clone()` is needed here to avoid mutable borrow `self.def_collector` when first borrow is alive + // Cloning immutable map is lazy and fast let macros = self.def_collector.def_map[module_id].scope.textual_macros.clone(); for (name, macro_) in macros { self.def_collector.define_textual_macro(self.module_id, name.clone(), macro_.id); -- cgit v1.2.3 From f7f7c2aff80f0870f0d71bf70075e3b5bf68994f Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Sun, 8 Sep 2019 00:05:58 +0800 Subject: Revert "Replace with immutable map to avoid heavy cloning" This reverts commit 2c494eb803c88ef5d23607c3b156fce60c2b8076. See: https://github.com/rust-analyzer/rust-analyzer/pull/1784#issuecomment-529119924 --- Cargo.lock | 27 --------------------------- crates/ra_hir/Cargo.toml | 1 - crates/ra_hir/src/nameres.rs | 7 ++----- crates/ra_hir/src/nameres/collector.rs | 3 --- 4 files changed, 2 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7f329c4db..f93f11a82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -484,16 +484,6 @@ dependencies = [ "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "im" -version = "13.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sized-chunks 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "indexmap" version = "1.1.0" @@ -1016,7 +1006,6 @@ dependencies = [ "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)", "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git)", "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "im 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1561,14 +1550,6 @@ dependencies = [ "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "sized-chunks" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "slab" version = "0.4.2" @@ -1703,11 +1684,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "typenum" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicase" version = "2.5.1" @@ -1917,7 +1893,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum im 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8db49f8bc08d5cc4e2bb0f7d25a6d1db2c79bc6f7d7c86c96c657eb3d214125f" "checksum indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4d6d89e0948bf10c08b9ecc8ac5b83f07f857ebe2c0cbe38de15b4e4f510356" "checksum indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c60da1c9abea75996b70a931bba6c750730399005b61ccd853cee50ef3d0d0c" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" @@ -2012,7 +1987,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" "checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" -"checksum sized-chunks 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f01db57d7ee89c8e053245deb77040a6cc8508311f381c88749c33d4b9b78785" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum smol_str 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "590700be3630457c56f8c73c0ea39881476ad7076cd84057d44f4f38f79914fb" @@ -2028,7 +2002,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index f955dc3e6..d9bed4dda 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml @@ -6,7 +6,6 @@ authors = ["rust-analyzer developers"] [dependencies] arrayvec = "0.4.10" -im = "13.0.0" log = "0.4.5" relative-path = "0.4.0" rustc-hash = "1.0" diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 7e5138d05..befbb2a9b 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -54,7 +54,6 @@ mod mod_resolution; #[cfg(test)] mod tests; -use std::hash::BuildHasherDefault; use std::sync::Arc; use once_cell::sync::Lazy; @@ -62,7 +61,7 @@ use ra_arena::{impl_arena_id, Arena, RawId}; use ra_db::{Edition, FileId}; use ra_prof::profile; use ra_syntax::ast; -use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; +use rustc_hash::{FxHashMap, FxHashSet}; use test_utils::tested_by; use crate::{ @@ -74,8 +73,6 @@ use crate::{ AstId, BuiltinType, Crate, HirFileId, MacroDef, Module, ModuleDef, Name, Path, PathKind, Trait, }; -pub(crate) type ImmFxHashMap = im::HashMap>; - pub(crate) use self::raw::{ImportSourceMap, RawItems}; pub use self::{ @@ -142,7 +139,7 @@ pub(crate) struct ModuleData { pub struct ModuleScope { items: FxHashMap, macros: FxHashMap, - textual_macros: ImmFxHashMap, + textual_macros: FxHashMap, } static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index 3803c7185..10c32ffa1 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -631,7 +631,6 @@ where modules[res].parent = Some(self.module_id); modules[res].declaration = Some(declaration); modules[res].definition = definition; - // Cloning immutable map is lazy and fast modules[res].scope.textual_macros = modules[self.module_id].scope.textual_macros.clone(); modules[self.module_id].children.insert(name.clone(), res); let resolution = Resolution { @@ -708,8 +707,6 @@ where } fn import_all_textual_macros(&mut self, module_id: CrateModuleId) { - // `clone()` is needed here to avoid mutable borrow `self.def_collector` when first borrow is alive - // Cloning immutable map is lazy and fast let macros = self.def_collector.def_map[module_id].scope.textual_macros.clone(); for (name, macro_) in macros { self.def_collector.define_textual_macro(self.module_id, name.clone(), macro_.id); -- cgit v1.2.3 From 92c07803cc0ce1d2008cc912f006d1cd66ff3f4a Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Sun, 8 Sep 2019 00:37:54 +0800 Subject: Rename `textual_macro` -> `legacy_macro` Add comments --- crates/ra_hir/src/nameres.rs | 27 ++++++++++++++++------ crates/ra_hir/src/nameres/collector.rs | 37 ++++++++++++++----------------- crates/ra_hir/src/nameres/tests/macros.rs | 2 +- crates/ra_hir/src/ty/tests.rs | 2 +- 4 files changed, 39 insertions(+), 29 deletions(-) diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index befbb2a9b..74546e5e2 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -138,8 +138,21 @@ pub(crate) struct ModuleData { #[derive(Debug, Default, PartialEq, Eq, Clone)] pub struct ModuleScope { items: FxHashMap, + /// Macros in current module scoped + /// + /// This scope works exactly the same way that item scoping does. + /// Macro invocation with quantified path will search in it. + /// See details below. macros: FxHashMap, - textual_macros: FxHashMap, + /// Macros visable in current module in legacy textual scope + /// + /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. + /// If it yields no result, then it turns to module scoped `macros`. + /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped, + /// and only normal scoped `macros` will be searched in. + /// + /// Note that this automatically inherit macros defined textually before the definition of module itself. + legacy_macros: FxHashMap, } static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { @@ -173,8 +186,8 @@ impl ModuleScope { _ => None, } } - fn get_textual_macro(&self, name: &Name) -> Option { - self.textual_macros.get(name).copied() + fn get_legacy_macro(&self, name: &Name) -> Option { + self.legacy_macros.get(name).copied() } } @@ -489,13 +502,13 @@ impl CrateDefMap { name: &Name, ) -> ItemOrMacro { // Resolve in: - // - textual scoped macros + // - legacy scope // - current module / scope // - extern prelude // - std prelude - let from_textual_mcro = self[module] + let from_legacy_macro = self[module] .scope - .get_textual_macro(name) + .get_legacy_macro(name) .map_or_else(|| Either::A(PerNs::none()), Either::B); let from_scope = self[module].scope.get_item_or_macro(name).unwrap_or_else(|| Either::A(PerNs::none())); @@ -503,7 +516,7 @@ impl CrateDefMap { self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); let from_prelude = self.resolve_in_prelude(db, name); - or(from_textual_mcro, or(from_scope, or(Either::A(from_extern_prelude), from_prelude))) + or(from_legacy_macro, or(from_scope, or(Either::A(from_extern_prelude), from_prelude))) } fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index 10c32ffa1..09cda7656 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -146,22 +146,19 @@ where self.def_map.exported_macros.insert(name.clone(), macro_id); } self.update(module_id, None, &[(name.clone(), def)]); - self.define_textual_macro(module_id, name.clone(), macro_id); + self.define_legacy_macro(module_id, name.clone(), macro_id); } - /// Define a macro in current textual scope. + /// Define a legacy textual scoped macro in module /// - /// We use a map `textual_macros` to store all textual macros visable per module. - /// It will clone all macros from parent textual scope, whose definition is prior to + /// We use a map `legacy_macros` to store all legacy textual scoped macros visable per module. + /// It will clone all macros from parent legacy scope, whose definition is prior to /// the definition of current module. - /// And also, `macro_use` on a module will import all textual macros visable inside to - /// current textual scope, with possible shadowing. - fn define_textual_macro(&mut self, module_id: CrateModuleId, name: Name, macro_id: MacroDefId) { + /// And also, `macro_use` on a module will import all legacy macros visable inside to + /// current legacy scope, with possible shadowing. + fn define_legacy_macro(&mut self, module_id: CrateModuleId, name: Name, macro_id: MacroDefId) { // Always shadowing - self.def_map.modules[module_id] - .scope - .textual_macros - .insert(name, MacroDef { id: macro_id }); + self.def_map.modules[module_id].scope.legacy_macros.insert(name, MacroDef { id: macro_id }); } /// Import macros from `#[macro_use] extern crate`. @@ -194,7 +191,7 @@ where fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, module: Module) { let item_map = self.db.crate_def_map(module.krate); for (name, ¯o_id) in &item_map.exported_macros { - self.define_textual_macro(current_module_id, name.clone(), macro_id); + self.define_legacy_macro(current_module_id, name.clone(), macro_id); } } @@ -578,7 +575,7 @@ where } .collect(&*items); if *is_macro_use { - self.import_all_textual_macros(module_id); + self.import_all_legacy_macros(module_id); } } // out of line module, resolve, parse and recurse @@ -605,7 +602,7 @@ where } .collect(raw_items.items()); if *is_macro_use { - self.import_all_textual_macros(module_id); + self.import_all_legacy_macros(module_id); } } Err(candidate) => self.def_collector.def_map.diagnostics.push( @@ -631,7 +628,7 @@ where modules[res].parent = Some(self.module_id); modules[res].declaration = Some(declaration); modules[res].definition = definition; - modules[res].scope.textual_macros = modules[self.module_id].scope.textual_macros.clone(); + modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone(); modules[self.module_id].children.insert(name.clone(), res); let resolution = Resolution { def: PerNs::types( @@ -685,10 +682,10 @@ where let ast_id = mac.ast_id.with_file_id(self.file_id); - // Case 2: try to resolve in textual scope and expand macro_rules, triggering + // Case 2: try to resolve in legacy scope and expand macro_rules, triggering // recursive item collection. if let Some(macro_def) = mac.path.as_ident().and_then(|name| { - self.def_collector.def_map[self.module_id].scope.get_textual_macro(&name) + self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) }) { let def = macro_def.id; let macro_call_id = MacroCallLoc { def, ast_id }.id(self.def_collector.db); @@ -706,10 +703,10 @@ where self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path)); } - fn import_all_textual_macros(&mut self, module_id: CrateModuleId) { - let macros = self.def_collector.def_map[module_id].scope.textual_macros.clone(); + fn import_all_legacy_macros(&mut self, module_id: CrateModuleId) { + let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone(); for (name, macro_) in macros { - self.def_collector.define_textual_macro(self.module_id, name.clone(), macro_.id); + self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_.id); } } } diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs index a894c6836..21fab53e9 100644 --- a/crates/ra_hir/src/nameres/tests/macros.rs +++ b/crates/ra_hir/src/nameres/tests/macros.rs @@ -279,7 +279,7 @@ fn prelude_cycle() { } #[test] -fn plain_macros_are_textual_scoped() { +fn plain_macros_are_legacy_textual_scoped() { let map = def_map( r#" //- /main.rs diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index f2d5b115e..25716fe8c 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -2804,7 +2804,7 @@ fn main() { } #[test] -fn infer_textual_scoped_macros_expanded() { +fn infer_legacy_textual_scoped_macros_expanded() { assert_snapshot!( infer(r#" struct Foo(Vec); -- cgit v1.2.3 From 9ed21d65fb6727f6de4961dfa440981864451af6 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Sun, 8 Sep 2019 03:40:04 +0800 Subject: Fix test --- crates/ra_hir/src/nameres/tests/macros.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs index 21fab53e9..ebc4d6890 100644 --- a/crates/ra_hir/src/nameres/tests/macros.rs +++ b/crates/ra_hir/src/nameres/tests/macros.rs @@ -268,13 +268,10 @@ fn prelude_cycle() { ); assert_snapshot!(map, @r###" ⋮crate - ⋮foo: t ⋮prelude: t ⋮ ⋮crate::prelude ⋮declare_mod: m - ⋮ - ⋮crate::foo "###); } -- cgit v1.2.3