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.rs117
1 files changed, 66 insertions, 51 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 827ced4ad..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, 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,
@@ -460,7 +473,7 @@ 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() {
@@ -483,7 +496,7 @@ impl ExprCollector<'_> {
483 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr) 496 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
484 } 497 }
485 ast::Expr::TupleExpr(e) => { 498 ast::Expr::TupleExpr(e) => {
486 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); 499 let exprs = e.fields().map(|expr| self.collect_expr(expr)).collect();
487 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr) 500 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
488 } 501 }
489 ast::Expr::BoxExpr(e) => { 502 ast::Expr::BoxExpr(e) => {
@@ -556,9 +569,6 @@ impl ExprCollector<'_> {
556 } 569 }
557 } 570 }
558 } 571 }
559
560 // FIXME implement HIR for these:
561 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
562 } 572 }
563 } 573 }
564 574
@@ -601,26 +611,35 @@ impl ExprCollector<'_> {
601 self.collect_block_items(&block); 611 self.collect_block_items(&block);
602 let statements = block 612 let statements = block
603 .statements() 613 .statements()
604 .map(|s| match s { 614 .filter_map(|s| {
605 ast::Stmt::LetStmt(stmt) => { 615 let stmt = match s {
606 let pat = self.collect_pat_opt(stmt.pat()); 616 ast::Stmt::LetStmt(stmt) => {
607 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 617 let pat = self.collect_pat_opt(stmt.pat());
608 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 618 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
609 Statement::Let { pat, type_ref, initializer } 619 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
610 } 620 Statement::Let { pat, type_ref, initializer }
611 ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())), 621 }
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)
612 }) 628 })
613 .collect(); 629 .collect();
614 let tail = block.expr().map(|e| self.collect_expr(e)); 630 let tail = block.expr().map(|e| self.collect_expr(e));
615 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)
616 self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr)
617 } 632 }
618 633
619 fn collect_block_items(&mut self, block: &ast::BlockExpr) { 634 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
620 let container = ContainerId::DefWithBodyId(self.def); 635 let container = ContainerId::DefWithBodyId(self.def);
621 636
622 let items = block 637 let items = block
623 .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 })
624 .filter_map(|item| { 643 .filter_map(|item| {
625 let (def, name): (ModuleDefId, Option<ast::Name>) = match item { 644 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
626 ast::Item::Fn(def) => { 645 ast::Item::Fn(def) => {
@@ -704,7 +723,7 @@ impl ExprCollector<'_> {
704 723
705 fn collect_pat(&mut self, pat: ast::Pat) -> PatId { 724 fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
706 let pattern = match &pat { 725 let pattern = match &pat {
707 ast::Pat::BindPat(bp) => { 726 ast::Pat::IdentPat(bp) => {
708 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);
709 let annotation = 728 let annotation =
710 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());
@@ -743,7 +762,7 @@ impl ExprCollector<'_> {
743 } 762 }
744 ast::Pat::TupleStructPat(p) => { 763 ast::Pat::TupleStructPat(p) => {
745 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));
746 let (args, ellipsis) = self.collect_tuple_pat(p.args()); 765 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
747 Pat::TupleStruct { path, args, ellipsis } 766 Pat::TupleStruct { path, args, ellipsis }
748 } 767 }
749 ast::Pat::RefPat(p) => { 768 ast::Pat::RefPat(p) => {
@@ -761,40 +780,36 @@ impl ExprCollector<'_> {
761 } 780 }
762 ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), 781 ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()),
763 ast::Pat::TuplePat(p) => { 782 ast::Pat::TuplePat(p) => {
764 let (args, ellipsis) = self.collect_tuple_pat(p.args()); 783 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
765 Pat::Tuple { args, ellipsis } 784 Pat::Tuple { args, ellipsis }
766 } 785 }
767 ast::Pat::PlaceholderPat(_) => Pat::Wild, 786 ast::Pat::WildcardPat(_) => Pat::Wild,
768 ast::Pat::RecordPat(p) => { 787 ast::Pat::RecordPat(p) => {
769 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));
770 let record_field_pat_list = 789 let args: Vec<_> = p
771 p.record_field_pat_list().expect("every struct should have a field list"); 790 .record_pat_field_list()
772 let mut fields: Vec<_> = record_field_pat_list 791 .expect("every struct should have a field list")
773 .bind_pats() 792 .fields()
774 .filter_map(|bind_pat| { 793 .filter_map(|f| {
775 let ast_pat = 794 let ast_pat = f.pat()?;
776 ast::Pat::cast(bind_pat.syntax().clone()).expect("bind pat is a pat");
777 let pat = self.collect_pat(ast_pat); 795 let pat = self.collect_pat(ast_pat);
778 let name = bind_pat.name()?.as_name(); 796 let name = f.field_name()?.as_name();
779 Some(RecordFieldPat { name, pat }) 797 Some(RecordFieldPat { name, pat })
780 }) 798 })
781 .collect(); 799 .collect();
782 let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
783 let ast_pat = f.pat()?;
784 let pat = self.collect_pat(ast_pat);
785 let name = f.field_name()?.as_name();
786 Some(RecordFieldPat { name, pat })
787 });
788 fields.extend(iter);
789 800
790 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();
791 806
792 Pat::Record { path, args: fields, ellipsis } 807 Pat::Record { path, args, ellipsis }
793 } 808 }
794 ast::Pat::SlicePat(p) => { 809 ast::Pat::SlicePat(p) => {
795 let SlicePatComponents { prefix, slice, suffix } = p.components(); 810 let SlicePatComponents { prefix, slice, suffix } = p.components();
796 811
797 // FIXME properly handle `DotDotPat` 812 // FIXME properly handle `RestPat`
798 Pat::Slice { 813 Pat::Slice {
799 prefix: prefix.into_iter().map(|p| self.collect_pat(p)).collect(), 814 prefix: prefix.into_iter().map(|p| self.collect_pat(p)).collect(),
800 slice: slice.map(|p| self.collect_pat(p)), 815 slice: slice.map(|p| self.collect_pat(p)),
@@ -811,10 +826,10 @@ impl ExprCollector<'_> {
811 Pat::Missing 826 Pat::Missing
812 } 827 }
813 } 828 }
814 ast::Pat::DotDotPat(_) => { 829 ast::Pat::RestPat(_) => {
815 // `DotDotPat` requires special handling and should not be mapped 830 // `RestPat` requires special handling and should not be mapped
816 // 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
817 // when `DotDotPat` is mapped to `Pat`, which can easily happen 832 // when `RestPat` is mapped to `Pat`, which can easily happen
818 // when the source code being analyzed has a malformed pattern 833 // when the source code being analyzed has a malformed pattern
819 // which includes `..` in a place where it isn't valid. 834 // which includes `..` in a place where it isn't valid.
820 835
@@ -838,10 +853,10 @@ impl ExprCollector<'_> {
838 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>) {
839 // 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
840 // consider the possiblity of there being multiple `..` here. 855 // consider the possiblity of there being multiple `..` here.
841 let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::DotDotPat(_))); 856 let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_)));
842 // 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.
843 let args = args 858 let args = args
844 .filter(|p| !matches!(p, ast::Pat::DotDotPat(_))) 859 .filter(|p| !matches!(p, ast::Pat::RestPat(_)))
845 .map(|p| self.collect_pat(p)) 860 .map(|p| self.collect_pat(p))
846 .collect(); 861 .collect();
847 862