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.rs76
1 files changed, 50 insertions, 26 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index d4cab0561..148ff007e 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -3,42 +3,53 @@
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};
14use ra_prof::profile;
11use ra_syntax::{ast, AstNode, AstPtr}; 15use ra_syntax::{ast, AstNode, AstPtr};
12use rustc_hash::FxHashMap; 16use rustc_hash::FxHashMap;
13 17
14use crate::{ 18use crate::{
15 db::DefDatabase, 19 db::DefDatabase,
16 expr::{Expr, ExprId, Pat, PatId}, 20 expr::{Expr, ExprId, Pat, PatId},
17 nameres::{BuiltinShadowMode, CrateDefMap}, 21 item_scope::BuiltinShadowMode,
22 nameres::CrateDefMap,
18 path::{ModPath, Path}, 23 path::{ModPath, Path},
19 src::HasSource, 24 src::HasSource,
20 DefWithBodyId, HasModule, Lookup, ModuleId, 25 DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId,
21}; 26};
22 27
23struct Expander { 28pub(crate) struct Expander {
24 crate_def_map: Arc<CrateDefMap>, 29 crate_def_map: Arc<CrateDefMap>,
25 current_file_id: HirFileId, 30 current_file_id: HirFileId,
26 hygiene: Hygiene, 31 hygiene: Hygiene,
32 ast_id_map: Arc<AstIdMap>,
27 module: ModuleId, 33 module: ModuleId,
28} 34}
29 35
30impl Expander { 36impl Expander {
31 fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { 37 pub(crate) fn new(
38 db: &impl DefDatabase,
39 current_file_id: HirFileId,
40 module: ModuleId,
41 ) -> Expander {
32 let crate_def_map = db.crate_def_map(module.krate); 42 let crate_def_map = db.crate_def_map(module.krate);
33 let hygiene = Hygiene::new(db, current_file_id); 43 let hygiene = Hygiene::new(db, current_file_id);
34 Expander { crate_def_map, current_file_id, hygiene, module } 44 let ast_id_map = db.ast_id_map(current_file_id);
45 Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module }
35 } 46 }
36 47
37 fn enter_expand( 48 pub(crate) fn enter_expand<T: ast::AstNode, DB: DefDatabase>(
38 &mut self, 49 &mut self,
39 db: &impl DefDatabase, 50 db: &DB,
40 macro_call: ast::MacroCall, 51 macro_call: ast::MacroCall,
41 ) -> Option<(Mark, ast::Expr)> { 52 ) -> Option<(Mark, T)> {
42 let ast_id = AstId::new( 53 let ast_id = AstId::new(
43 self.current_file_id, 54 self.current_file_id,
44 db.ast_id_map(self.current_file_id).ast_id(&macro_call), 55 db.ast_id_map(self.current_file_id).ast_id(&macro_call),
@@ -49,12 +60,17 @@ impl Expander {
49 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); 60 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id));
50 let file_id = call_id.as_file(); 61 let file_id = call_id.as_file();
51 if let Some(node) = db.parse_or_expand(file_id) { 62 if let Some(node) = db.parse_or_expand(file_id) {
52 if let Some(expr) = ast::Expr::cast(node) { 63 if let Some(expr) = T::cast(node) {
53 log::debug!("macro expansion {:#?}", expr.syntax()); 64 log::debug!("macro expansion {:#?}", expr.syntax());
54 65
55 let mark = Mark { file_id: self.current_file_id }; 66 let mark = Mark {
67 file_id: self.current_file_id,
68 ast_id_map: mem::take(&mut self.ast_id_map),
69 bomb: DropBomb::new("expansion mark dropped"),
70 };
56 self.hygiene = Hygiene::new(db, file_id); 71 self.hygiene = Hygiene::new(db, file_id);
57 self.current_file_id = file_id; 72 self.current_file_id = file_id;
73 self.ast_id_map = db.ast_id_map(file_id);
58 74
59 return Some((mark, expr)); 75 return Some((mark, expr));
60 } 76 }
@@ -67,13 +83,14 @@ impl Expander {
67 None 83 None
68 } 84 }
69 85
70 fn exit(&mut self, db: &impl DefDatabase, mark: Mark) { 86 pub(crate) fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) {
71 self.hygiene = Hygiene::new(db, mark.file_id); 87 self.hygiene = Hygiene::new(db, mark.file_id);
72 self.current_file_id = mark.file_id; 88 self.current_file_id = mark.file_id;
73 std::mem::forget(mark); 89 self.ast_id_map = mem::take(&mut mark.ast_id_map);
90 mark.bomb.defuse();
74 } 91 }
75 92
76 fn to_source<T>(&self, value: T) -> InFile<T> { 93 pub(crate) fn to_source<T>(&self, value: T) -> InFile<T> {
77 InFile { file_id: self.current_file_id, value } 94 InFile { file_id: self.current_file_id, value }
78 } 95 }
79 96
@@ -91,18 +108,17 @@ impl Expander {
91 .0 108 .0
92 .take_macros() 109 .take_macros()
93 } 110 }
94}
95 111
96struct Mark { 112 fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> {
97 file_id: HirFileId, 113 let file_local_id = self.ast_id_map.ast_id(item);
114 AstId::new(self.current_file_id, file_local_id)
115 }
98} 116}
99 117
100impl Drop for Mark { 118pub(crate) struct Mark {
101 fn drop(&mut self) { 119 file_id: HirFileId,
102 if !std::thread::panicking() { 120 ast_id_map: Arc<AstIdMap>,
103 panic!("dropped mark") 121 bomb: DropBomb,
104 }
105 }
106} 122}
107 123
108/// The body of an item (function, const etc.). 124/// The body of an item (function, const etc.).
@@ -119,6 +135,7 @@ pub struct Body {
119 pub params: Vec<PatId>, 135 pub params: Vec<PatId>,
120 /// The `ExprId` of the actual body expression. 136 /// The `ExprId` of the actual body expression.
121 pub body_expr: ExprId, 137 pub body_expr: ExprId,
138 pub defs: Vec<ModuleDefId>,
122} 139}
123 140
124pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>; 141pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>;
@@ -152,6 +169,7 @@ impl Body {
152 db: &impl DefDatabase, 169 db: &impl DefDatabase,
153 def: DefWithBodyId, 170 def: DefWithBodyId,
154 ) -> (Arc<Body>, Arc<BodySourceMap>) { 171 ) -> (Arc<Body>, Arc<BodySourceMap>) {
172 let _p = profile("body_with_source_map_query");
155 let mut params = None; 173 let mut params = None;
156 174
157 let (file_id, module, body) = match def { 175 let (file_id, module, body) = match def {
@@ -173,7 +191,7 @@ impl Body {
173 } 191 }
174 }; 192 };
175 let expander = Expander::new(db, file_id, module); 193 let expander = Expander::new(db, file_id, module);
176 let (body, source_map) = Body::new(db, expander, params, body); 194 let (body, source_map) = Body::new(db, def, expander, params, body);
177 (Arc::new(body), Arc::new(source_map)) 195 (Arc::new(body), Arc::new(source_map))
178 } 196 }
179 197
@@ -183,11 +201,12 @@ impl Body {
183 201
184 fn new( 202 fn new(
185 db: &impl DefDatabase, 203 db: &impl DefDatabase,
204 def: DefWithBodyId,
186 expander: Expander, 205 expander: Expander,
187 params: Option<ast::ParamList>, 206 params: Option<ast::ParamList>,
188 body: Option<ast::Expr>, 207 body: Option<ast::Expr>,
189 ) -> (Body, BodySourceMap) { 208 ) -> (Body, BodySourceMap) {
190 lower::lower(db, expander, params, body) 209 lower::lower(db, def, expander, params, body)
191 } 210 }
192} 211}
193 212
@@ -217,6 +236,11 @@ impl BodySourceMap {
217 self.expr_map.get(&src).cloned() 236 self.expr_map.get(&src).cloned()
218 } 237 }
219 238
239 pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> {
240 let src = node.map(|it| Either::Right(AstPtr::new(it)));
241 self.expr_map.get(&src).cloned()
242 }
243
220 pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> { 244 pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> {
221 self.pat_map_back.get(pat).copied() 245 self.pat_map_back.get(pat).copied()
222 } 246 }