diff options
Diffstat (limited to 'crates/hir_expand/src/db.rs')
-rw-r--r-- | crates/hir_expand/src/db.rs | 120 |
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..5c769c1bf 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -13,8 +13,8 @@ use syntax::{ | |||
13 | 13 | ||
14 | use crate::{ | 14 | use 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 | ||
283 | fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> { | 264 | fn 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.arg_or_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, ¯o_arg.0); | 348 | let ExpandResult { value: tt, err } = macro_rules.expand(db, id, ¯o_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 | ||
438 | fn macro_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { | 404 | fn 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 | } |