diff options
Diffstat (limited to 'crates/ra_hir_def/src/body/lower.rs')
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 117 |
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 | ||
4 | use std::{any::type_name, sync::Arc}; | ||
5 | |||
4 | use either::Either; | 6 | use either::Either; |
5 | use hir_expand::{ | 7 | use hir_expand::{ |
6 | hygiene::Hygiene, | 8 | hygiene::Hygiene, |
@@ -10,11 +12,12 @@ use hir_expand::{ | |||
10 | use ra_arena::Arena; | 12 | use ra_arena::Arena; |
11 | use ra_syntax::{ | 13 | use 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 | }; |
20 | use rustc_hash::FxHashMap; | ||
18 | use test_utils::mark; | 21 | use test_utils::mark; |
19 | 22 | ||
20 | use crate::{ | 23 | use crate::{ |
@@ -35,9 +38,6 @@ use crate::{ | |||
35 | }; | 38 | }; |
36 | 39 | ||
37 | use super::{ExprSource, PatSource}; | 40 | use super::{ExprSource, PatSource}; |
38 | use ast::AstChildren; | ||
39 | use rustc_hash::FxHashMap; | ||
40 | use std::{any::type_name, sync::Arc}; | ||
41 | 41 | ||
42 | pub(crate) struct LowerCtx { | 42 | pub(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 | ||