Auto merge of #17419 - ishanjain28:filter_builtin_macro_expansion, r=Veykril

Filter builtin macro expansion

This PR adds a filter on the types of built in macros that are allowed to be expanded.

Currently, This list of allowed macros contains, `stringify, cfg, core_panic, std_panic, concat, concat_bytes, include, include_str, include_bytes, env` and `option_env`.

Fixes #14177
This commit is contained in:
bors 2024-06-20 08:39:17 +00:00
commit 6738f81b12
2 changed files with 75 additions and 5 deletions

View file

@ -19,8 +19,12 @@ use hir_def::{
AsMacroCall, DefWithBodyId, FunctionId, MacroId, TraitId, VariantId, AsMacroCall, DefWithBodyId, FunctionId, MacroId, TraitId, VariantId,
}; };
use hir_expand::{ use hir_expand::{
attrs::collect_attrs, db::ExpandDatabase, files::InRealFile, name::AsName, InMacroFile, attrs::collect_attrs,
MacroCallId, MacroFileId, MacroFileIdExt, builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
db::ExpandDatabase,
files::InRealFile,
name::AsName,
InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt,
}; };
use itertools::Itertools; use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
@ -324,6 +328,48 @@ impl<'db> SemanticsImpl<'db> {
Some(node) Some(node)
} }
/// Expands the macro if it isn't one of the built-in ones that expand to custom syntax or dummy
/// expansions.
pub fn expand_allowed_builtins(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
let sa = self.analyze_no_infer(macro_call.syntax())?;
let macro_call = InFile::new(sa.file_id, macro_call);
let file_id = if let Some(call) =
<ast::MacroCall as crate::semantics::ToDef>::to_def(self, macro_call)
{
call.as_macro_file()
} else {
sa.expand(self.db, macro_call)?
};
let macro_call = self.db.lookup_intern_macro_call(file_id.macro_call_id);
let skip = matches!(
macro_call.def.kind,
hir_expand::MacroDefKind::BuiltIn(
_,
BuiltinFnLikeExpander::Column
| BuiltinFnLikeExpander::File
| BuiltinFnLikeExpander::ModulePath
| BuiltinFnLikeExpander::Asm
| BuiltinFnLikeExpander::LlvmAsm
| BuiltinFnLikeExpander::GlobalAsm
| BuiltinFnLikeExpander::LogSyntax
| BuiltinFnLikeExpander::TraceMacros
| BuiltinFnLikeExpander::FormatArgs
| BuiltinFnLikeExpander::FormatArgsNl
| BuiltinFnLikeExpander::ConstFormatArgs,
) | hir_expand::MacroDefKind::BuiltInEager(_, EagerExpander::CompileError)
);
if skip {
// these macros expand to custom builtin syntax and/or dummy things, no point in
// showing these to the user
return None;
}
let node = self.parse_or_expand(file_id.into());
Some(node)
}
/// If `item` has an attribute macro attached to it, expands it. /// If `item` has an attribute macro attached to it, expands it.
pub fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> { pub fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> {
let src = self.wrap_node_infile(item.clone()); let src = self.wrap_node_infile(item.clone());

View file

@ -111,9 +111,10 @@ fn expand_macro_recur(
macro_call: &ast::Item, macro_call: &ast::Item,
) -> Option<SyntaxNode> { ) -> Option<SyntaxNode> {
let expanded = match macro_call { let expanded = match macro_call {
item @ ast::Item::MacroCall(macro_call) => { item @ ast::Item::MacroCall(macro_call) => sema
sema.expand_attr_macro(item).or_else(|| sema.expand(macro_call))?.clone_for_update() .expand_attr_macro(item)
} .or_else(|| sema.expand_allowed_builtins(macro_call))?
.clone_for_update(),
item => sema.expand_attr_macro(item)?.clone_for_update(), item => sema.expand_attr_macro(item)?.clone_for_update(),
}; };
expand(sema, expanded) expand(sema, expanded)
@ -228,6 +229,29 @@ mod tests {
expect.assert_eq(&actual); expect.assert_eq(&actual);
} }
#[test]
fn expand_allowed_builtin_macro() {
check(
r#"
//- minicore: concat
$0concat!("test", 10, 'b', true);"#,
expect![[r#"
concat!
"test10btrue""#]],
);
}
#[test]
fn do_not_expand_disallowed_macro() {
let (analysis, pos) = fixture::position(
r#"
//- minicore: asm
$0asm!("0x300, x0");"#,
);
let expansion = analysis.expand_macro(pos).unwrap();
assert!(expansion.is_none());
}
#[test] #[test]
fn macro_expand_as_keyword() { fn macro_expand_as_keyword() {
check( check(