aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_expand/src/db.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_expand/src/db.rs')
-rw-r--r--crates/hir_expand/src/db.rs120
1 files changed, 39 insertions, 81 deletions
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index c43d382ad..7a82400a8 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -13,8 +13,8 @@ use syntax::{
13 13
14use crate::{ 14use crate::{
15 ast_id_map::AstIdMap, hygiene::HygieneFrame, input::process_macro_input, BuiltinDeriveExpander, 15 ast_id_map::AstIdMap, hygiene::HygieneFrame, input::process_macro_input, BuiltinDeriveExpander,
16 BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId, HirFileId, HirFileIdRepr, LazyMacroId, 16 BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc, MacroDefId,
17 MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander, 17 MacroDefKind, MacroFile, ProcMacroExpander,
18}; 18};
19 19
20/// Total limit on the number of tokens produced by any macro invocation. 20/// Total limit on the number of tokens produced by any macro invocation.
@@ -41,7 +41,7 @@ impl TokenExpander {
41 fn expand( 41 fn expand(
42 &self, 42 &self,
43 db: &dyn AstDatabase, 43 db: &dyn AstDatabase,
44 id: LazyMacroId, 44 id: MacroCallId,
45 tt: &tt::Subtree, 45 tt: &tt::Subtree,
46 ) -> mbe::ExpandResult<tt::Subtree> { 46 ) -> mbe::ExpandResult<tt::Subtree> {
47 match self { 47 match self {
@@ -101,11 +101,7 @@ pub trait AstDatabase: SourceDatabase {
101 /// We encode macro definitions into ids of macro calls, this what allows us 101 /// We encode macro definitions into ids of macro calls, this what allows us
102 /// to be incremental. 102 /// to be incremental.
103 #[salsa::interned] 103 #[salsa::interned]
104 fn intern_macro(&self, macro_call: MacroCallLoc) -> LazyMacroId; 104 fn intern_macro(&self, macro_call: MacroCallLoc) -> MacroCallId;
105 /// Certain built-in macros are eager (`format!(concat!("file: ", file!(), "{}"")), 92`).
106 /// For them, we actually want to encode the whole token tree as an argument.
107 #[salsa::interned]
108 fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId;
109 105
110 /// Lowers syntactic macro call to a token tree representation. 106 /// Lowers syntactic macro call to a token tree representation.
111 #[salsa::transparent] 107 #[salsa::transparent]
@@ -146,17 +142,12 @@ pub fn expand_hypothetical(
146 token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?; 142 token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?;
147 let token_id = tmap_1.token_by_range(range)?; 143 let token_id = tmap_1.token_by_range(range)?;
148 144
149 let lazy_id = match actual_macro_call {
150 MacroCallId::LazyMacro(id) => id,
151 MacroCallId::EagerMacro(_) => return None,
152 };
153
154 let macro_def = { 145 let macro_def = {
155 let loc = db.lookup_intern_macro(lazy_id); 146 let loc: MacroCallLoc = db.lookup_intern_macro(actual_macro_call);
156 db.macro_def(loc.def)? 147 db.macro_def(loc.def)?
157 }; 148 };
158 149
159 let hypothetical_expansion = macro_def.expand(db, lazy_id, &tt); 150 let hypothetical_expansion = macro_def.expand(db, actual_macro_call, &tt);
160 151
161 let fragment_kind = macro_fragment_kind(db, actual_macro_call); 152 let fragment_kind = macro_fragment_kind(db, actual_macro_call);
162 153
@@ -194,30 +185,22 @@ fn parse_macro_expansion(
194 // Note: 185 // Note:
195 // The final goal we would like to make all parse_macro success, 186 // The final goal we would like to make all parse_macro success,
196 // such that the following log will not call anyway. 187 // such that the following log will not call anyway.
197 match macro_file.macro_call_id { 188 let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
198 MacroCallId::LazyMacro(id) => { 189 let node = loc.kind.node(db);
199 let loc: MacroCallLoc = db.lookup_intern_macro(id); 190
200 let node = loc.kind.node(db); 191 // collect parent information for warning log
201 192 let parents =
202 // collect parent information for warning log 193 std::iter::successors(loc.kind.file_id().call_node(db), |it| it.file_id.call_node(db))
203 let parents = std::iter::successors(loc.kind.file_id().call_node(db), |it| {
204 it.file_id.call_node(db)
205 })
206 .map(|n| format!("{:#}", n.value)) 194 .map(|n| format!("{:#}", n.value))
207 .collect::<Vec<_>>() 195 .collect::<Vec<_>>()
208 .join("\n"); 196 .join("\n");
209 197
210 log::warn!( 198 log::warn!(
211 "fail on macro_parse: (reason: {:?} macro_call: {:#}) parents: {}", 199 "fail on macro_parse: (reason: {:?} macro_call: {:#}) parents: {}",
212 err, 200 err,
213 node.value, 201 node.value,
214 parents 202 parents
215 ); 203 );
216 }
217 _ => {
218 log::warn!("fail on macro_parse: (reason: {:?})", err);
219 }
220 }
221 } 204 }
222 let tt = match result.value { 205 let tt = match result.value {
223 Some(tt) => tt, 206 Some(tt) => tt,
@@ -269,25 +252,16 @@ fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree,
269 let arg = db.macro_arg_text(id)?; 252 let arg = db.macro_arg_text(id)?;
270 let (mut tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg)); 253 let (mut tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg));
271 254
272 if let MacroCallId::LazyMacro(id) = id { 255 let loc: MacroCallLoc = db.lookup_intern_macro(id);
273 let loc: MacroCallLoc = db.lookup_intern_macro(id); 256 if loc.def.is_proc_macro() {
274 if loc.def.is_proc_macro() { 257 // proc macros expect their inputs without parentheses, MBEs expect it with them included
275 // proc macros expect their inputs without parentheses, MBEs expect it with them included 258 tt.delimiter = None;
276 tt.delimiter = None;
277 }
278 } 259 }
279 260
280 Some(Arc::new((tt, tmap))) 261 Some(Arc::new((tt, tmap)))
281} 262}
282 263
283fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> { 264fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> {
284 let id = match id {
285 MacroCallId::LazyMacro(id) => id,
286 MacroCallId::EagerMacro(_id) => {
287 // FIXME: support macro_arg for eager macro
288 return None;
289 }
290 };
291 let loc = db.lookup_intern_macro(id); 265 let loc = db.lookup_intern_macro(id);
292 let arg = loc.kind.arg(db)?; 266 let arg = loc.kind.arg(db)?;
293 let arg = process_macro_input(db, arg, id); 267 let arg = process_macro_input(db, arg, id);
@@ -347,24 +321,21 @@ fn macro_expand_with_arg(
347 arg: Option<Arc<(tt::Subtree, mbe::TokenMap)>>, 321 arg: Option<Arc<(tt::Subtree, mbe::TokenMap)>>,
348) -> ExpandResult<Option<Arc<tt::Subtree>>> { 322) -> ExpandResult<Option<Arc<tt::Subtree>>> {
349 let _p = profile::span("macro_expand"); 323 let _p = profile::span("macro_expand");
350 let lazy_id = match id { 324 let loc: MacroCallLoc = db.lookup_intern_macro(id);
351 MacroCallId::LazyMacro(id) => id, 325 if let Some(eager) = &loc.eager {
352 MacroCallId::EagerMacro(id) => { 326 if arg.is_some() {
353 if arg.is_some() { 327 return ExpandResult::str_err(
354 return ExpandResult::str_err( 328 "hypothetical macro expansion not implemented for eager macro".to_owned(),
355 "hypothetical macro expansion not implemented for eager macro".to_owned(), 329 );
356 ); 330 } else {
357 } else { 331 return ExpandResult {
358 return ExpandResult { 332 value: Some(eager.expansion.clone()),
359 value: Some(db.lookup_intern_eager_expansion(id).subtree), 333 // FIXME: There could be errors here!
360 // FIXME: There could be errors here! 334 err: None,
361 err: None, 335 };
362 };
363 }
364 } 336 }
365 }; 337 }
366 338
367 let loc = db.lookup_intern_macro(lazy_id);
368 let macro_arg = match arg.or_else(|| db.macro_arg(id)) { 339 let macro_arg = match arg.or_else(|| db.macro_arg(id)) {
369 Some(it) => it, 340 Some(it) => it,
370 None => return ExpandResult::str_err("Fail to args in to tt::TokenTree".into()), 341 None => return ExpandResult::str_err("Fail to args in to tt::TokenTree".into()),
@@ -374,7 +345,7 @@ fn macro_expand_with_arg(
374 Some(it) => it, 345 Some(it) => it,
375 None => return ExpandResult::str_err("Fail to find macro definition".into()), 346 None => return ExpandResult::str_err("Fail to find macro definition".into()),
376 }; 347 };
377 let ExpandResult { value: tt, err } = macro_rules.expand(db, lazy_id, &macro_arg.0); 348 let ExpandResult { value: tt, err } = macro_rules.expand(db, id, &macro_arg.0);
378 // Set a hard limit for the expanded tt 349 // Set a hard limit for the expanded tt
379 let count = tt.count(); 350 let count = tt.count();
380 if count > TOKEN_LIMIT { 351 if count > TOKEN_LIMIT {
@@ -391,12 +362,7 @@ fn expand_proc_macro(
391 db: &dyn AstDatabase, 362 db: &dyn AstDatabase,
392 id: MacroCallId, 363 id: MacroCallId,
393) -> Result<tt::Subtree, mbe::ExpandError> { 364) -> Result<tt::Subtree, mbe::ExpandError> {
394 let lazy_id = match id { 365 let loc: MacroCallLoc = db.lookup_intern_macro(id);
395 MacroCallId::LazyMacro(id) => id,
396 MacroCallId::EagerMacro(_) => unreachable!(),
397 };
398
399 let loc = db.lookup_intern_macro(lazy_id);
400 let macro_arg = match db.macro_arg(id) { 366 let macro_arg = match db.macro_arg(id) {
401 Some(it) => it, 367 Some(it) => it,
402 None => { 368 None => {
@@ -436,14 +402,6 @@ fn hygiene_frame(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<HygieneFrame>
436} 402}
437 403
438fn macro_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { 404fn macro_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
439 match id { 405 let loc: MacroCallLoc = db.lookup_intern_macro(id);
440 MacroCallId::LazyMacro(id) => { 406 loc.kind.fragment_kind()
441 let loc: MacroCallLoc = db.lookup_intern_macro(id);
442 loc.kind.fragment_kind()
443 }
444 MacroCallId::EagerMacro(id) => {
445 let loc: EagerCallLoc = db.lookup_intern_eager_expansion(id);
446 loc.fragment
447 }
448 }
449} 407}