about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-10-29 13:13:12 +0000
committerGitHub <noreply@github.com>2021-10-29 13:13:12 +0000
commitb9fa37f5b4e452a496bd7c4baeba08cbdebf6336 (patch)
tree8f18f5891cff5b4f83c7d5d5a3fef198cd6a0a14
parent78108235d5182a6453a8eaa5a8ad5f2826f35f55 (diff)
parent98cff6572d2dd05760ac0f9f54df2f261b320b26 (diff)
downloadrust-b9fa37f5b4e452a496bd7c4baeba08cbdebf6336.tar.gz
rust-b9fa37f5b4e452a496bd7c4baeba08cbdebf6336.zip
Merge #10648
10648: fix: Don't discard attributed items when a proc-macro unexpectedly fails to expand r=Veykril a=Veykril

Fixes https://github.com/rust-analyzer/rust-analyzer/issues/9205

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
-rw-r--r--crates/hir_expand/src/proc_macro.rs34
-rw-r--r--crates/proc_macro_api/src/lib.rs2
2 files changed, 23 insertions, 13 deletions
diff --git a/crates/hir_expand/src/proc_macro.rs b/crates/hir_expand/src/proc_macro.rs
index e8e1d99e808..d68794eb980 100644
--- a/crates/hir_expand/src/proc_macro.rs
+++ b/crates/hir_expand/src/proc_macro.rs
@@ -1,9 +1,10 @@
 //! Proc Macro Expander stub
 
-use crate::db::AstDatabase;
-use base_db::{CrateId, ProcMacroExpansionError, ProcMacroId};
+use base_db::{CrateId, ProcMacroExpansionError, ProcMacroId, ProcMacroKind};
 use mbe::ExpandResult;
 
+use crate::db::AstDatabase;
+
 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
 pub struct ProcMacroExpander {
     krate: CrateId,
@@ -36,20 +37,29 @@ impl ProcMacroExpander {
                 let krate_graph = db.crate_graph();
                 let proc_macro = match krate_graph[self.krate].proc_macro.get(id.0 as usize) {
                     Some(proc_macro) => proc_macro,
-                    None => return ExpandResult::str_err("No derive macro found.".to_string()),
+                    None => return ExpandResult::str_err("No proc-macro found.".to_string()),
                 };
 
                 // Proc macros have access to the environment variables of the invoking crate.
                 let env = &krate_graph[calling_crate].env;
-
-                proc_macro
-                    .expander
-                    .expand(tt, attr_arg, env)
-                    .map_err(|err| match err {
-                        ProcMacroExpansionError::Panic(text) => mbe::ExpandError::Other(text),
-                        ProcMacroExpansionError::System(text) => mbe::ExpandError::Other(text),
-                    })
-                    .into()
+                match proc_macro.expander.expand(tt, attr_arg, env) {
+                    Ok(t) => ExpandResult::ok(t),
+                    Err(err) => match err {
+                        // Don't discard the item in case something unexpected happened while expanding attributes
+                        ProcMacroExpansionError::System(text)
+                            if proc_macro.kind == ProcMacroKind::Attr =>
+                        {
+                            ExpandResult {
+                                value: tt.clone(),
+                                err: Some(mbe::ExpandError::Other(text)),
+                            }
+                        }
+                        ProcMacroExpansionError::System(text)
+                        | ProcMacroExpansionError::Panic(text) => {
+                            ExpandResult::only_err(mbe::ExpandError::Other(text))
+                        }
+                    },
+                }
             }
             None => ExpandResult::only_err(mbe::ExpandError::UnresolvedProcMacro),
         }
diff --git a/crates/proc_macro_api/src/lib.rs b/crates/proc_macro_api/src/lib.rs
index b03a029f8ad..9e50c1f83f7 100644
--- a/crates/proc_macro_api/src/lib.rs
+++ b/crates/proc_macro_api/src/lib.rs
@@ -167,7 +167,7 @@ impl ProcMacro {
         let request = msg::Request::ExpandMacro(task);
         let response = self.process.lock().unwrap_or_else(|e| e.into_inner()).send_task(request)?;
         match response {
-            msg::Response::ExpandMacro(it) => Ok(it.map(|it| it.to_subtree())),
+            msg::Response::ExpandMacro(it) => Ok(it.map(FlatTree::to_subtree)),
             msg::Response::ListMacros { .. } => {
                 Err(ServerError { message: "unexpected response".to_string(), io: None })
             }