diff options
Diffstat (limited to 'crates/hir_def/src/body')
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 109 | ||||
-rw-r--r-- | crates/hir_def/src/body/tests.rs | 2 |
2 files changed, 59 insertions, 52 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 19f5065d1..bfb75a8a5 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -30,6 +30,7 @@ use crate::{ | |||
30 | LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, | 30 | LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, |
31 | Statement, | 31 | Statement, |
32 | }, | 32 | }, |
33 | intern::Interned, | ||
33 | item_scope::BuiltinShadowMode, | 34 | item_scope::BuiltinShadowMode, |
34 | path::{GenericArgs, Path}, | 35 | path::{GenericArgs, Path}, |
35 | type_ref::{Mutability, Rawness, TypeRef}, | 36 | type_ref::{Mutability, Rawness, TypeRef}, |
@@ -74,6 +75,7 @@ pub(super) fn lower( | |||
74 | _c: Count::new(), | 75 | _c: Count::new(), |
75 | }, | 76 | }, |
76 | expander, | 77 | expander, |
78 | statements_in_scope: Vec::new(), | ||
77 | } | 79 | } |
78 | .collect(params, body) | 80 | .collect(params, body) |
79 | } | 81 | } |
@@ -83,6 +85,7 @@ struct ExprCollector<'a> { | |||
83 | expander: Expander, | 85 | expander: Expander, |
84 | body: Body, | 86 | body: Body, |
85 | source_map: BodySourceMap, | 87 | source_map: BodySourceMap, |
88 | statements_in_scope: Vec<Statement>, | ||
86 | } | 89 | } |
87 | 90 | ||
88 | impl ExprCollector<'_> { | 91 | impl ExprCollector<'_> { |
@@ -320,8 +323,10 @@ impl ExprCollector<'_> { | |||
320 | Vec::new() | 323 | Vec::new() |
321 | }; | 324 | }; |
322 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); | 325 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); |
323 | let generic_args = | 326 | let generic_args = e |
324 | e.generic_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); | 327 | .generic_arg_list() |
328 | .and_then(|it| GenericArgs::from_ast(&self.ctx(), it)) | ||
329 | .map(Box::new); | ||
325 | self.alloc_expr( | 330 | self.alloc_expr( |
326 | Expr::MethodCall { receiver, method_name, args, generic_args }, | 331 | Expr::MethodCall { receiver, method_name, args, generic_args }, |
327 | syntax_ptr, | 332 | syntax_ptr, |
@@ -383,7 +388,7 @@ impl ExprCollector<'_> { | |||
383 | self.alloc_expr(Expr::Yield { expr }, syntax_ptr) | 388 | self.alloc_expr(Expr::Yield { expr }, syntax_ptr) |
384 | } | 389 | } |
385 | ast::Expr::RecordExpr(e) => { | 390 | ast::Expr::RecordExpr(e) => { |
386 | let path = e.path().and_then(|path| self.expander.parse_path(path)); | 391 | let path = e.path().and_then(|path| self.expander.parse_path(path)).map(Box::new); |
387 | let record_lit = if let Some(nfl) = e.record_expr_field_list() { | 392 | let record_lit = if let Some(nfl) = e.record_expr_field_list() { |
388 | let fields = nfl | 393 | let fields = nfl |
389 | .fields() | 394 | .fields() |
@@ -428,7 +433,7 @@ impl ExprCollector<'_> { | |||
428 | } | 433 | } |
429 | ast::Expr::CastExpr(e) => { | 434 | ast::Expr::CastExpr(e) => { |
430 | let expr = self.collect_expr_opt(e.expr()); | 435 | let expr = self.collect_expr_opt(e.expr()); |
431 | let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty()); | 436 | let type_ref = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty())); |
432 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) | 437 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) |
433 | } | 438 | } |
434 | ast::Expr::RefExpr(e) => { | 439 | ast::Expr::RefExpr(e) => { |
@@ -462,13 +467,16 @@ impl ExprCollector<'_> { | |||
462 | if let Some(pl) = e.param_list() { | 467 | if let Some(pl) = e.param_list() { |
463 | for param in pl.params() { | 468 | for param in pl.params() { |
464 | let pat = self.collect_pat_opt(param.pat()); | 469 | let pat = self.collect_pat_opt(param.pat()); |
465 | let type_ref = param.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); | 470 | let type_ref = |
471 | param.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it))); | ||
466 | args.push(pat); | 472 | args.push(pat); |
467 | arg_types.push(type_ref); | 473 | arg_types.push(type_ref); |
468 | } | 474 | } |
469 | } | 475 | } |
470 | let ret_type = | 476 | let ret_type = e |
471 | e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it)); | 477 | .ret_type() |
478 | .and_then(|r| r.ty()) | ||
479 | .map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it))); | ||
472 | let body = self.collect_expr_opt(e.body()); | 480 | let body = self.collect_expr_opt(e.body()); |
473 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) | 481 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) |
474 | } | 482 | } |
@@ -533,15 +541,13 @@ impl ExprCollector<'_> { | |||
533 | ids[0] | 541 | ids[0] |
534 | } | 542 | } |
535 | ast::Expr::MacroStmts(e) => { | 543 | ast::Expr::MacroStmts(e) => { |
536 | // FIXME: these statements should be held by some hir containter | 544 | e.statements().for_each(|s| self.collect_stmt(s)); |
537 | for stmt in e.statements() { | 545 | let tail = e |
538 | self.collect_stmt(stmt); | 546 | .expr() |
539 | } | 547 | .map(|e| self.collect_expr(e)) |
540 | if let Some(expr) = e.expr() { | 548 | .unwrap_or_else(|| self.alloc_expr(Expr::Missing, syntax_ptr.clone())); |
541 | self.collect_expr(expr) | 549 | |
542 | } else { | 550 | self.alloc_expr(Expr::MacroStmts { tail }, syntax_ptr) |
543 | self.alloc_expr(Expr::Missing, syntax_ptr) | ||
544 | } | ||
545 | } | 551 | } |
546 | }) | 552 | }) |
547 | } | 553 | } |
@@ -618,58 +624,55 @@ impl ExprCollector<'_> { | |||
618 | } | 624 | } |
619 | } | 625 | } |
620 | 626 | ||
621 | fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> { | 627 | fn collect_stmt(&mut self, s: ast::Stmt) { |
622 | let stmt = match s { | 628 | match s { |
623 | ast::Stmt::LetStmt(stmt) => { | 629 | ast::Stmt::LetStmt(stmt) => { |
624 | self.check_cfg(&stmt)?; | 630 | if self.check_cfg(&stmt).is_none() { |
625 | 631 | return; | |
632 | } | ||
626 | let pat = self.collect_pat_opt(stmt.pat()); | 633 | let pat = self.collect_pat_opt(stmt.pat()); |
627 | let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); | 634 | let type_ref = |
635 | stmt.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it))); | ||
628 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); | 636 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); |
629 | vec![Statement::Let { pat, type_ref, initializer }] | 637 | self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer }); |
630 | } | 638 | } |
631 | ast::Stmt::ExprStmt(stmt) => { | 639 | ast::Stmt::ExprStmt(stmt) => { |
632 | self.check_cfg(&stmt)?; | 640 | if self.check_cfg(&stmt).is_none() { |
641 | return; | ||
642 | } | ||
633 | 643 | ||
634 | // Note that macro could be expended to multiple statements | 644 | // Note that macro could be expended to multiple statements |
635 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { | 645 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { |
636 | let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); | 646 | let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); |
637 | let mut stmts = vec![]; | ||
638 | 647 | ||
639 | self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| { | 648 | self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| { |
640 | match expansion { | 649 | match expansion { |
641 | Some(expansion) => { | 650 | Some(expansion) => { |
642 | let statements: ast::MacroStmts = expansion; | 651 | let statements: ast::MacroStmts = expansion; |
643 | 652 | ||
644 | statements.statements().for_each(|stmt| { | 653 | statements.statements().for_each(|stmt| this.collect_stmt(stmt)); |
645 | if let Some(mut r) = this.collect_stmt(stmt) { | ||
646 | stmts.append(&mut r); | ||
647 | } | ||
648 | }); | ||
649 | if let Some(expr) = statements.expr() { | 654 | if let Some(expr) = statements.expr() { |
650 | stmts.push(Statement::Expr(this.collect_expr(expr))); | 655 | let expr = this.collect_expr(expr); |
656 | this.statements_in_scope.push(Statement::Expr(expr)); | ||
651 | } | 657 | } |
652 | } | 658 | } |
653 | None => { | 659 | None => { |
654 | stmts.push(Statement::Expr( | 660 | let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone()); |
655 | this.alloc_expr(Expr::Missing, syntax_ptr.clone()), | 661 | this.statements_in_scope.push(Statement::Expr(expr)); |
656 | )); | ||
657 | } | 662 | } |
658 | } | 663 | } |
659 | }); | 664 | }); |
660 | stmts | ||
661 | } else { | 665 | } else { |
662 | vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))] | 666 | let expr = self.collect_expr_opt(stmt.expr()); |
667 | self.statements_in_scope.push(Statement::Expr(expr)); | ||
663 | } | 668 | } |
664 | } | 669 | } |
665 | ast::Stmt::Item(item) => { | 670 | ast::Stmt::Item(item) => { |
666 | self.check_cfg(&item)?; | 671 | if self.check_cfg(&item).is_none() { |
667 | 672 | return; | |
668 | return None; | 673 | } |
669 | } | 674 | } |
670 | }; | 675 | } |
671 | |||
672 | Some(stmt) | ||
673 | } | 676 | } |
674 | 677 | ||
675 | fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { | 678 | fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { |
@@ -677,18 +680,22 @@ impl ExprCollector<'_> { | |||
677 | let block_loc = | 680 | let block_loc = |
678 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; | 681 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; |
679 | let block_id = self.db.intern_block(block_loc); | 682 | let block_id = self.db.intern_block(block_loc); |
680 | self.body.block_scopes.push(block_id); | ||
681 | 683 | ||
682 | let opt_def_map = self.db.block_def_map(block_id); | 684 | let (module, def_map) = match self.db.block_def_map(block_id) { |
683 | let has_def_map = opt_def_map.is_some(); | 685 | Some(def_map) => { |
684 | let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); | 686 | self.body.block_scopes.push(block_id); |
685 | let module = if has_def_map { def_map.root() } else { self.expander.module }; | 687 | (def_map.root(), def_map) |
688 | } | ||
689 | None => (self.expander.module, self.expander.def_map.clone()), | ||
690 | }; | ||
686 | let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); | 691 | let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); |
687 | let prev_local_module = mem::replace(&mut self.expander.module, module); | 692 | let prev_local_module = mem::replace(&mut self.expander.module, module); |
693 | let prev_statements = std::mem::take(&mut self.statements_in_scope); | ||
694 | |||
695 | block.statements().for_each(|s| self.collect_stmt(s)); | ||
688 | 696 | ||
689 | let statements = | ||
690 | block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); | ||
691 | let tail = block.tail_expr().map(|e| self.collect_expr(e)); | 697 | let tail = block.tail_expr().map(|e| self.collect_expr(e)); |
698 | let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements); | ||
692 | let syntax_node_ptr = AstPtr::new(&block.into()); | 699 | let syntax_node_ptr = AstPtr::new(&block.into()); |
693 | let expr_id = self.alloc_expr( | 700 | let expr_id = self.alloc_expr( |
694 | Expr::Block { id: block_id, statements, tail, label: None }, | 701 | Expr::Block { id: block_id, statements, tail, label: None }, |
@@ -755,7 +762,7 @@ impl ExprCollector<'_> { | |||
755 | } | 762 | } |
756 | } | 763 | } |
757 | ast::Pat::TupleStructPat(p) => { | 764 | ast::Pat::TupleStructPat(p) => { |
758 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 765 | let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new); |
759 | let (args, ellipsis) = self.collect_tuple_pat(p.fields()); | 766 | let (args, ellipsis) = self.collect_tuple_pat(p.fields()); |
760 | Pat::TupleStruct { path, args, ellipsis } | 767 | Pat::TupleStruct { path, args, ellipsis } |
761 | } | 768 | } |
@@ -765,7 +772,7 @@ impl ExprCollector<'_> { | |||
765 | Pat::Ref { pat, mutability } | 772 | Pat::Ref { pat, mutability } |
766 | } | 773 | } |
767 | ast::Pat::PathPat(p) => { | 774 | ast::Pat::PathPat(p) => { |
768 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 775 | let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new); |
769 | path.map(Pat::Path).unwrap_or(Pat::Missing) | 776 | path.map(Pat::Path).unwrap_or(Pat::Missing) |
770 | } | 777 | } |
771 | ast::Pat::OrPat(p) => { | 778 | ast::Pat::OrPat(p) => { |
@@ -779,7 +786,7 @@ impl ExprCollector<'_> { | |||
779 | } | 786 | } |
780 | ast::Pat::WildcardPat(_) => Pat::Wild, | 787 | ast::Pat::WildcardPat(_) => Pat::Wild, |
781 | ast::Pat::RecordPat(p) => { | 788 | ast::Pat::RecordPat(p) => { |
782 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 789 | let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new); |
783 | let args: Vec<_> = p | 790 | let args: Vec<_> = p |
784 | .record_pat_field_list() | 791 | .record_pat_field_list() |
785 | .expect("every struct should have a field list") | 792 | .expect("every struct should have a field list") |
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs index faa133297..c1d3e998f 100644 --- a/crates/hir_def/src/body/tests.rs +++ b/crates/hir_def/src/body/tests.rs | |||
@@ -143,7 +143,7 @@ fn f() { | |||
143 | //^^^^^^^^^^^^^ could not convert tokens | 143 | //^^^^^^^^^^^^^ could not convert tokens |
144 | 144 | ||
145 | env!("OUT_DIR"); | 145 | env!("OUT_DIR"); |
146 | //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "load out dirs from check" to fix | 146 | //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix |
147 | 147 | ||
148 | compile_error!("compile_error works"); | 148 | compile_error!("compile_error works"); |
149 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works | 149 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works |