Skip to content

Commit ee38991

Browse files
committed
Auto merge of rust-lang#18117 - ChayimFriedman2:issue-18089, r=Veykril
fix: Always cache macro expansions' root node in Semantics Previously some expansions were not cached, but were cached in the expansion cache, which caused panics when later queries tried to lookup the node from the expansion cache. Fixes rust-lang#18089.
2 parents 63cf6fe + 7ac6a72 commit ee38991

File tree

7 files changed

+166
-48
lines changed

7 files changed

+166
-48
lines changed

src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Builtin macros and attributes
22
#[macro_use]
3-
mod quote;
3+
pub mod quote;
44

55
mod attr_macro;
66
mod derive_macro;

src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub(crate) fn dollar_crate(span: Span) -> tt::Ident<Span> {
1818
// 2. #()* pattern repetition not supported now
1919
// * But we can do it manually, see `test_quote_derive_copy_hack`
2020
#[doc(hidden)]
21+
#[macro_export]
2122
macro_rules! quote_impl__ {
2223
($span:ident) => {
2324
Vec::<$crate::tt::TokenTree>::new()
@@ -27,8 +28,8 @@ macro_rules! quote_impl__ {
2728
{
2829
let children = $crate::builtin::quote::__quote!($span $($tt)*);
2930
$crate::tt::Subtree {
30-
delimiter: crate::tt::Delimiter {
31-
kind: crate::tt::DelimiterKind::$delim,
31+
delimiter: $crate::tt::Delimiter {
32+
kind: $crate::tt::DelimiterKind::$delim,
3233
open: $span,
3334
close: $span,
3435
},
@@ -40,9 +41,9 @@ macro_rules! quote_impl__ {
4041
( @PUNCT($span:ident) $first:literal ) => {
4142
{
4243
vec![
43-
crate::tt::Leaf::Punct(crate::tt::Punct {
44+
$crate::tt::Leaf::Punct($crate::tt::Punct {
4445
char: $first,
45-
spacing: crate::tt::Spacing::Alone,
46+
spacing: $crate::tt::Spacing::Alone,
4647
span: $span,
4748
}).into()
4849
]
@@ -52,14 +53,14 @@ macro_rules! quote_impl__ {
5253
( @PUNCT($span:ident) $first:literal, $sec:literal ) => {
5354
{
5455
vec![
55-
crate::tt::Leaf::Punct(crate::tt::Punct {
56+
$crate::tt::Leaf::Punct($crate::tt::Punct {
5657
char: $first,
57-
spacing: crate::tt::Spacing::Joint,
58+
spacing: $crate::tt::Spacing::Joint,
5859
span: $span,
5960
}).into(),
60-
crate::tt::Leaf::Punct(crate::tt::Punct {
61+
$crate::tt::Leaf::Punct($crate::tt::Punct {
6162
char: $sec,
62-
spacing: crate::tt::Spacing::Alone,
63+
spacing: $crate::tt::Spacing::Alone,
6364
span: $span,
6465
}).into()
6566
]
@@ -98,7 +99,7 @@ macro_rules! quote_impl__ {
9899
// Ident
99100
($span:ident $tt:ident ) => {
100101
vec![ {
101-
crate::tt::Leaf::Ident(crate::tt::Ident {
102+
$crate::tt::Leaf::Ident($crate::tt::Ident {
102103
sym: intern::Symbol::intern(stringify!($tt)),
103104
span: $span,
104105
is_raw: tt::IdentIsRaw::No,
@@ -109,6 +110,7 @@ macro_rules! quote_impl__ {
109110
// Puncts
110111
// FIXME: Not all puncts are handled
111112
($span:ident -> ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '-', '>')};
113+
($span:ident => ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '=', '>')};
112114
($span:ident & ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '&')};
113115
($span:ident , ) => {$crate::builtin::quote::__quote!(@PUNCT($span) ',')};
114116
($span:ident : ) => {$crate::builtin::quote::__quote!(@PUNCT($span) ':')};
@@ -118,6 +120,9 @@ macro_rules! quote_impl__ {
118120
($span:ident < ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '<')};
119121
($span:ident > ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '>')};
120122
($span:ident ! ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '!')};
123+
($span:ident # ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '#')};
124+
($span:ident $ ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '$')};
125+
($span:ident * ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '*')};
121126

122127
($span:ident $first:tt $($tail:tt)+ ) => {
123128
{
@@ -129,18 +134,19 @@ macro_rules! quote_impl__ {
129134
}
130135
};
131136
}
132-
pub(super) use quote_impl__ as __quote;
137+
pub use quote_impl__ as __quote;
133138

134139
/// FIXME:
135140
/// It probably should implement in proc-macro
136-
macro_rules! quote_impl {
141+
#[macro_export]
142+
macro_rules! quote {
137143
($span:ident=> $($tt:tt)* ) => {
138144
$crate::builtin::quote::IntoTt::to_subtree($crate::builtin::quote::__quote!($span $($tt)*), $span)
139145
}
140146
}
141-
pub(super) use quote_impl as quote;
147+
pub(super) use quote;
142148

143-
pub(crate) trait IntoTt {
149+
pub trait IntoTt {
144150
fn to_subtree(self, span: Span) -> crate::tt::Subtree;
145151
fn to_tokens(self) -> Vec<crate::tt::TokenTree>;
146152
}
@@ -168,7 +174,7 @@ impl IntoTt for crate::tt::Subtree {
168174
}
169175
}
170176

171-
pub(crate) trait ToTokenTree {
177+
pub trait ToTokenTree {
172178
fn to_token(self, span: Span) -> crate::tt::TokenTree;
173179
}
174180

src/tools/rust-analyzer/crates/hir/src/semantics.rs

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ impl<'db> SemanticsImpl<'db> {
449449
Some(
450450
calls
451451
.into_iter()
452-
.map(|call| macro_call_to_macro_id(ctx, call?).map(|id| Macro { id }))
452+
.map(|call| macro_call_to_macro_id(self, ctx, call?).map(|id| Macro { id }))
453453
.collect(),
454454
)
455455
})
@@ -892,16 +892,7 @@ impl<'db> SemanticsImpl<'db> {
892892
let InMacroFile { file_id, value: mapped_tokens } = self.with_ctx(|ctx| {
893893
Some(
894894
ctx.cache
895-
.expansion_info_cache
896-
.entry(macro_file)
897-
.or_insert_with(|| {
898-
let exp_info = macro_file.expansion_info(self.db.upcast());
899-
900-
let InMacroFile { file_id, value } = exp_info.expanded();
901-
self.cache(value, file_id.into());
902-
903-
exp_info
904-
})
895+
.get_or_insert_expansion(self, macro_file)
905896
.map_range_down(span)?
906897
.map(SmallVec::<[_; 2]>::from_iter),
907898
)
@@ -1187,11 +1178,7 @@ impl<'db> SemanticsImpl<'db> {
11871178
let macro_file = file_id.macro_file()?;
11881179

11891180
self.with_ctx(|ctx| {
1190-
let expansion_info = ctx
1191-
.cache
1192-
.expansion_info_cache
1193-
.entry(macro_file)
1194-
.or_insert_with(|| macro_file.expansion_info(self.db.upcast()));
1181+
let expansion_info = ctx.cache.get_or_insert_expansion(self, macro_file);
11951182
expansion_info.arg().map(|node| node?.parent()).transpose()
11961183
})
11971184
}
@@ -1407,7 +1394,7 @@ impl<'db> SemanticsImpl<'db> {
14071394
let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
14081395
self.with_ctx(|ctx| {
14091396
ctx.macro_call_to_macro_call(macro_call)
1410-
.and_then(|call| macro_call_to_macro_id(ctx, call))
1397+
.and_then(|call| macro_call_to_macro_id(self, ctx, call))
14111398
.map(Into::into)
14121399
})
14131400
.or_else(|| {
@@ -1449,7 +1436,7 @@ impl<'db> SemanticsImpl<'db> {
14491436
let item_in_file = self.wrap_node_infile(item.clone());
14501437
let id = self.with_ctx(|ctx| {
14511438
let macro_call_id = ctx.item_to_macro_call(item_in_file.as_ref())?;
1452-
macro_call_to_macro_id(ctx, macro_call_id)
1439+
macro_call_to_macro_id(self, ctx, macro_call_id)
14531440
})?;
14541441
Some(Macro { id })
14551442
}
@@ -1769,6 +1756,7 @@ impl<'db> SemanticsImpl<'db> {
17691756
}
17701757

17711758
fn macro_call_to_macro_id(
1759+
sema: &SemanticsImpl<'_>,
17721760
ctx: &mut SourceToDefCtx<'_, '_>,
17731761
macro_call_id: MacroCallId,
17741762
) -> Option<MacroId> {
@@ -1784,11 +1772,7 @@ fn macro_call_to_macro_id(
17841772
it.to_ptr(db).to_node(&db.parse(file_id).syntax_node())
17851773
}
17861774
HirFileIdRepr::MacroFile(macro_file) => {
1787-
let expansion_info = ctx
1788-
.cache
1789-
.expansion_info_cache
1790-
.entry(macro_file)
1791-
.or_insert_with(|| macro_file.expansion_info(ctx.db.upcast()));
1775+
let expansion_info = ctx.cache.get_or_insert_expansion(sema, macro_file);
17921776
it.to_ptr(db).to_node(&expansion_info.expanded().value)
17931777
}
17941778
};
@@ -1800,11 +1784,7 @@ fn macro_call_to_macro_id(
18001784
it.to_ptr(db).to_node(&db.parse(file_id).syntax_node())
18011785
}
18021786
HirFileIdRepr::MacroFile(macro_file) => {
1803-
let expansion_info = ctx
1804-
.cache
1805-
.expansion_info_cache
1806-
.entry(macro_file)
1807-
.or_insert_with(|| macro_file.expansion_info(ctx.db.upcast()));
1787+
let expansion_info = ctx.cache.get_or_insert_expansion(sema, macro_file);
18081788
it.to_ptr(db).to_node(&expansion_info.expanded().value)
18091789
}
18101790
};

src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ use hir_def::{
9999
VariantId,
100100
};
101101
use hir_expand::{
102-
attrs::AttrId, name::AsName, ExpansionInfo, HirFileId, HirFileIdExt, MacroCallId,
102+
attrs::AttrId, name::AsName, ExpansionInfo, HirFileId, HirFileIdExt, InMacroFile, MacroCallId,
103+
MacroFileIdExt,
103104
};
104105
use rustc_hash::FxHashMap;
105106
use smallvec::SmallVec;
@@ -110,15 +111,32 @@ use syntax::{
110111
AstNode, AstPtr, SyntaxNode,
111112
};
112113

113-
use crate::{db::HirDatabase, InFile, InlineAsmOperand};
114+
use crate::{db::HirDatabase, InFile, InlineAsmOperand, SemanticsImpl};
114115

115116
#[derive(Default)]
116117
pub(super) struct SourceToDefCache {
117118
pub(super) dynmap_cache: FxHashMap<(ChildContainer, HirFileId), DynMap>,
118-
pub(super) expansion_info_cache: FxHashMap<MacroFileId, ExpansionInfo>,
119+
expansion_info_cache: FxHashMap<MacroFileId, ExpansionInfo>,
119120
pub(super) file_to_def_cache: FxHashMap<FileId, SmallVec<[ModuleId; 1]>>,
120121
}
121122

123+
impl SourceToDefCache {
124+
pub(super) fn get_or_insert_expansion(
125+
&mut self,
126+
sema: &SemanticsImpl<'_>,
127+
macro_file: MacroFileId,
128+
) -> &ExpansionInfo {
129+
self.expansion_info_cache.entry(macro_file).or_insert_with(|| {
130+
let exp_info = macro_file.expansion_info(sema.db.upcast());
131+
132+
let InMacroFile { file_id, value } = exp_info.expanded();
133+
sema.cache(value, file_id.into());
134+
135+
exp_info
136+
})
137+
}
138+
}
139+
122140
pub(super) struct SourceToDefCtx<'db, 'cache> {
123141
pub(super) db: &'db dyn HirDatabase,
124142
pub(super) cache: &'cache mut SourceToDefCache,
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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+
.proc_macro { color: #94BFF3; text-decoration: underline; }
33+
.derive { color: #94BFF3; font-style: italic; }
34+
.module { color: #AFD8AF; }
35+
.value_param { color: #DCDCCC; }
36+
.variable { color: #DCDCCC; }
37+
.format_specifier { color: #CC696B; }
38+
.mutable { text-decoration: underline; }
39+
.escape_sequence { color: #94BFF3; }
40+
.keyword { color: #F0DFAF; font-weight: bold; }
41+
.control { font-style: italic; }
42+
.reference { font-style: italic; font-weight: bold; }
43+
.const { font-weight: bolder; }
44+
45+
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
46+
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
47+
</style>
48+
<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>
49+
<span class="macro">template</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">template</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
50+
<span class="brace">}</span>
51+
52+
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="module attribute crate_root library">proc_macros</span><span class="operator attribute">::</span><span class="attribute attribute library">issue_18089</span><span class="attribute_bracket attribute">]</span>
53+
<span class="keyword">fn</span> <span class="function declaration">template</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span></code></pre>

src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,3 +1358,20 @@ pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! {
13581358
false,
13591359
);
13601360
}
1361+
1362+
#[test]
1363+
fn issue_18089() {
1364+
check_highlighting(
1365+
r#"
1366+
//- proc_macros: issue_18089
1367+
fn main() {
1368+
template!(template);
1369+
}
1370+
1371+
#[proc_macros::issue_18089]
1372+
fn template() {}
1373+
"#,
1374+
expect_file!["./test_data/highlight_issue_18089.html"],
1375+
false,
1376+
);
1377+
}

0 commit comments

Comments
 (0)