aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_expand
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-03-27 02:57:02 +0000
committerGitHub <[email protected]>2021-03-27 02:57:02 +0000
commitc8066ebd1781a6f6f536abe3494477bd69df795a (patch)
treeedf5109d9f0629b0910f4f2ac716bd624330bb00 /crates/hir_expand
parent9c9376c4cffdd171375fbb21dd3d0f71a97a335e (diff)
parent8ce15b02dea7152953775904fd937cced2422bc6 (diff)
Merge #8201
8201: Fix recursive macro statements expansion r=edwin0cheng a=edwin0cheng This PR attempts to properly handle macro statement expansion by implementing the following: 1. Merge macro expanded statements to parent scope statements. 2. Add a new hir `Expr::MacroStmts` for handle tail expression infer. PS : The scope of macro expanded statements are so strange that it took more time than I thought to understand and implement it :( Fixes #8171 Co-authored-by: Edwin Cheng <[email protected]>
Diffstat (limited to 'crates/hir_expand')
-rw-r--r--crates/hir_expand/src/db.rs59
1 files changed, 42 insertions, 17 deletions
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index fc73e435b..d672f6723 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -5,7 +5,13 @@ use std::sync::Arc;
5use base_db::{salsa, SourceDatabase}; 5use base_db::{salsa, SourceDatabase};
6use mbe::{ExpandError, ExpandResult, MacroRules}; 6use mbe::{ExpandError, ExpandResult, MacroRules};
7use parser::FragmentKind; 7use parser::FragmentKind;
8use syntax::{algo::diff, ast::NameOwner, AstNode, GreenNode, Parse, SyntaxKind::*, SyntaxNode}; 8use syntax::{
9 algo::diff,
10 ast::{MacroStmts, NameOwner},
11 AstNode, GreenNode, Parse,
12 SyntaxKind::*,
13 SyntaxNode,
14};
9 15
10use crate::{ 16use crate::{
11 ast_id_map::AstIdMap, hygiene::HygieneFrame, BuiltinDeriveExpander, BuiltinFnLikeExpander, 17 ast_id_map::AstIdMap, hygiene::HygieneFrame, BuiltinDeriveExpander, BuiltinFnLikeExpander,
@@ -340,13 +346,19 @@ fn parse_macro_with_arg(
340 None => return ExpandResult { value: None, err: result.err }, 346 None => return ExpandResult { value: None, err: result.err },
341 }; 347 };
342 348
343 log::debug!("expanded = {}", tt.as_debug_string());
344
345 let fragment_kind = to_fragment_kind(db, macro_call_id); 349 let fragment_kind = to_fragment_kind(db, macro_call_id);
346 350
351 log::debug!("expanded = {}", tt.as_debug_string());
352 log::debug!("kind = {:?}", fragment_kind);
353
347 let (parse, rev_token_map) = match mbe::token_tree_to_syntax_node(&tt, fragment_kind) { 354 let (parse, rev_token_map) = match mbe::token_tree_to_syntax_node(&tt, fragment_kind) {
348 Ok(it) => it, 355 Ok(it) => it,
349 Err(err) => { 356 Err(err) => {
357 log::debug!(
358 "failed to parse expanstion to {:?} = {}",
359 fragment_kind,
360 tt.as_debug_string()
361 );
350 return ExpandResult::only_err(err); 362 return ExpandResult::only_err(err);
351 } 363 }
352 }; 364 };
@@ -362,15 +374,34 @@ fn parse_macro_with_arg(
362 return ExpandResult::only_err(err); 374 return ExpandResult::only_err(err);
363 } 375 }
364 }; 376 };
365 377 if is_self_replicating(&node, &call_node.value) {
366 if !diff(&node, &call_node.value).is_empty() {
367 ExpandResult { value: Some((parse, Arc::new(rev_token_map))), err: Some(err) }
368 } else {
369 return ExpandResult::only_err(err); 378 return ExpandResult::only_err(err);
379 } else {
380 ExpandResult { value: Some((parse, Arc::new(rev_token_map))), err: Some(err) }
381 }
382 }
383 None => {
384 log::debug!("parse = {:?}", parse.syntax_node().kind());
385 ExpandResult { value: Some((parse, Arc::new(rev_token_map))), err: None }
386 }
387 }
388}
389
390fn is_self_replicating(from: &SyntaxNode, to: &SyntaxNode) -> bool {
391 if diff(from, to).is_empty() {
392 return true;
393 }
394 if let Some(stmts) = MacroStmts::cast(from.clone()) {
395 if stmts.statements().any(|stmt| diff(stmt.syntax(), to).is_empty()) {
396 return true;
397 }
398 if let Some(expr) = stmts.expr() {
399 if diff(expr.syntax(), to).is_empty() {
400 return true;
370 } 401 }
371 } 402 }
372 None => ExpandResult { value: Some((parse, Arc::new(rev_token_map))), err: None },
373 } 403 }
404 false
374} 405}
375 406
376fn hygiene_frame(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<HygieneFrame> { 407fn hygiene_frame(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<HygieneFrame> {
@@ -390,21 +421,15 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
390 421
391 let parent = match syn.parent() { 422 let parent = match syn.parent() {
392 Some(it) => it, 423 Some(it) => it,
393 None => { 424 None => return FragmentKind::Statements,
394 // FIXME:
395 // If it is root, which means the parent HirFile
396 // MacroKindFile must be non-items
397 // return expr now.
398 return FragmentKind::Expr;
399 }
400 }; 425 };
401 426
402 match parent.kind() { 427 match parent.kind() {
403 MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items, 428 MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items,
404 MACRO_STMTS => FragmentKind::Statement, 429 MACRO_STMTS => FragmentKind::Statements,
405 ITEM_LIST => FragmentKind::Items, 430 ITEM_LIST => FragmentKind::Items,
406 LET_STMT => { 431 LET_STMT => {
407 // FIXME: Handle Pattern 432 // FIXME: Handle LHS Pattern
408 FragmentKind::Expr 433 FragmentKind::Expr
409 } 434 }
410 EXPR_STMT => FragmentKind::Statements, 435 EXPR_STMT => FragmentKind::Statements,