From e7880db1d0f75c639ee561b586219648bd05c21c Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Thu, 14 Nov 2019 09:52:03 +0300
Subject: Expansion stack scaffold

---
 crates/ra_hir_def/src/body.rs       | 37 +++++++++++++++++++++++++++++++++++--
 crates/ra_hir_def/src/body/lower.rs |  9 +++------
 2 files changed, 38 insertions(+), 8 deletions(-)

(limited to 'crates/ra_hir_def/src')

diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 622c836d1..3b262e3bd 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -3,7 +3,7 @@ mod lower;
 
 use std::{ops::Index, sync::Arc};
 
-use hir_expand::{either::Either, HirFileId, MacroDefId, Source};
+use hir_expand::{either::Either, hygiene::Hygiene, HirFileId, MacroDefId, Source};
 use ra_arena::{map::ArenaMap, Arena};
 use ra_syntax::{ast, AstPtr};
 use rustc_hash::FxHashMap;
@@ -20,13 +20,34 @@ pub struct Expander {
     crate_def_map: Arc<CrateDefMap>,
     original_file_id: HirFileId,
     current_file_id: HirFileId,
+    hygiene: Hygiene,
     module: ModuleId,
 }
 
 impl Expander {
     pub fn new(db: &impl DefDatabase2, current_file_id: HirFileId, module: ModuleId) -> Expander {
         let crate_def_map = db.crate_def_map(module.krate);
-        Expander { crate_def_map, original_file_id: current_file_id, current_file_id, module }
+        let hygiene = Hygiene::new(db, current_file_id);
+        Expander {
+            crate_def_map,
+            original_file_id: current_file_id,
+            current_file_id,
+            hygiene,
+            module,
+        }
+    }
+
+    fn enter(&mut self, db: &impl DefDatabase2, file_id: HirFileId) -> Mark {
+        let mark = Mark { file_id: self.current_file_id };
+        self.hygiene = Hygiene::new(db, file_id);
+        self.current_file_id = file_id;
+        mark
+    }
+
+    fn exit(&mut self, db: &impl DefDatabase2, mark: Mark) {
+        self.hygiene = Hygiene::new(db, mark.file_id);
+        self.current_file_id = mark.file_id;
+        std::mem::forget(mark);
     }
 
     // FIXME: remove this.
@@ -43,6 +64,18 @@ impl Expander {
     }
 }
 
+struct Mark {
+    file_id: HirFileId,
+}
+
+impl Drop for Mark {
+    fn drop(&mut self) {
+        if !std::thread::panicking() {
+            panic!("dropped mark")
+        }
+    }
+}
+
 /// The body of an item (function, const etc.).
 #[derive(Debug, Eq, PartialEq)]
 pub struct Body {
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 1ea8ce249..5c291421a 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -2,7 +2,6 @@
 
 use hir_expand::{
     either::Either,
-    hygiene::Hygiene,
     name::{self, AsName, Name},
     AstId, MacroCallLoc, MacroFileKind,
 };
@@ -447,10 +446,9 @@ where
                         if let Some(node) = self.db.parse_or_expand(file_id) {
                             if let Some(expr) = ast::Expr::cast(node) {
                                 log::debug!("macro expansion {:#?}", expr.syntax());
-                                let old_file_id =
-                                    std::mem::replace(&mut self.expander.current_file_id, file_id);
+                                let mark = self.expander.enter(self.db, file_id);
                                 let id = self.collect_expr(expr);
-                                self.expander.current_file_id = old_file_id;
+                                self.expander.exit(self.db, mark);
                                 return id;
                             }
                         }
@@ -572,8 +570,7 @@ where
     }
 
     fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
-        let hygiene = Hygiene::new(self.db, self.expander.current_file_id);
-        Path::from_src(path, &hygiene)
+        Path::from_src(path, &self.expander.hygiene)
     }
 }
 
-- 
cgit v1.2.3