From 20f7068b68b99610926b375d53d3721b878ff86c Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Thu, 14 May 2020 17:57:37 +0800 Subject: Store proc-macro result in salsa db --- crates/ra_hir_expand/src/db.rs | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'crates/ra_hir_expand/src') diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 4c12d0a15..bf30d7151 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs @@ -34,7 +34,12 @@ impl TokenExpander { // FIXME switch these to ExpandResult as well TokenExpander::Builtin(it) => it.expand(db, id, tt).into(), TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), - TokenExpander::ProcMacro(it) => it.expand(db, id, tt).into(), + TokenExpander::ProcMacro(_) => { + // We store the result in salsa db to prevent non-determinisc behavior in + // some proc-macro implementation + // See #4315 for details + db.expand_proc_macro(id.into()).into() + } } } @@ -75,6 +80,8 @@ pub trait AstDatabase: SourceDatabase { #[salsa::interned] fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; + + fn expand_proc_macro(&self, call: MacroCallId) -> Result; } /// This expands the given macro call, but with different arguments. This is @@ -216,6 +223,33 @@ fn macro_expand_with_arg( (Some(Arc::new(tt)), err.map(|e| format!("{:?}", e))) } +pub(crate) fn expand_proc_macro( + db: &dyn AstDatabase, + id: MacroCallId, +) -> Result { + let lazy_id = match id { + MacroCallId::LazyMacro(id) => id, + MacroCallId::EagerMacro(_) => unreachable!(), + }; + + let loc = db.lookup_intern_macro(lazy_id); + let macro_arg = match db.macro_arg(id) { + Some(it) => it, + None => { + return Err( + tt::ExpansionError::Unknown("No arguments for proc-macro".to_string()).into() + ) + } + }; + + let expander = match loc.def.kind { + MacroDefKind::CustomDerive(expander) => expander, + _ => unreachable!(), + }; + + expander.expand(db, lazy_id, ¯o_arg.0) +} + pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option { match file_id.0 { HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()), -- cgit v1.2.3