diff options
Diffstat (limited to 'crates/ra_hir_expand/src')
-rw-r--r-- | crates/ra_hir_expand/src/db.rs | 36 |
1 files changed, 35 insertions, 1 deletions
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 { | |||
34 | // FIXME switch these to ExpandResult as well | 34 | // FIXME switch these to ExpandResult as well |
35 | TokenExpander::Builtin(it) => it.expand(db, id, tt).into(), | 35 | TokenExpander::Builtin(it) => it.expand(db, id, tt).into(), |
36 | TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), | 36 | TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), |
37 | TokenExpander::ProcMacro(it) => it.expand(db, id, tt).into(), | 37 | TokenExpander::ProcMacro(_) => { |
38 | // We store the result in salsa db to prevent non-determinisc behavior in | ||
39 | // some proc-macro implementation | ||
40 | // See #4315 for details | ||
41 | db.expand_proc_macro(id.into()).into() | ||
42 | } | ||
38 | } | 43 | } |
39 | } | 44 | } |
40 | 45 | ||
@@ -75,6 +80,8 @@ pub trait AstDatabase: SourceDatabase { | |||
75 | 80 | ||
76 | #[salsa::interned] | 81 | #[salsa::interned] |
77 | fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; | 82 | fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; |
83 | |||
84 | fn expand_proc_macro(&self, call: MacroCallId) -> Result<tt::Subtree, mbe::ExpandError>; | ||
78 | } | 85 | } |
79 | 86 | ||
80 | /// This expands the given macro call, but with different arguments. This is | 87 | /// This expands the given macro call, but with different arguments. This is |
@@ -216,6 +223,33 @@ fn macro_expand_with_arg( | |||
216 | (Some(Arc::new(tt)), err.map(|e| format!("{:?}", e))) | 223 | (Some(Arc::new(tt)), err.map(|e| format!("{:?}", e))) |
217 | } | 224 | } |
218 | 225 | ||
226 | pub(crate) fn expand_proc_macro( | ||
227 | db: &dyn AstDatabase, | ||
228 | id: MacroCallId, | ||
229 | ) -> Result<tt::Subtree, mbe::ExpandError> { | ||
230 | let lazy_id = match id { | ||
231 | MacroCallId::LazyMacro(id) => id, | ||
232 | MacroCallId::EagerMacro(_) => unreachable!(), | ||
233 | }; | ||
234 | |||
235 | let loc = db.lookup_intern_macro(lazy_id); | ||
236 | let macro_arg = match db.macro_arg(id) { | ||
237 | Some(it) => it, | ||
238 | None => { | ||
239 | return Err( | ||
240 | tt::ExpansionError::Unknown("No arguments for proc-macro".to_string()).into() | ||
241 | ) | ||
242 | } | ||
243 | }; | ||
244 | |||
245 | let expander = match loc.def.kind { | ||
246 | MacroDefKind::CustomDerive(expander) => expander, | ||
247 | _ => unreachable!(), | ||
248 | }; | ||
249 | |||
250 | expander.expand(db, lazy_id, ¯o_arg.0) | ||
251 | } | ||
252 | |||
219 | pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> { | 253 | pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> { |
220 | match file_id.0 { | 254 | match file_id.0 { |
221 | HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()), | 255 | HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()), |