aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/body.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/body.rs')
-rw-r--r--crates/ra_hir_def/src/body.rs63
1 files changed, 42 insertions, 21 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 7787cb87f..401fe0b9b 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -3,10 +3,13 @@
3mod lower; 3mod lower;
4pub mod scope; 4pub mod scope;
5 5
6use std::{ops::Index, sync::Arc}; 6use std::{mem, ops::Index, sync::Arc};
7 7
8use drop_bomb::DropBomb;
8use either::Either; 9use either::Either;
9use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId}; 10use hir_expand::{
11 ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId,
12};
10use ra_arena::{map::ArenaMap, Arena}; 13use ra_arena::{map::ArenaMap, Arena};
11use ra_syntax::{ast, AstNode, AstPtr}; 14use ra_syntax::{ast, AstNode, AstPtr};
12use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
@@ -15,15 +18,16 @@ use crate::{
15 db::DefDatabase, 18 db::DefDatabase,
16 expr::{Expr, ExprId, Pat, PatId}, 19 expr::{Expr, ExprId, Pat, PatId},
17 nameres::{BuiltinShadowMode, CrateDefMap}, 20 nameres::{BuiltinShadowMode, CrateDefMap},
18 path::Path, 21 path::{ModPath, Path},
19 src::HasSource, 22 src::HasSource,
20 DefWithBodyId, HasModule, Lookup, ModuleId, 23 DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId,
21}; 24};
22 25
23struct Expander { 26struct Expander {
24 crate_def_map: Arc<CrateDefMap>, 27 crate_def_map: Arc<CrateDefMap>,
25 current_file_id: HirFileId, 28 current_file_id: HirFileId,
26 hygiene: Hygiene, 29 hygiene: Hygiene,
30 ast_id_map: Arc<AstIdMap>,
27 module: ModuleId, 31 module: ModuleId,
28} 32}
29 33
@@ -31,7 +35,8 @@ impl Expander {
31 fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { 35 fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander {
32 let crate_def_map = db.crate_def_map(module.krate); 36 let crate_def_map = db.crate_def_map(module.krate);
33 let hygiene = Hygiene::new(db, current_file_id); 37 let hygiene = Hygiene::new(db, current_file_id);
34 Expander { crate_def_map, current_file_id, hygiene, module } 38 let ast_id_map = db.ast_id_map(current_file_id);
39 Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module }
35 } 40 }
36 41
37 fn enter_expand( 42 fn enter_expand(
@@ -44,7 +49,7 @@ impl Expander {
44 db.ast_id_map(self.current_file_id).ast_id(&macro_call), 49 db.ast_id_map(self.current_file_id).ast_id(&macro_call),
45 ); 50 );
46 51
47 if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { 52 if let Some(path) = macro_call.path().and_then(|path| self.parse_mod_path(path)) {
48 if let Some(def) = self.resolve_path_as_macro(db, &path) { 53 if let Some(def) = self.resolve_path_as_macro(db, &path) {
49 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); 54 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id));
50 let file_id = call_id.as_file(); 55 let file_id = call_id.as_file();
@@ -52,9 +57,14 @@ impl Expander {
52 if let Some(expr) = ast::Expr::cast(node) { 57 if let Some(expr) = ast::Expr::cast(node) {
53 log::debug!("macro expansion {:#?}", expr.syntax()); 58 log::debug!("macro expansion {:#?}", expr.syntax());
54 59
55 let mark = Mark { file_id: self.current_file_id }; 60 let mark = Mark {
61 file_id: self.current_file_id,
62 ast_id_map: mem::take(&mut self.ast_id_map),
63 bomb: DropBomb::new("expansion mark dropped"),
64 };
56 self.hygiene = Hygiene::new(db, file_id); 65 self.hygiene = Hygiene::new(db, file_id);
57 self.current_file_id = file_id; 66 self.current_file_id = file_id;
67 self.ast_id_map = db.ast_id_map(file_id);
58 68
59 return Some((mark, expr)); 69 return Some((mark, expr));
60 } 70 }
@@ -67,10 +77,11 @@ impl Expander {
67 None 77 None
68 } 78 }
69 79
70 fn exit(&mut self, db: &impl DefDatabase, mark: Mark) { 80 fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) {
71 self.hygiene = Hygiene::new(db, mark.file_id); 81 self.hygiene = Hygiene::new(db, mark.file_id);
72 self.current_file_id = mark.file_id; 82 self.current_file_id = mark.file_id;
73 std::mem::forget(mark); 83 self.ast_id_map = mem::take(&mut mark.ast_id_map);
84 mark.bomb.defuse();
74 } 85 }
75 86
76 fn to_source<T>(&self, value: T) -> InFile<T> { 87 fn to_source<T>(&self, value: T) -> InFile<T> {
@@ -81,24 +92,27 @@ impl Expander {
81 Path::from_src(path, &self.hygiene) 92 Path::from_src(path, &self.hygiene)
82 } 93 }
83 94
84 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { 95 fn parse_mod_path(&mut self, path: ast::Path) -> Option<ModPath> {
96 ModPath::from_src(path, &self.hygiene)
97 }
98
99 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &ModPath) -> Option<MacroDefId> {
85 self.crate_def_map 100 self.crate_def_map
86 .resolve_path(db, self.module.local_id, path.mod_path(), BuiltinShadowMode::Other) 101 .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other)
87 .0 102 .0
88 .take_macros() 103 .take_macros()
89 } 104 }
105
106 fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> {
107 let file_local_id = self.ast_id_map.ast_id(item);
108 AstId::new(self.current_file_id, file_local_id)
109 }
90} 110}
91 111
92struct Mark { 112struct Mark {
93 file_id: HirFileId, 113 file_id: HirFileId,
94} 114 ast_id_map: Arc<AstIdMap>,
95 115 bomb: DropBomb,
96impl Drop for Mark {
97 fn drop(&mut self) {
98 if !std::thread::panicking() {
99 panic!("dropped mark")
100 }
101 }
102} 116}
103 117
104/// The body of an item (function, const etc.). 118/// The body of an item (function, const etc.).
@@ -115,6 +129,7 @@ pub struct Body {
115 pub params: Vec<PatId>, 129 pub params: Vec<PatId>,
116 /// The `ExprId` of the actual body expression. 130 /// The `ExprId` of the actual body expression.
117 pub body_expr: ExprId, 131 pub body_expr: ExprId,
132 pub defs: Vec<ModuleDefId>,
118} 133}
119 134
120pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>; 135pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>;
@@ -169,7 +184,7 @@ impl Body {
169 } 184 }
170 }; 185 };
171 let expander = Expander::new(db, file_id, module); 186 let expander = Expander::new(db, file_id, module);
172 let (body, source_map) = Body::new(db, expander, params, body); 187 let (body, source_map) = Body::new(db, def, expander, params, body);
173 (Arc::new(body), Arc::new(source_map)) 188 (Arc::new(body), Arc::new(source_map))
174 } 189 }
175 190
@@ -179,11 +194,12 @@ impl Body {
179 194
180 fn new( 195 fn new(
181 db: &impl DefDatabase, 196 db: &impl DefDatabase,
197 def: DefWithBodyId,
182 expander: Expander, 198 expander: Expander,
183 params: Option<ast::ParamList>, 199 params: Option<ast::ParamList>,
184 body: Option<ast::Expr>, 200 body: Option<ast::Expr>,
185 ) -> (Body, BodySourceMap) { 201 ) -> (Body, BodySourceMap) {
186 lower::lower(db, expander, params, body) 202 lower::lower(db, def, expander, params, body)
187 } 203 }
188} 204}
189 205
@@ -213,6 +229,11 @@ impl BodySourceMap {
213 self.expr_map.get(&src).cloned() 229 self.expr_map.get(&src).cloned()
214 } 230 }
215 231
232 pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> {
233 let src = node.map(|it| Either::Right(AstPtr::new(it)));
234 self.expr_map.get(&src).cloned()
235 }
236
216 pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> { 237 pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> {
217 self.pat_map_back.get(pat).copied() 238 self.pat_map_back.get(pat).copied()
218 } 239 }