4431: Store proc-macro result in salsa db r=matklad a=edwin0cheng

Fixed #4315 

Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
bors[bot] 2020-05-15 10:17:42 +00:00 committed by GitHub
commit 982b92f966
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 3 deletions

View file

@ -34,7 +34,12 @@ impl TokenExpander {
// FIXME switch these to ExpandResult as well // FIXME switch these to ExpandResult as well
TokenExpander::Builtin(it) => it.expand(db, id, tt).into(), TokenExpander::Builtin(it) => it.expand(db, id, tt).into(),
TokenExpander::BuiltinDerive(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] #[salsa::interned]
fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId;
fn expand_proc_macro(&self, call: MacroCallId) -> Result<tt::Subtree, mbe::ExpandError>;
} }
/// This expands the given macro call, but with different arguments. This is /// 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))) (Some(Arc::new(tt)), err.map(|e| format!("{:?}", e)))
} }
pub(crate) fn expand_proc_macro(
db: &dyn AstDatabase,
id: MacroCallId,
) -> Result<tt::Subtree, mbe::ExpandError> {
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, &macro_arg.0)
}
pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> { pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> {
match file_id.0 { match file_id.0 {
HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()), HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()),

View file

@ -22,7 +22,7 @@ pub enum ParseError {
RepetitionEmtpyTokenTree, RepetitionEmtpyTokenTree,
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExpandError { pub enum ExpandError {
NoMatchingRule, NoMatchingRule,
UnexpectedToken, UnexpectedToken,

View file

@ -243,7 +243,7 @@ impl Subtree {
pub mod buffer; pub mod buffer;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExpansionError { pub enum ExpansionError {
IOError(String), IOError(String),
JsonError(String), JsonError(String),