From 20f7068b68b99610926b375d53d3721b878ff86c Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Thu, 14 May 2020 17:57:37 +0800 Subject: [PATCH] Store proc-macro result in salsa db --- crates/ra_hir_expand/src/db.rs | 36 +++++++++++++++++++++++++++++++++- crates/ra_mbe/src/lib.rs | 2 +- crates/ra_tt/src/lib.rs | 2 +- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 4c12d0a1596..bf30d71519e 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs @@ -34,7 +34,12 @@ pub fn expand( // 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 @@ fn parse_macro(&self, macro_file: MacroFile) #[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()), diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 1a020398e9e..9c450eabaed 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs @@ -22,7 +22,7 @@ pub enum ParseError { RepetitionEmtpyTokenTree, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum ExpandError { NoMatchingRule, UnexpectedToken, diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs index 5248e026c52..342ddbe3294 100644 --- a/crates/ra_tt/src/lib.rs +++ b/crates/ra_tt/src/lib.rs @@ -243,7 +243,7 @@ pub fn delimiter_kind(&self) -> Option { pub mod buffer; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum ExpansionError { IOError(String), JsonError(String),