Implement dummy expansions for builtin attributes

This commit is contained in:
Lukas Wirth 2021-06-09 18:02:31 +02:00
parent 5f592f4f58
commit ae8d74ab2c
10 changed files with 176 additions and 11 deletions

View File

@ -1344,6 +1344,7 @@ impl MacroDef {
MacroDefKind::Declarative(_) => MacroKind::Declarative,
MacroDefKind::BuiltIn(_, _) | MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn,
MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive,
MacroDefKind::BuiltInAttr(_, _) => MacroKind::Attr,
MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::CustomDerive, _) => {
MacroKind::Derive
}

View File

@ -9,6 +9,7 @@ use base_db::{CrateId, Edition, FileId, ProcMacroId};
use cfg::{CfgExpr, CfgOptions};
use hir_expand::{
ast_id_map::FileAstId,
builtin_attr::find_builtin_attr,
builtin_derive::find_builtin_derive,
builtin_macro::find_builtin_macro,
name::{name, AsName, Name},
@ -1836,7 +1837,8 @@ impl ModCollector<'_, '_> {
let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
if attrs.by_key("rustc_builtin_macro").exists() {
let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
.or_else(|| find_builtin_derive(&mac.name, krate, ast_id));
.or_else(|| find_builtin_derive(&mac.name, krate, ast_id))
.or_else(|| find_builtin_attr(&mac.name, krate, ast_id));
match macro_id {
Some(macro_id) => {

View File

@ -0,0 +1,115 @@
//! Builtin derives.
use syntax::ast;
use crate::{db::AstDatabase, name, AstId, CrateId, MacroCallId, MacroDefId, MacroDefKind};
macro_rules! register_builtin {
( $(($name:ident, $variant:ident) => $expand:ident),* ) => {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BuiltinAttrExpander {
$($variant),*
}
impl BuiltinAttrExpander {
pub fn expand(
&self,
db: &dyn AstDatabase,
id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
let expander = match *self {
$( BuiltinAttrExpander::$variant => $expand, )*
};
expander(db, id, tt)
}
fn find_by_name(name: &name::Name) -> Option<Self> {
match name {
$( id if id == &name::name![$name] => Some(BuiltinAttrExpander::$variant), )*
_ => None,
}
}
}
};
}
register_builtin! {
(bench, Bench) => bench_expand,
(cfg_accessible, CfgAccessible) => cfg_accessible_expand,
(cfg_eval, CfgEval) => cfg_eval_expand,
(derive, Derive) => derive_expand,
(global_allocator, GlobalAllocator) => global_allocator_expand,
(test, Test) => test_expand,
(test_case, TestCase) => test_case_expand
}
pub fn find_builtin_attr(
ident: &name::Name,
krate: CrateId,
ast_id: AstId<ast::Macro>,
) -> Option<MacroDefId> {
let expander = BuiltinAttrExpander::find_by_name(ident)?;
Some(MacroDefId {
krate,
kind: MacroDefKind::BuiltInAttr(expander, ast_id),
local_inner: false,
})
}
fn bench_expand(
_db: &dyn AstDatabase,
_id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
Ok(tt.clone())
}
fn cfg_accessible_expand(
_db: &dyn AstDatabase,
_id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
Ok(tt.clone())
}
fn cfg_eval_expand(
_db: &dyn AstDatabase,
_id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
Ok(tt.clone())
}
fn derive_expand(
_db: &dyn AstDatabase,
_id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
Ok(tt.clone())
}
fn global_allocator_expand(
_db: &dyn AstDatabase,
_id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
Ok(tt.clone())
}
fn test_expand(
_db: &dyn AstDatabase,
_id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
Ok(tt.clone())
}
fn test_case_expand(
_db: &dyn AstDatabase,
_id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
Ok(tt.clone())
}

View File

@ -12,9 +12,9 @@ use syntax::{
};
use crate::{
ast_id_map::AstIdMap, hygiene::HygieneFrame, input::process_macro_input, BuiltinDeriveExpander,
BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc,
MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
ast_id_map::AstIdMap, hygiene::HygieneFrame, input::process_macro_input, BuiltinAttrExpander,
BuiltinDeriveExpander, BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId,
MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
};
/// Total limit on the number of tokens produced by any macro invocation.
@ -31,6 +31,8 @@ pub enum TokenExpander {
MacroDef { mac: mbe::MacroDef, def_site_token_map: mbe::TokenMap },
/// Stuff like `line!` and `file!`.
Builtin(BuiltinFnLikeExpander),
/// `global_allocator` and such.
BuiltinAttr(BuiltinAttrExpander),
/// `derive(Copy)` and such.
BuiltinDerive(BuiltinDeriveExpander),
/// The thing we love the most here in rust-analyzer -- procedural macros.
@ -49,6 +51,7 @@ impl TokenExpander {
TokenExpander::MacroDef { mac, .. } => mac.expand(tt),
TokenExpander::Builtin(it) => it.expand(db, id, tt),
// FIXME switch these to ExpandResult as well
TokenExpander::BuiltinAttr(it) => it.expand(db, id, tt).into(),
TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(),
TokenExpander::ProcMacro(_) => {
// We store the result in salsa db to prevent non-deterministic behavior in
@ -64,6 +67,7 @@ impl TokenExpander {
TokenExpander::MacroRules { mac, .. } => mac.map_id_down(id),
TokenExpander::MacroDef { mac, .. } => mac.map_id_down(id),
TokenExpander::Builtin(..)
| TokenExpander::BuiltinAttr(..)
| TokenExpander::BuiltinDerive(..)
| TokenExpander::ProcMacro(..) => id,
}
@ -74,6 +78,7 @@ impl TokenExpander {
TokenExpander::MacroRules { mac, .. } => mac.map_id_up(id),
TokenExpander::MacroDef { mac, .. } => mac.map_id_up(id),
TokenExpander::Builtin(..)
| TokenExpander::BuiltinAttr(..)
| TokenExpander::BuiltinDerive(..)
| TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call),
}
@ -299,6 +304,9 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<TokenExpander>>
}
},
MacroDefKind::BuiltIn(expander, _) => Some(Arc::new(TokenExpander::Builtin(expander))),
MacroDefKind::BuiltInAttr(expander, _) => {
Some(Arc::new(TokenExpander::BuiltinAttr(expander)))
}
MacroDefKind::BuiltInDerive(expander, _) => {
Some(Arc::new(TokenExpander::BuiltinDerive(expander)))
}

View File

@ -224,6 +224,7 @@ fn eager_macro_recur(
}
MacroDefKind::Declarative(_)
| MacroDefKind::BuiltIn(..)
| MacroDefKind::BuiltInAttr(..)
| MacroDefKind::BuiltInDerive(..)
| MacroDefKind::ProcMacro(..) => {
let res = lazy_expand(db, &def, curr.with_value(child.clone()), krate);

View File

@ -192,6 +192,7 @@ impl HygieneFrame {
(info, Some(loc.def.krate), loc.def.local_inner)
}
MacroDefKind::BuiltIn(..) => (info, Some(loc.def.krate), false),
MacroDefKind::BuiltInAttr(..) => (info, None, false),
MacroDefKind::BuiltInDerive(..) => (info, None, false),
MacroDefKind::BuiltInEager(..) => (info, None, false),
MacroDefKind::ProcMacro(..) => (info, None, false),

View File

@ -8,6 +8,7 @@ pub mod db;
pub mod ast_id_map;
pub mod name;
pub mod hygiene;
pub mod builtin_attr;
pub mod builtin_derive;
pub mod builtin_macro;
pub mod proc_macro;
@ -32,6 +33,7 @@ use syntax::{
};
use crate::ast_id_map::FileAstId;
use crate::builtin_attr::BuiltinAttrExpander;
use crate::builtin_derive::BuiltinDeriveExpander;
use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander};
use crate::proc_macro::ProcMacroExpander;
@ -206,6 +208,7 @@ impl MacroDefId {
let id = match &self.kind {
MacroDefKind::Declarative(id) => id,
MacroDefKind::BuiltIn(_, id) => id,
MacroDefKind::BuiltInAttr(_, id) => id,
MacroDefKind::BuiltInDerive(_, id) => id,
MacroDefKind::BuiltInEager(_, id) => id,
MacroDefKind::ProcMacro(.., id) => return Either::Right(*id),
@ -223,6 +226,7 @@ pub enum MacroDefKind {
Declarative(AstId<ast::Macro>),
BuiltIn(BuiltinFnLikeExpander, AstId<ast::Macro>),
// FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander
BuiltInAttr(BuiltinAttrExpander, AstId<ast::Macro>),
BuiltInDerive(BuiltinDeriveExpander, AstId<ast::Macro>),
BuiltInEager(EagerExpander, AstId<ast::Macro>),
ProcMacro(ProcMacroExpander, ProcMacroKind, AstId<ast::Fn>),

View File

@ -160,7 +160,6 @@ pub mod known {
str,
// Special names
macro_rules,
derive,
doc,
cfg,
cfg_attr,
@ -240,6 +239,14 @@ pub mod known {
PartialOrd,
Eq,
PartialEq,
// Builtin attributes
bench,
cfg_accessible,
cfg_eval,
derive,
global_allocator,
test,
test_case,
// Safe intrinsics
abort,
size_of,

View File

@ -656,6 +656,32 @@ fn main() { let _ = crate::$0 }
);
}
#[test]
fn does_not_complete_non_fn_macros() {
check(
r#"
mod m {
#[rustc_builtin_macro]
pub macro Clone {}
}
fn f() {m::$0}
"#,
expect![[r#""#]],
);
check(
r#"
mod m {
#[rustc_builtin_macro]
pub macro bench {}
}
fn f() {m::$0}
"#,
expect![[r#""#]],
);
}
#[test]
fn completes_in_assoc_item_list() {
check(

View File

@ -481,14 +481,14 @@ impl S {
);
check(
r#"
mod m {
#[rustc_builtin_macro]
pub macro Clone {}
}
#[rustc_builtin_macro]
pub macro bench {}
fn f() {m::$0}
fn f() {$0}
"#,
expect![[r#""#]],
expect![[r#"
fn f() fn()
"#]],
);
}