Use dyn cache for Semantics macro resolution

This commit is contained in:
Lukas Wirth 2024-06-04 15:51:01 +02:00
parent 7d40763c88
commit 9349045e09
11 changed files with 44 additions and 41 deletions

View file

@ -2755,6 +2755,12 @@ impl Macro {
} }
} }
pub fn is_asm_or_global_asm(&self, db: &dyn HirDatabase) -> bool {
matches!(self.id, MacroId::Macro2Id(it) if {
matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm())
})
}
pub fn is_attr(&self, db: &dyn HirDatabase) -> bool { pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
matches!(self.kind(db), MacroKind::Attr) matches!(self.kind(db), MacroKind::Attr)
} }

View file

@ -1317,9 +1317,15 @@ impl<'db> SemanticsImpl<'db> {
} }
pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<Macro> { pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<Macro> {
let sa = self.analyze(macro_call.syntax())?;
let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call); let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
sa.resolve_macro_call(self.db, macro_call) self.with_ctx(|ctx| {
ctx.macro_call_to_macro_call(macro_call)
.and_then(|call| macro_call_to_macro_id(ctx, call))
.map(Into::into)
})
.or_else(|| {
self.analyze(macro_call.value.syntax())?.resolve_macro_call(self.db, macro_call)
})
} }
pub fn is_proc_macro_call(&self, macro_call: &ast::MacroCall) -> bool { pub fn is_proc_macro_call(&self, macro_call: &ast::MacroCall) -> bool {
@ -1339,12 +1345,17 @@ impl<'db> SemanticsImpl<'db> {
} }
pub fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool { pub fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool {
let sa = match self.analyze(macro_call.syntax()) { let Some(mac) = self.resolve_macro_call(macro_call) else { return false };
Some(it) => it, if mac.is_asm_or_global_asm(self.db) {
None => return false, return true;
}; }
let Some(sa) = self.analyze(macro_call.syntax()) else { return false };
let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call); let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
sa.is_unsafe_macro_call(self.db, macro_call) match macro_call.map(|it| it.syntax().parent().and_then(ast::MacroExpr::cast)).transpose() {
Some(it) => sa.is_unsafe_macro_call_expr(self.db, it.as_ref()),
None => false,
}
} }
pub fn resolve_attr_macro_call(&self, item: &ast::Item) -> Option<Macro> { pub fn resolve_attr_macro_call(&self, item: &ast::Item) -> Option<Macro> {

View file

@ -842,32 +842,13 @@ impl SourceAnalyzer {
infer.variant_resolution_for_expr(expr_id) infer.variant_resolution_for_expr(expr_id)
} }
pub(crate) fn is_unsafe_macro_call( pub(crate) fn is_unsafe_macro_call_expr(
&self, &self,
db: &dyn HirDatabase, db: &dyn HirDatabase,
macro_call: InFile<&ast::MacroCall>, macro_expr: InFile<&ast::MacroExpr>,
) -> bool { ) -> bool {
// check for asm/global_asm
if let Some(mac) = self.resolve_macro_call(db, macro_call) {
let ex = match mac.id {
hir_def::MacroId::Macro2Id(it) => it.lookup(db.upcast()).expander,
hir_def::MacroId::MacroRulesId(it) => it.lookup(db.upcast()).expander,
_ => hir_def::MacroExpander::Declarative,
};
if matches!(ex, hir_def::MacroExpander::BuiltIn(ex) if ex.is_asm()) {
return true;
}
}
let macro_expr = match macro_call
.map(|it| it.syntax().parent().and_then(ast::MacroExpr::cast))
.transpose()
{
Some(it) => it,
None => return false,
};
if let (Some((def, body, sm)), Some(infer)) = (&self.def, &self.infer) { if let (Some((def, body, sm)), Some(infer)) = (&self.def, &self.infer) {
if let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr.as_ref()) { if let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr) {
let mut is_unsafe = false; let mut is_unsafe = false;
unsafe_expressions( unsafe_expressions(
db, db,

View file

@ -584,6 +584,9 @@ fn highlight_method_call(
if func.is_async(sema.db) { if func.is_async(sema.db) {
h |= HlMod::Async; h |= HlMod::Async;
} }
if func.is_const(sema.db) {
h |= HlMod::Const;
}
if func if func
.as_assoc_item(sema.db) .as_assoc_item(sema.db)
.and_then(|it| it.container_or_implemented_trait(sema.db)) .and_then(|it| it.container_or_implemented_trait(sema.db))

View file

@ -48,16 +48,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">foo</span> <span class="brace">{</span> <pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">foo</span> <span class="brace">{</span>
<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> <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>
<span class="keyword">mod</span> y <span class="brace">{</span> <span class="keyword">mod</span> y <span class="brace">{</span>
<span class="keyword">struct</span> <span class="punctuation">$</span>foo<span class="semicolon">;</span> <span class="keyword">pub</span> <span class="keyword">struct</span> <span class="punctuation">$</span>foo<span class="semicolon">;</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="brace">}</span><span class="semicolon">;</span> <span class="brace">}</span><span class="semicolon">;</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
<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> <span class="macro">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro public">Foo</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="keyword">mod</span> <span class="module declaration">module</span> <span class="brace">{</span> <span class="keyword">mod</span> <span class="module declaration">module</span> <span class="brace">{</span>
<span class="comment">// FIXME: IDE layer has this unresolved</span> <span class="macro">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro public">Bar</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<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> <span class="keyword">fn</span> <span class="function declaration">func</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="module">y</span><span class="operator">::</span><span class="struct public">Bar</span><span class="parenthesis">)</span> <span class="brace">{</span>
<span class="keyword">fn</span> <span class="function declaration">func</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
<span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span> <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span>
<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 const 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 const">C</span><span class="brace">}</span><span class="bracket">]</span> <span class="brace">}</span> <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 const 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 const">C</span><span class="brace">}</span><span class="bracket">]</span> <span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>

View file

@ -66,10 +66,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="operator macro">&</span><span class="keyword macro">raw</span> <span class="keyword macro">const</span> <span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon macro">;</span> <span class="operator macro">&</span><span class="keyword macro">raw</span> <span class="keyword macro">const</span> <span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon macro">;</span>
<span class="keyword macro">const</span> <span class="keyword macro">const</span>
<span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="parenthesis">(</span><span class="parenthesis">)</span><span class="operator">.</span><span class="method const consuming trait">assoc_const_method</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">trait</span> <span class="trait declaration">ConstTrait</span> <span class="brace">{</span> <span class="keyword">trait</span> <span class="trait declaration">ConstTrait</span> <span class="brace">{</span>
<span class="keyword const">const</span> <span class="constant associated const declaration static trait">ASSOC_CONST</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="keyword const">const</span> <span class="constant associated const declaration static trait">ASSOC_CONST</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="keyword const">const</span> <span class="keyword">fn</span> <span class="function associated const declaration static trait">assoc_const_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> <span class="keyword const">const</span> <span class="keyword">fn</span> <span class="function associated const declaration static trait">assoc_const_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="keyword const">const</span> <span class="keyword">fn</span> <span class="method associated const consuming declaration trait">assoc_const_method</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">impl</span> <span class="keyword const">const</span> <span class="trait">ConstTrait</span> <span class="keyword">for</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> <span class="keyword">impl</span> <span class="keyword const">const</span> <span class="trait">ConstTrait</span> <span class="keyword">for</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
<span class="keyword const">const</span> <span class="constant associated const declaration static trait">ASSOC_CONST</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="keyword const">const</span> <span class="constant associated const declaration static trait">ASSOC_CONST</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>

View file

@ -49,5 +49,5 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
<span class="keyword">let</span> <span class="variable declaration">foo</span> <span class="operator">=</span> <span class="enum_variant default_library library">Some</span><span class="parenthesis">(</span><span class="numeric_literal">92</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="keyword">let</span> <span class="variable declaration">foo</span> <span class="operator">=</span> <span class="enum_variant default_library library">Some</span><span class="parenthesis">(</span><span class="numeric_literal">92</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="keyword">let</span> <span class="variable declaration">nums</span> <span class="operator">=</span> <span class="module default_library library">iter</span><span class="operator">::</span><span class="function default_library library">repeat</span><span class="parenthesis">(</span><span class="variable">foo</span><span class="operator">.</span><span class="method default_library library">unwrap</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="keyword">let</span> <span class="variable declaration">nums</span> <span class="operator">=</span> <span class="module default_library library">iter</span><span class="operator">::</span><span class="function default_library library">repeat</span><span class="parenthesis">(</span><span class="variable">foo</span><span class="operator">.</span><span class="method const default_library library">unwrap</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="brace">}</span></code></pre> <span class="brace">}</span></code></pre>

View file

@ -218,7 +218,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="bool_literal">true</span> <span class="bool_literal">true</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword const">const</span> <span class="constant const declaration">USAGE_OF_BOOL</span><span class="colon">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="enum public">Bool</span><span class="operator">::</span><span class="enum_variant public">True</span><span class="operator">.</span><span class="method consuming public">to_primitive</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="keyword const">const</span> <span class="constant const declaration">USAGE_OF_BOOL</span><span class="colon">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="enum public">Bool</span><span class="operator">::</span><span class="enum_variant public">True</span><span class="operator">.</span><span class="method const consuming public">to_primitive</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="keyword">trait</span> <span class="trait declaration">Baz</span> <span class="brace">{</span> <span class="keyword">trait</span> <span class="trait declaration">Baz</span> <span class="brace">{</span>
<span class="keyword">type</span> <span class="type_alias associated declaration static trait">Qux</span><span class="semicolon">;</span> <span class="keyword">type</span> <span class="type_alias associated declaration static trait">Qux</span><span class="semicolon">;</span>

View file

@ -165,7 +165,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="macro">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="macro">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="keyword">let</span> <span class="variable declaration">i</span><span class="colon">:</span> <span class="builtin_type">u64</span> <span class="operator">=</span> <span class="numeric_literal">3</span><span class="semicolon">;</span> <span class="keyword">let</span> <span class="variable declaration">i</span><span class="colon">:</span> <span class="builtin_type">u64</span> <span class="operator">=</span> <span class="numeric_literal">3</span><span class="semicolon">;</span>
<span class="keyword">let</span> <span class="variable declaration">o</span><span class="colon">:</span> <span class="builtin_type">u64</span><span class="semicolon">;</span> <span class="keyword">let</span> <span class="variable declaration">o</span><span class="colon">:</span> <span class="builtin_type">u64</span><span class="semicolon">;</span>
<span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span> <span class="macro default_library library">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
<span class="string_literal macro">"mov </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro">, </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"mov </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro">, </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span>
<span class="string_literal macro">"add </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro">, 5"</span><span class="comma macro">,</span> <span class="string_literal macro">"add </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro">, 5"</span><span class="comma macro">,</span>
<span class="none macro">out</span><span class="parenthesis macro">(</span><span class="none macro">reg</span><span class="parenthesis macro">)</span> <span class="none macro">o</span><span class="comma macro">,</span> <span class="none macro">out</span><span class="parenthesis macro">(</span><span class="none macro">reg</span><span class="parenthesis macro">)</span> <span class="none macro">o</span><span class="comma macro">,</span>

View file

@ -657,10 +657,12 @@ const fn const_fn<const CONST_PARAM: ()>(const {}: const fn()) where (): const C
&raw const (); &raw const ();
const const
); );
().assoc_const_method();
} }
trait ConstTrait { trait ConstTrait {
const ASSOC_CONST: () = (); const ASSOC_CONST: () = ();
const fn assoc_const_fn() {} const fn assoc_const_fn() {}
const fn assoc_const_method(self) {}
} }
impl const ConstTrait for () { impl const ConstTrait for () {
const ASSOC_CONST: () = (); const ASSOC_CONST: () = ();
@ -1070,16 +1072,15 @@ fn test_block_mod_items() {
macro_rules! foo { macro_rules! foo {
($foo:ident) => { ($foo:ident) => {
mod y { mod y {
struct $foo; pub struct $foo;
} }
}; };
} }
fn main() { fn main() {
foo!(Foo); foo!(Foo);
mod module { mod module {
// FIXME: IDE layer has this unresolved
foo!(Bar); foo!(Bar);
fn func() { fn func(_: y::Bar) {
mod inner { mod inner {
struct Innerest<const C: usize> { field: [(); {C}] } struct Innerest<const C: usize> { field: [(); {C}] }
} }

View file

@ -160,7 +160,7 @@ fn integrated_completion_benchmark() {
analysis.completions(&config, position, None).unwrap(); analysis.completions(&config, position, None).unwrap();
} }
let _g = crate::tracing::hprof::init("*"); let _g = crate::tracing::hprof::init("*>10");
let completion_offset = { let completion_offset = {
let _it = stdx::timeit("change"); let _it = stdx::timeit("change");