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

@ -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,