aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/body/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/body/lower.rs')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs163
1 files changed, 87 insertions, 76 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index c6bc85e2f..f5c37edb3 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -1,6 +1,8 @@
1//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr` 1//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
2//! representation. 2//! representation.
3 3
4use std::{any::type_name, sync::Arc};
5
4use either::Either; 6use either::Either;
5use hir_expand::{ 7use hir_expand::{
6 hygiene::Hygiene, 8 hygiene::Hygiene,
@@ -10,11 +12,12 @@ use hir_expand::{
10use ra_arena::Arena; 12use ra_arena::Arena;
11use ra_syntax::{ 13use ra_syntax::{
12 ast::{ 14 ast::{
13 self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner, 15 self, ArgListOwner, ArrayExprKind, AstChildren, LiteralKind, LoopBodyOwner, NameOwner,
14 SlicePatComponents, TypeAscriptionOwner, 16 SlicePatComponents,
15 }, 17 },
16 AstNode, AstPtr, 18 AstNode, AstPtr,
17}; 19};
20use rustc_hash::FxHashMap;
18use test_utils::mark; 21use test_utils::mark;
19 22
20use crate::{ 23use crate::{
@@ -35,9 +38,6 @@ use crate::{
35}; 38};
36 39
37use super::{ExprSource, PatSource}; 40use super::{ExprSource, PatSource};
38use ast::AstChildren;
39use rustc_hash::FxHashMap;
40use std::{any::type_name, sync::Arc};
41 41
42pub(crate) struct LowerCtx { 42pub(crate) struct LowerCtx {
43 hygiene: Hygiene, 43 hygiene: Hygiene,
@@ -224,9 +224,22 @@ impl ExprCollector<'_> {
224 self.alloc_expr(Expr::Unsafe { body }, syntax_ptr) 224 self.alloc_expr(Expr::Unsafe { body }, syntax_ptr)
225 } 225 }
226 // FIXME: we need to record these effects somewhere... 226 // FIXME: we need to record these effects somewhere...
227 ast::Effect::Async(_) | ast::Effect::Label(_) => { 227 ast::Effect::Label(label) => match e.block_expr() {
228 self.collect_block_opt(e.block_expr()) 228 Some(block) => {
229 } 229 let res = self.collect_block(block);
230 match &mut self.body.exprs[res] {
231 Expr::Block { label: block_label, .. } => {
232 *block_label =
233 label.lifetime_token().map(|t| Name::new_lifetime(&t))
234 }
235 _ => unreachable!(),
236 }
237 res
238 }
239 None => self.missing_expr(),
240 },
241 // FIXME: we need to record these effects somewhere...
242 ast::Effect::Async(_) => self.collect_block_opt(e.block_expr()),
230 }, 243 },
231 ast::Expr::BlockExpr(e) => self.collect_block(e), 244 ast::Expr::BlockExpr(e) => self.collect_block(e),
232 ast::Expr::LoopExpr(e) => { 245 ast::Expr::LoopExpr(e) => {
@@ -324,7 +337,7 @@ impl ExprCollector<'_> {
324 }; 337 };
325 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 338 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
326 let generic_args = 339 let generic_args =
327 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); 340 e.generic_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
328 self.alloc_expr( 341 self.alloc_expr(
329 Expr::MethodCall { receiver, method_name, args, generic_args }, 342 Expr::MethodCall { receiver, method_name, args, generic_args },
330 syntax_ptr, 343 syntax_ptr,
@@ -379,10 +392,10 @@ impl ExprCollector<'_> {
379 let expr = e.expr().map(|e| self.collect_expr(e)); 392 let expr = e.expr().map(|e| self.collect_expr(e));
380 self.alloc_expr(Expr::Return { expr }, syntax_ptr) 393 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
381 } 394 }
382 ast::Expr::RecordLit(e) => { 395 ast::Expr::RecordExpr(e) => {
383 let path = e.path().and_then(|path| self.expander.parse_path(path)); 396 let path = e.path().and_then(|path| self.expander.parse_path(path));
384 let mut field_ptrs = Vec::new(); 397 let mut field_ptrs = Vec::new();
385 let record_lit = if let Some(nfl) = e.record_field_list() { 398 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
386 let fields = nfl 399 let fields = nfl
387 .fields() 400 .fields()
388 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 401 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
@@ -432,7 +445,7 @@ impl ExprCollector<'_> {
432 } 445 }
433 ast::Expr::CastExpr(e) => { 446 ast::Expr::CastExpr(e) => {
434 let expr = self.collect_expr_opt(e.expr()); 447 let expr = self.collect_expr_opt(e.expr());
435 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref()); 448 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty());
436 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 449 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
437 } 450 }
438 ast::Expr::RefExpr(e) => { 451 ast::Expr::RefExpr(e) => {
@@ -460,22 +473,19 @@ impl ExprCollector<'_> {
460 self.alloc_expr(Expr::Missing, syntax_ptr) 473 self.alloc_expr(Expr::Missing, syntax_ptr)
461 } 474 }
462 } 475 }
463 ast::Expr::LambdaExpr(e) => { 476 ast::Expr::ClosureExpr(e) => {
464 let mut args = Vec::new(); 477 let mut args = Vec::new();
465 let mut arg_types = Vec::new(); 478 let mut arg_types = Vec::new();
466 if let Some(pl) = e.param_list() { 479 if let Some(pl) = e.param_list() {
467 for param in pl.params() { 480 for param in pl.params() {
468 let pat = self.collect_pat_opt(param.pat()); 481 let pat = self.collect_pat_opt(param.pat());
469 let type_ref = 482 let type_ref = param.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
470 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
471 args.push(pat); 483 args.push(pat);
472 arg_types.push(type_ref); 484 arg_types.push(type_ref);
473 } 485 }
474 } 486 }
475 let ret_type = e 487 let ret_type =
476 .ret_type() 488 e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it));
477 .and_then(|r| r.type_ref())
478 .map(|it| TypeRef::from_ast(&self.ctx(), it));
479 let body = self.collect_expr_opt(e.body()); 489 let body = self.collect_expr_opt(e.body());
480 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 490 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
481 } 491 }
@@ -486,7 +496,7 @@ impl ExprCollector<'_> {
486 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr) 496 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
487 } 497 }
488 ast::Expr::TupleExpr(e) => { 498 ast::Expr::TupleExpr(e) => {
489 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); 499 let exprs = e.fields().map(|expr| self.collect_expr(expr)).collect();
490 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr) 500 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
491 } 501 }
492 ast::Expr::BoxExpr(e) => { 502 ast::Expr::BoxExpr(e) => {
@@ -559,9 +569,6 @@ impl ExprCollector<'_> {
559 } 569 }
560 } 570 }
561 } 571 }
562
563 // FIXME implement HIR for these:
564 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
565 } 572 }
566 } 573 }
567 574
@@ -604,76 +611,84 @@ impl ExprCollector<'_> {
604 self.collect_block_items(&block); 611 self.collect_block_items(&block);
605 let statements = block 612 let statements = block
606 .statements() 613 .statements()
607 .map(|s| match s { 614 .filter_map(|s| {
608 ast::Stmt::LetStmt(stmt) => { 615 let stmt = match s {
609 let pat = self.collect_pat_opt(stmt.pat()); 616 ast::Stmt::LetStmt(stmt) => {
610 let type_ref = 617 let pat = self.collect_pat_opt(stmt.pat());
611 stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it)); 618 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
612 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 619 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
613 Statement::Let { pat, type_ref, initializer } 620 Statement::Let { pat, type_ref, initializer }
614 } 621 }
615 ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())), 622 ast::Stmt::ExprStmt(stmt) => {
623 Statement::Expr(self.collect_expr_opt(stmt.expr()))
624 }
625 ast::Stmt::Item(_) => return None,
626 };
627 Some(stmt)
616 }) 628 })
617 .collect(); 629 .collect();
618 let tail = block.expr().map(|e| self.collect_expr(e)); 630 let tail = block.expr().map(|e| self.collect_expr(e));
619 let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t)); 631 self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr)
620 self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr)
621 } 632 }
622 633
623 fn collect_block_items(&mut self, block: &ast::BlockExpr) { 634 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
624 let container = ContainerId::DefWithBodyId(self.def); 635 let container = ContainerId::DefWithBodyId(self.def);
625 636
626 let items = block 637 let items = block
627 .items() 638 .statements()
639 .filter_map(|stmt| match stmt {
640 ast::Stmt::Item(it) => Some(it),
641 ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None,
642 })
628 .filter_map(|item| { 643 .filter_map(|item| {
629 let (def, name): (ModuleDefId, Option<ast::Name>) = match item { 644 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
630 ast::ModuleItem::FnDef(def) => { 645 ast::Item::Fn(def) => {
631 let id = self.find_inner_item(&def)?; 646 let id = self.find_inner_item(&def)?;
632 ( 647 (
633 FunctionLoc { container: container.into(), id }.intern(self.db).into(), 648 FunctionLoc { container: container.into(), id }.intern(self.db).into(),
634 def.name(), 649 def.name(),
635 ) 650 )
636 } 651 }
637 ast::ModuleItem::TypeAliasDef(def) => { 652 ast::Item::TypeAlias(def) => {
638 let id = self.find_inner_item(&def)?; 653 let id = self.find_inner_item(&def)?;
639 ( 654 (
640 TypeAliasLoc { container: container.into(), id }.intern(self.db).into(), 655 TypeAliasLoc { container: container.into(), id }.intern(self.db).into(),
641 def.name(), 656 def.name(),
642 ) 657 )
643 } 658 }
644 ast::ModuleItem::ConstDef(def) => { 659 ast::Item::Const(def) => {
645 let id = self.find_inner_item(&def)?; 660 let id = self.find_inner_item(&def)?;
646 ( 661 (
647 ConstLoc { container: container.into(), id }.intern(self.db).into(), 662 ConstLoc { container: container.into(), id }.intern(self.db).into(),
648 def.name(), 663 def.name(),
649 ) 664 )
650 } 665 }
651 ast::ModuleItem::StaticDef(def) => { 666 ast::Item::Static(def) => {
652 let id = self.find_inner_item(&def)?; 667 let id = self.find_inner_item(&def)?;
653 (StaticLoc { container, id }.intern(self.db).into(), def.name()) 668 (StaticLoc { container, id }.intern(self.db).into(), def.name())
654 } 669 }
655 ast::ModuleItem::StructDef(def) => { 670 ast::Item::Struct(def) => {
656 let id = self.find_inner_item(&def)?; 671 let id = self.find_inner_item(&def)?;
657 (StructLoc { container, id }.intern(self.db).into(), def.name()) 672 (StructLoc { container, id }.intern(self.db).into(), def.name())
658 } 673 }
659 ast::ModuleItem::EnumDef(def) => { 674 ast::Item::Enum(def) => {
660 let id = self.find_inner_item(&def)?; 675 let id = self.find_inner_item(&def)?;
661 (EnumLoc { container, id }.intern(self.db).into(), def.name()) 676 (EnumLoc { container, id }.intern(self.db).into(), def.name())
662 } 677 }
663 ast::ModuleItem::UnionDef(def) => { 678 ast::Item::Union(def) => {
664 let id = self.find_inner_item(&def)?; 679 let id = self.find_inner_item(&def)?;
665 (UnionLoc { container, id }.intern(self.db).into(), def.name()) 680 (UnionLoc { container, id }.intern(self.db).into(), def.name())
666 } 681 }
667 ast::ModuleItem::TraitDef(def) => { 682 ast::Item::Trait(def) => {
668 let id = self.find_inner_item(&def)?; 683 let id = self.find_inner_item(&def)?;
669 (TraitLoc { container, id }.intern(self.db).into(), def.name()) 684 (TraitLoc { container, id }.intern(self.db).into(), def.name())
670 } 685 }
671 ast::ModuleItem::ExternBlock(_) => return None, // FIXME: collect from extern blocks 686 ast::Item::ExternBlock(_) => return None, // FIXME: collect from extern blocks
672 ast::ModuleItem::ImplDef(_) 687 ast::Item::Impl(_)
673 | ast::ModuleItem::UseItem(_) 688 | ast::Item::Use(_)
674 | ast::ModuleItem::ExternCrateItem(_) 689 | ast::Item::ExternCrate(_)
675 | ast::ModuleItem::Module(_) 690 | ast::Item::Module(_)
676 | ast::ModuleItem::MacroCall(_) => return None, 691 | ast::Item::MacroCall(_) => return None,
677 }; 692 };
678 693
679 Some((def, name)) 694 Some((def, name))
@@ -708,7 +723,7 @@ impl ExprCollector<'_> {
708 723
709 fn collect_pat(&mut self, pat: ast::Pat) -> PatId { 724 fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
710 let pattern = match &pat { 725 let pattern = match &pat {
711 ast::Pat::BindPat(bp) => { 726 ast::Pat::IdentPat(bp) => {
712 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 727 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
713 let annotation = 728 let annotation =
714 BindingAnnotation::new(bp.mut_token().is_some(), bp.ref_token().is_some()); 729 BindingAnnotation::new(bp.mut_token().is_some(), bp.ref_token().is_some());
@@ -747,7 +762,7 @@ impl ExprCollector<'_> {
747 } 762 }
748 ast::Pat::TupleStructPat(p) => { 763 ast::Pat::TupleStructPat(p) => {
749 let path = p.path().and_then(|path| self.expander.parse_path(path)); 764 let path = p.path().and_then(|path| self.expander.parse_path(path));
750 let (args, ellipsis) = self.collect_tuple_pat(p.args()); 765 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
751 Pat::TupleStruct { path, args, ellipsis } 766 Pat::TupleStruct { path, args, ellipsis }
752 } 767 }
753 ast::Pat::RefPat(p) => { 768 ast::Pat::RefPat(p) => {
@@ -765,40 +780,36 @@ impl ExprCollector<'_> {
765 } 780 }
766 ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), 781 ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()),
767 ast::Pat::TuplePat(p) => { 782 ast::Pat::TuplePat(p) => {
768 let (args, ellipsis) = self.collect_tuple_pat(p.args()); 783 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
769 Pat::Tuple { args, ellipsis } 784 Pat::Tuple { args, ellipsis }
770 } 785 }
771 ast::Pat::PlaceholderPat(_) => Pat::Wild, 786 ast::Pat::WildcardPat(_) => Pat::Wild,
772 ast::Pat::RecordPat(p) => { 787 ast::Pat::RecordPat(p) => {
773 let path = p.path().and_then(|path| self.expander.parse_path(path)); 788 let path = p.path().and_then(|path| self.expander.parse_path(path));
774 let record_field_pat_list = 789 let args: Vec<_> = p
775 p.record_field_pat_list().expect("every struct should have a field list"); 790 .record_pat_field_list()
776 let mut fields: Vec<_> = record_field_pat_list 791 .expect("every struct should have a field list")
777 .bind_pats() 792 .fields()
778 .filter_map(|bind_pat| { 793 .filter_map(|f| {
779 let ast_pat = 794 let ast_pat = f.pat()?;
780 ast::Pat::cast(bind_pat.syntax().clone()).expect("bind pat is a pat");
781 let pat = self.collect_pat(ast_pat); 795 let pat = self.collect_pat(ast_pat);
782 let name = bind_pat.name()?.as_name(); 796 let name = f.field_name()?.as_name();
783 Some(RecordFieldPat { name, pat }) 797 Some(RecordFieldPat { name, pat })
784 }) 798 })
785 .collect(); 799 .collect();
786 let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
787 let ast_pat = f.pat()?;
788 let pat = self.collect_pat(ast_pat);
789 let name = f.field_name()?.as_name();
790 Some(RecordFieldPat { name, pat })
791 });
792 fields.extend(iter);
793 800
794 let ellipsis = record_field_pat_list.dotdot_token().is_some(); 801 let ellipsis = p
802 .record_pat_field_list()
803 .expect("every struct should have a field list")
804 .dotdot_token()
805 .is_some();
795 806
796 Pat::Record { path, args: fields, ellipsis } 807 Pat::Record { path, args, ellipsis }
797 } 808 }
798 ast::Pat::SlicePat(p) => { 809 ast::Pat::SlicePat(p) => {
799 let SlicePatComponents { prefix, slice, suffix } = p.components(); 810 let SlicePatComponents { prefix, slice, suffix } = p.components();
800 811
801 // FIXME properly handle `DotDotPat` 812 // FIXME properly handle `RestPat`
802 Pat::Slice { 813 Pat::Slice {
803 prefix: prefix.into_iter().map(|p| self.collect_pat(p)).collect(), 814 prefix: prefix.into_iter().map(|p| self.collect_pat(p)).collect(),
804 slice: slice.map(|p| self.collect_pat(p)), 815 slice: slice.map(|p| self.collect_pat(p)),
@@ -815,10 +826,10 @@ impl ExprCollector<'_> {
815 Pat::Missing 826 Pat::Missing
816 } 827 }
817 } 828 }
818 ast::Pat::DotDotPat(_) => { 829 ast::Pat::RestPat(_) => {
819 // `DotDotPat` requires special handling and should not be mapped 830 // `RestPat` requires special handling and should not be mapped
820 // to a Pat. Here we are using `Pat::Missing` as a fallback for 831 // to a Pat. Here we are using `Pat::Missing` as a fallback for
821 // when `DotDotPat` is mapped to `Pat`, which can easily happen 832 // when `RestPat` is mapped to `Pat`, which can easily happen
822 // when the source code being analyzed has a malformed pattern 833 // when the source code being analyzed has a malformed pattern
823 // which includes `..` in a place where it isn't valid. 834 // which includes `..` in a place where it isn't valid.
824 835
@@ -842,10 +853,10 @@ impl ExprCollector<'_> {
842 fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) { 853 fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) {
843 // Find the location of the `..`, if there is one. Note that we do not 854 // Find the location of the `..`, if there is one. Note that we do not
844 // consider the possiblity of there being multiple `..` here. 855 // consider the possiblity of there being multiple `..` here.
845 let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::DotDotPat(_))); 856 let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_)));
846 // We want to skip the `..` pattern here, since we account for it above. 857 // We want to skip the `..` pattern here, since we account for it above.
847 let args = args 858 let args = args
848 .filter(|p| !matches!(p, ast::Pat::DotDotPat(_))) 859 .filter(|p| !matches!(p, ast::Pat::RestPat(_)))
849 .map(|p| self.collect_pat(p)) 860 .map(|p| self.collect_pat(p))
850 .collect(); 861 .collect();
851 862