Skip to content

Commit 40bf8bf

Browse files
committed
Auto merge of #16679 - Veykril:block-mod, r=Veykril
fix: Fix modules in blocks not resolving in ide layer Fixes #16511
2 parents 2251d06 + 91554e0 commit 40bf8bf

File tree

11 files changed

+183
-33
lines changed

11 files changed

+183
-33
lines changed

crates/base-db/src/input.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ impl CrateGraph {
570570
.arena
571571
.iter_mut()
572572
.take(m)
573-
.find_map(|(id, data)| merge((id, data), (topo, &crate_data)).then_some(id));
573+
.find_map(|(id, data)| merge((id, data), (topo, crate_data)).then_some(id));
574574

575575
let new_id =
576576
if let Some(res) = res { res } else { self.arena.alloc(crate_data.clone()) };

crates/hir-def/src/body/tests/block.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,40 @@ pub mod cov_mark {
298298
);
299299
}
300300

301+
#[test]
302+
fn macro_exported_in_block_mod() {
303+
check_at(
304+
r#"
305+
#[macro_export]
306+
macro_rules! foo {
307+
() => { pub struct FooWorks; };
308+
}
309+
macro_rules! bar {
310+
() => { pub struct BarWorks; };
311+
}
312+
fn main() {
313+
mod module {
314+
foo!();
315+
bar!();
316+
$0
317+
}
318+
}
319+
"#,
320+
expect![[r#"
321+
block scope
322+
module: t
323+
324+
block scope::module
325+
BarWorks: t v
326+
FooWorks: t v
327+
328+
crate
329+
foo: m
330+
main: v
331+
"#]],
332+
);
333+
}
334+
301335
#[test]
302336
fn macro_resolve_legacy() {
303337
check_at(

crates/hir-def/src/child_by_source.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,11 @@ impl ChildBySource for DefWithBodyId {
189189
VariantId::EnumVariantId(v).child_by_source_to(db, res, file_id)
190190
}
191191

192-
for (_, def_map) in body.blocks(db) {
192+
for (block, def_map) in body.blocks(db) {
193193
// All block expressions are merged into the same map, because they logically all add
194194
// inner items to the containing `DefWithBodyId`.
195195
def_map[DefMap::ROOT].scope.child_by_source_to(db, res, file_id);
196+
res[keys::BLOCK].insert(block.lookup(db).ast_id.to_node(db.upcast()), block);
196197
}
197198
}
198199
}

crates/hir-def/src/dyn_map/keys.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ use syntax::{ast, AstNode, AstPtr};
88

99
use crate::{
1010
dyn_map::{DynMap, Policy},
11-
ConstId, EnumId, EnumVariantId, ExternCrateId, FieldId, FunctionId, ImplId, LifetimeParamId,
12-
Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId,
13-
TypeOrConstParamId, UnionId, UseId,
11+
BlockId, ConstId, EnumId, EnumVariantId, ExternCrateId, FieldId, FunctionId, ImplId,
12+
LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId,
13+
TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId,
1414
};
1515

1616
pub type Key<K, V> = crate::dyn_map::Key<K, V, AstPtrPolicy<K, V>>;
1717

18+
pub const BLOCK: Key<ast::BlockExpr, BlockId> = Key::new();
1819
pub const FUNCTION: Key<ast::Fn, FunctionId> = Key::new();
1920
pub const CONST: Key<ast::Const, ConstId> = Key::new();
2021
pub const STATIC: Key<ast::Static, StaticId> = Key::new();

crates/hir-def/src/nameres.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,12 @@ impl DefMap {
469469
CrateRootModuleId { krate: self.krate }
470470
}
471471

472+
/// This is the same as [`Self::crate_root`] for crate def maps, but for block def maps, it
473+
/// returns the root block module.
474+
pub fn root_module_id(&self) -> ModuleId {
475+
self.module_id(Self::ROOT)
476+
}
477+
472478
pub(crate) fn resolve_path(
473479
&self,
474480
db: &dyn DefDatabase,

crates/hir-def/src/resolver.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Name resolution façade.
2-
use std::{fmt, hash::BuildHasherDefault};
2+
use std::{fmt, hash::BuildHasherDefault, mem};
33

44
use base_db::CrateId;
55
use hir_expand::{
@@ -809,7 +809,7 @@ fn resolver_for_scope_(
809809
for scope in scope_chain.into_iter().rev() {
810810
if let Some(block) = scopes.block(scope) {
811811
let def_map = db.block_def_map(block);
812-
r = r.push_block_scope(def_map, DefMap::ROOT);
812+
r = r.push_block_scope(def_map);
813813
// FIXME: This adds as many module scopes as there are blocks, but resolving in each
814814
// already traverses all parents, so this is O(n²). I think we could only store the
815815
// innermost module scope instead?
@@ -835,8 +835,9 @@ impl Resolver {
835835
self.push_scope(Scope::ImplDefScope(impl_def))
836836
}
837837

838-
fn push_block_scope(self, def_map: Arc<DefMap>, module_id: LocalModuleId) -> Resolver {
839-
self.push_scope(Scope::BlockScope(ModuleItemMap { def_map, module_id }))
838+
fn push_block_scope(self, def_map: Arc<DefMap>) -> Resolver {
839+
debug_assert!(def_map.block_id().is_some());
840+
self.push_scope(Scope::BlockScope(ModuleItemMap { def_map, module_id: DefMap::ROOT }))
840841
}
841842

842843
fn push_expr_scope(
@@ -986,19 +987,27 @@ pub trait HasResolver: Copy {
986987
impl HasResolver for ModuleId {
987988
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
988989
let mut def_map = self.def_map(db);
989-
let mut modules: SmallVec<[_; 1]> = smallvec![];
990990
let mut module_id = self.local_id;
991+
let mut modules: SmallVec<[_; 1]> = smallvec![];
992+
993+
if !self.is_block_module() {
994+
return Resolver { scopes: vec![], module_scope: ModuleItemMap { def_map, module_id } };
995+
}
996+
991997
while let Some(parent) = def_map.parent() {
992-
modules.push((def_map, module_id));
993-
def_map = parent.def_map(db);
994-
module_id = parent.local_id;
998+
let block_def_map = mem::replace(&mut def_map, parent.def_map(db));
999+
modules.push(block_def_map);
1000+
if !parent.is_block_module() {
1001+
module_id = parent.local_id;
1002+
break;
1003+
}
9951004
}
9961005
let mut resolver = Resolver {
9971006
scopes: Vec::with_capacity(modules.len()),
9981007
module_scope: ModuleItemMap { def_map, module_id },
9991008
};
1000-
for (def_map, module) in modules.into_iter().rev() {
1001-
resolver = resolver.push_block_scope(def_map, module);
1009+
for def_map in modules.into_iter().rev() {
1010+
resolver = resolver.push_block_scope(def_map);
10021011
}
10031012
resolver
10041013
}

crates/hir/src/semantics/source_to_def.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,17 @@
8686
//! syntax nodes against this specific crate.
8787
8888
use base_db::FileId;
89+
use either::Either;
8990
use hir_def::{
9091
child_by_source::ChildBySource,
9192
dyn_map::{
9293
keys::{self, Key},
9394
DynMap,
9495
},
9596
hir::{BindingId, LabelId},
96-
AdtId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FieldId,
97-
FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId, StaticId,
98-
StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId, VariantId,
97+
AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId,
98+
FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId,
99+
StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId, VariantId,
99100
};
100101
use hir_expand::{attrs::AttrId, name::AsName, HirFileId, HirFileIdExt, MacroCallId};
101102
use rustc_hash::FxHashMap;
@@ -131,15 +132,19 @@ impl SourceToDefCtx<'_, '_> {
131132
mods
132133
}
133134

134-
pub(super) fn module_to_def(&self, src: InFile<ast::Module>) -> Option<ModuleId> {
135+
pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> {
135136
let _p = tracing::span!(tracing::Level::INFO, "module_to_def");
136137
let parent_declaration = src
137138
.syntax()
138139
.ancestors_with_macros_skip_attr_item(self.db.upcast())
139-
.find_map(|it| it.map(ast::Module::cast).transpose());
140+
.find_map(|it| it.map(Either::<ast::Module, ast::BlockExpr>::cast).transpose())
141+
.map(|it| it.transpose());
140142

141143
let parent_module = match parent_declaration {
142-
Some(parent_declaration) => self.module_to_def(parent_declaration),
144+
Some(Either::Right(parent_block)) => self
145+
.block_to_def(parent_block)
146+
.map(|block| self.db.block_def_map(block).root_module_id()),
147+
Some(Either::Left(parent_declaration)) => self.module_to_def(parent_declaration),
143148
None => {
144149
let file_id = src.file_id.original_file(self.db.upcast());
145150
self.file_to_def(file_id).first().copied()
@@ -197,6 +202,9 @@ impl SourceToDefCtx<'_, '_> {
197202
pub(super) fn tuple_field_to_def(&mut self, src: InFile<ast::TupleField>) -> Option<FieldId> {
198203
self.to_def(src, keys::TUPLE_FIELD)
199204
}
205+
pub(super) fn block_to_def(&mut self, src: InFile<ast::BlockExpr>) -> Option<BlockId> {
206+
self.to_def(src, keys::BLOCK)
207+
}
200208
pub(super) fn enum_variant_to_def(
201209
&mut self,
202210
src: InFile<ast::Variant>,

crates/ide/src/syntax_highlighting/highlight.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,11 @@ fn highlight_name(
342342

343343
fn calc_binding_hash(name: &hir::Name, shadow_count: u32) -> u64 {
344344
fn hash<T: std::hash::Hash + std::fmt::Debug>(x: T) -> u64 {
345-
use std::{collections::hash_map::DefaultHasher, hash::Hasher};
345+
use ide_db::FxHasher;
346346

347-
let mut hasher = DefaultHasher::new();
347+
use std::hash::Hasher;
348+
349+
let mut hasher = FxHasher::default();
348350
x.hash(&mut hasher);
349351
hasher.finish()
350352
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
2+
<style>
3+
body { margin: 0; }
4+
pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
5+
6+
.lifetime { color: #DFAF8F; font-style: italic; }
7+
.label { color: #DFAF8F; font-style: italic; }
8+
.comment { color: #7F9F7F; }
9+
.documentation { color: #629755; }
10+
.intra_doc_link { font-style: italic; }
11+
.injected { opacity: 0.65 ; }
12+
.struct, .enum { color: #7CB8BB; }
13+
.enum_variant { color: #BDE0F3; }
14+
.string_literal { color: #CC9393; }
15+
.field { color: #94BFF3; }
16+
.function { color: #93E0E3; }
17+
.function.unsafe { color: #BC8383; }
18+
.trait.unsafe { color: #BC8383; }
19+
.operator.unsafe { color: #BC8383; }
20+
.mutable.unsafe { color: #BC8383; text-decoration: underline; }
21+
.keyword.unsafe { color: #BC8383; font-weight: bold; }
22+
.macro.unsafe { color: #BC8383; }
23+
.parameter { color: #94BFF3; }
24+
.text { color: #DCDCCC; }
25+
.type { color: #7CB8BB; }
26+
.builtin_type { color: #8CD0D3; }
27+
.type_param { color: #DFAF8F; }
28+
.attribute { color: #94BFF3; }
29+
.numeric_literal { color: #BFEBBF; }
30+
.bool_literal { color: #BFE6EB; }
31+
.macro { color: #94BFF3; }
32+
.derive { color: #94BFF3; font-style: italic; }
33+
.module { color: #AFD8AF; }
34+
.value_param { color: #DCDCCC; }
35+
.variable { color: #DCDCCC; }
36+
.format_specifier { color: #CC696B; }
37+
.mutable { text-decoration: underline; }
38+
.escape_sequence { color: #94BFF3; }
39+
.keyword { color: #F0DFAF; font-weight: bold; }
40+
.control { font-style: italic; }
41+
.reference { font-style: italic; font-weight: bold; }
42+
43+
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
44+
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
45+
</style>
46+
<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">foo</span> <span class="brace">{</span>
47+
<span class="parenthesis">(</span><span class="punctuation">$</span>foo<span class="colon">:</span>ident<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
48+
<span class="keyword">mod</span> y <span class="brace">{</span>
49+
<span class="keyword">struct</span> <span class="punctuation">$</span>foo<span class="semicolon">;</span>
50+
<span class="brace">}</span>
51+
<span class="brace">}</span><span class="semicolon">;</span>
52+
<span class="brace">}</span>
53+
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
54+
<span class="macro">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro">Foo</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
55+
<span class="keyword">mod</span> <span class="module declaration">module</span> <span class="brace">{</span>
56+
<span class="comment">// FIXME: IDE layer has this unresolved</span>
57+
<span class="unresolved_reference">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">Bar</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
58+
<span class="keyword">fn</span> <span class="function declaration">func</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
59+
<span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span>
60+
<span class="keyword">struct</span> <span class="struct declaration">Innerest</span><span class="angle">&lt;</span><span class="keyword">const</span> <span class="const_param declaration">C</span><span class="colon">:</span> <span class="unresolved_reference">usize</span><span class="angle">&gt;</span> <span class="brace">{</span> <span class="field declaration">field</span><span class="colon">:</span> <span class="bracket">[</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">{</span><span class="const_param">C</span><span class="brace">}</span><span class="bracket">]</span> <span class="brace">}</span>
61+
<span class="brace">}</span>
62+
<span class="brace">}</span>
63+
<span class="brace">}</span>
64+
<span class="brace">}</span></code></pre>

crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@
4444
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
4545
</style>
4646
<pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
47-
<span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
48-
<span class="keyword">let</span> <span class="variable declaration" data-binding-hash="2705725358298919760" style="color: hsl(76,47%,83%);">x</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
49-
<span class="keyword">let</span> <span class="variable declaration" data-binding-hash="3365759661443752373" style="color: hsl(15,86%,51%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
47+
<span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="8384512769119783714" style="color: hsl(59,93%,58%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
48+
<span class="keyword">let</span> <span class="variable declaration" data-binding-hash="17360984456076382725" style="color: hsl(95,79%,86%);">x</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="8384512769119783714" style="color: hsl(59,93%,58%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
49+
<span class="keyword">let</span> <span class="variable declaration" data-binding-hash="17186414787327620935" style="color: hsl(196,64%,89%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="8384512769119783714" style="color: hsl(59,93%,58%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
5050

51-
<span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="794745962933817518" style="color: hsl(127,71%,87%);">x</span> <span class="operator">=</span> <span class="string_literal">"other color please!"</span><span class="semicolon">;</span>
52-
<span class="keyword">let</span> <span class="variable declaration" data-binding-hash="6717528807933952652" style="color: hsl(90,74%,79%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="794745962933817518" style="color: hsl(127,71%,87%);">x</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
51+
<span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="4786021388930833562" style="color: hsl(137,61%,87%);">x</span> <span class="operator">=</span> <span class="string_literal">"other color please!"</span><span class="semicolon">;</span>
52+
<span class="keyword">let</span> <span class="variable declaration" data-binding-hash="18017815841345165192" style="color: hsl(39,76%,89%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="4786021388930833562" style="color: hsl(137,61%,87%);">x</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
5353
<span class="brace">}</span>
5454

5555
<span class="keyword">fn</span> <span class="function declaration">bar</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
56-
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable reference" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
56+
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable reference" data-binding-hash="8384512769119783714" style="color: hsl(59,93%,58%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
5757
<span class="brace">}</span></code></pre>

crates/ide/src/syntax_highlighting/tests.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -993,10 +993,6 @@ pub struct Struct;
993993
}
994994

995995
#[test]
996-
#[cfg_attr(
997-
not(all(unix, target_pointer_width = "64")),
998-
ignore = "depends on `DefaultHasher` outputs"
999-
)]
1000996
fn test_rainbow_highlighting() {
1001997
check_highlighting(
1002998
r#"
@@ -1018,6 +1014,35 @@ fn bar() {
10181014
);
10191015
}
10201016

1017+
#[test]
1018+
fn test_block_mod_items() {
1019+
check_highlighting(
1020+
r#"
1021+
macro_rules! foo {
1022+
($foo:ident) => {
1023+
mod y {
1024+
struct $foo;
1025+
}
1026+
};
1027+
}
1028+
fn main() {
1029+
foo!(Foo);
1030+
mod module {
1031+
// FIXME: IDE layer has this unresolved
1032+
foo!(Bar);
1033+
fn func() {
1034+
mod inner {
1035+
struct Innerest<const C: usize> { field: [(); {C}] }
1036+
}
1037+
}
1038+
}
1039+
}
1040+
"#,
1041+
expect_file!["./test_data/highlight_block_mod_items.html"],
1042+
false,
1043+
);
1044+
}
1045+
10211046
#[test]
10221047
fn test_ranges() {
10231048
let (analysis, file_id) = fixture::file(

0 commit comments

Comments
 (0)