aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/body
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/body')
-rw-r--r--crates/hir_def/src/body/lower.rs129
1 files changed, 67 insertions, 62 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 8c8eb8007..7052058f2 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -379,23 +379,22 @@ impl ExprCollector<'_> {
379 } 379 }
380 ast::Expr::RecordExpr(e) => { 380 ast::Expr::RecordExpr(e) => {
381 let path = e.path().and_then(|path| self.expander.parse_path(path)); 381 let path = e.path().and_then(|path| self.expander.parse_path(path));
382 let mut field_ptrs = Vec::new();
383 let record_lit = if let Some(nfl) = e.record_expr_field_list() { 382 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
384 let fields = nfl 383 let fields = nfl
385 .fields() 384 .fields()
386 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
387 .filter_map(|field| { 385 .filter_map(|field| {
388 self.check_cfg(&field)?; 386 self.check_cfg(&field)?;
389 387
390 let name = field.field_name()?.as_name(); 388 let name = field.field_name()?.as_name();
391 389
392 Some(RecordLitField { 390 let expr = match field.expr() {
393 name, 391 Some(e) => self.collect_expr(e),
394 expr: match field.expr() { 392 None => self.missing_expr(),
395 Some(e) => self.collect_expr(e), 393 };
396 None => self.missing_expr(), 394 let src = self.expander.to_source(AstPtr::new(&field));
397 }, 395 self.source_map.field_map.insert(src.clone(), expr);
398 }) 396 self.source_map.field_map_back.insert(expr, src);
397 Some(RecordLitField { name, expr })
399 }) 398 })
400 .collect(); 399 .collect();
401 let spread = nfl.spread().map(|s| self.collect_expr(s)); 400 let spread = nfl.spread().map(|s| self.collect_expr(s));
@@ -404,12 +403,7 @@ impl ExprCollector<'_> {
404 Expr::RecordLit { path, fields: Vec::new(), spread: None } 403 Expr::RecordLit { path, fields: Vec::new(), spread: None }
405 }; 404 };
406 405
407 let res = self.alloc_expr(record_lit, syntax_ptr); 406 self.alloc_expr(record_lit, syntax_ptr)
408 for (i, ptr) in field_ptrs.into_iter().enumerate() {
409 let src = self.expander.to_source(ptr);
410 self.source_map.field_map.insert((res, i), src);
411 }
412 res
413 } 407 }
414 ast::Expr::FieldExpr(e) => { 408 ast::Expr::FieldExpr(e) => {
415 let expr = self.collect_expr_opt(e.expr()); 409 let expr = self.collect_expr_opt(e.expr());
@@ -525,7 +519,7 @@ impl ExprCollector<'_> {
525 } 519 }
526 ast::Expr::MacroCall(e) => { 520 ast::Expr::MacroCall(e) => {
527 let mut ids = vec![]; 521 let mut ids = vec![];
528 self.collect_macro_call(e, syntax_ptr.clone(), |this, expansion| { 522 self.collect_macro_call(e, syntax_ptr.clone(), true, |this, expansion| {
529 ids.push(match expansion { 523 ids.push(match expansion {
530 Some(it) => this.collect_expr(it), 524 Some(it) => this.collect_expr(it),
531 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()), 525 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
@@ -533,6 +527,17 @@ impl ExprCollector<'_> {
533 }); 527 });
534 ids[0] 528 ids[0]
535 } 529 }
530 ast::Expr::MacroStmts(e) => {
531 // FIXME: these statements should be held by some hir containter
532 for stmt in e.statements() {
533 self.collect_stmt(stmt);
534 }
535 if let Some(expr) = e.expr() {
536 self.collect_expr(expr)
537 } else {
538 self.alloc_expr(Expr::Missing, syntax_ptr)
539 }
540 }
536 } 541 }
537 } 542 }
538 543
@@ -540,6 +545,7 @@ impl ExprCollector<'_> {
540 &mut self, 545 &mut self,
541 e: ast::MacroCall, 546 e: ast::MacroCall,
542 syntax_ptr: AstPtr<ast::Expr>, 547 syntax_ptr: AstPtr<ast::Expr>,
548 is_error_recoverable: bool,
543 mut collector: F, 549 mut collector: F,
544 ) { 550 ) {
545 // File containing the macro call. Expansion errors will be attached here. 551 // File containing the macro call. Expansion errors will be attached here.
@@ -573,7 +579,7 @@ impl ExprCollector<'_> {
573 Some((mark, expansion)) => { 579 Some((mark, expansion)) => {
574 // FIXME: Statements are too complicated to recover from error for now. 580 // FIXME: Statements are too complicated to recover from error for now.
575 // It is because we don't have any hygiene for local variable expansion right now. 581 // It is because we don't have any hygiene for local variable expansion right now.
576 if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() { 582 if !is_error_recoverable && res.err.is_some() {
577 self.expander.exit(self.db, mark); 583 self.expander.exit(self.db, mark);
578 collector(self, None); 584 collector(self, None);
579 } else { 585 } else {
@@ -597,56 +603,55 @@ impl ExprCollector<'_> {
597 } 603 }
598 604
599 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> { 605 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> {
600 let stmt = 606 let stmt = match s {
601 match s { 607 ast::Stmt::LetStmt(stmt) => {
602 ast::Stmt::LetStmt(stmt) => { 608 self.check_cfg(&stmt)?;
603 self.check_cfg(&stmt)?; 609
604 610 let pat = self.collect_pat_opt(stmt.pat());
605 let pat = self.collect_pat_opt(stmt.pat()); 611 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
606 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 612 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
607 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 613 vec![Statement::Let { pat, type_ref, initializer }]
608 vec![Statement::Let { pat, type_ref, initializer }] 614 }
609 } 615 ast::Stmt::ExprStmt(stmt) => {
610 ast::Stmt::ExprStmt(stmt) => { 616 self.check_cfg(&stmt)?;
611 self.check_cfg(&stmt)?; 617
612 618 // Note that macro could be expended to multiple statements
613 // Note that macro could be expended to multiple statements 619 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
614 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { 620 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
615 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); 621 let mut stmts = vec![];
616 let mut stmts = vec![]; 622
617 623 self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| {
618 self.collect_macro_call(m, syntax_ptr.clone(), |this, expansion| { 624 match expansion {
619 match expansion { 625 Some(expansion) => {
620 Some(expansion) => { 626 let statements: ast::MacroStmts = expansion;
621 let statements: ast::MacroStmts = expansion; 627
622 628 statements.statements().for_each(|stmt| {
623 statements.statements().for_each(|stmt| { 629 if let Some(mut r) = this.collect_stmt(stmt) {
624 if let Some(mut r) = this.collect_stmt(stmt) { 630 stmts.append(&mut r);
625 stmts.append(&mut r);
626 }
627 });
628 if let Some(expr) = statements.expr() {
629 stmts.push(Statement::Expr(this.collect_expr(expr)));
630 } 631 }
631 } 632 });
632 None => { 633 if let Some(expr) = statements.expr() {
633 stmts.push(Statement::Expr( 634 stmts.push(Statement::Expr(this.collect_expr(expr)));
634 this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
635 ));
636 } 635 }
637 } 636 }
638 }); 637 None => {
639 stmts 638 stmts.push(Statement::Expr(
640 } else { 639 this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
641 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))] 640 ));
642 } 641 }
642 }
643 });
644 stmts
645 } else {
646 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))]
643 } 647 }
644 ast::Stmt::Item(item) => { 648 }
645 self.check_cfg(&item)?; 649 ast::Stmt::Item(item) => {
650 self.check_cfg(&item)?;
646 651
647 return None; 652 return None;
648 } 653 }
649 }; 654 };
650 655
651 Some(stmt) 656 Some(stmt)
652 } 657 }