aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/expr.rs')
-rw-r--r--crates/ra_hir/src/expr.rs693
1 files changed, 47 insertions, 646 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 7cdc7555c..fc21e269f 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -1,36 +1,30 @@
1use std::ops::Index; 1pub(crate) mod lower;
2use std::sync::Arc; 2pub(crate) mod scope;
3pub(crate) mod validation;
3 4
4use rustc_hash::FxHashMap; 5use std::{ops::Index, sync::Arc};
5 6
6use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 7use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
7use ra_syntax::{ 8use ra_syntax::{ast, AstPtr};
8 ast::{ 9use rustc_hash::FxHashMap;
9 self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner,
10 TryBlockBodyOwner, TypeAscriptionOwner,
11 },
12 AstNode, AstPtr, SyntaxNodePtr,
13};
14use test_utils::tested_by;
15 10
16use crate::{ 11use crate::{
17 name::{AsName, SELF_PARAM},
18 path::GenericArgs, 12 path::GenericArgs,
19 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy}, 13 ty::primitive::{UncertainFloatTy, UncertainIntTy},
20 type_ref::{Mutability, TypeRef}, 14 type_ref::{Mutability, TypeRef},
21 DefWithBody, Either, HasSource, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind, Name, 15 DefWithBody, Either, HasSource, HirDatabase, Name, Path, Resolver, Source,
22 Path, Resolver,
23}; 16};
24 17
25pub use self::scope::ExprScopes; 18pub use self::scope::ExprScopes;
26 19
27pub(crate) mod scope;
28pub(crate) mod validation;
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 20#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
31pub struct ExprId(RawId); 21pub struct ExprId(RawId);
32impl_arena_id!(ExprId); 22impl_arena_id!(ExprId);
33 23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
25pub struct PatId(RawId);
26impl_arena_id!(PatId);
27
34/// The body of an item (function, const etc.). 28/// The body of an item (function, const etc.).
35#[derive(Debug, Eq, PartialEq)] 29#[derive(Debug, Eq, PartialEq)]
36pub struct Body { 30pub struct Body {
@@ -49,22 +43,32 @@ pub struct Body {
49 body_expr: ExprId, 43 body_expr: ExprId,
50} 44}
51 45
46type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>;
47type ExprSource = Source<ExprPtr>;
48
49type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
50type PatSource = Source<PatPtr>;
51
52/// An item body together with the mapping from syntax nodes to HIR expression 52/// An item body together with the mapping from syntax nodes to HIR expression
53/// IDs. This is needed to go from e.g. a position in a file to the HIR 53/// IDs. This is needed to go from e.g. a position in a file to the HIR
54/// expression containing it; but for type inference etc., we want to operate on 54/// expression containing it; but for type inference etc., we want to operate on
55/// a structure that is agnostic to the actual positions of expressions in the 55/// a structure that is agnostic to the actual positions of expressions in the
56/// file, so that we don't recompute types whenever some whitespace is typed. 56/// file, so that we don't recompute types whenever some whitespace is typed.
57///
58/// One complication here is that, due to macro expansion, a single `Body` might
59/// be spread across several files. So, for each ExprId and PatId, we record
60/// both the HirFileId and the position inside the file. However, we only store
61/// AST -> ExprId mapping for non-macro files, as it is not clear how to handle
62/// this properly for macros.
57#[derive(Default, Debug, Eq, PartialEq)] 63#[derive(Default, Debug, Eq, PartialEq)]
58pub struct BodySourceMap { 64pub struct BodySourceMap {
59 expr_map: FxHashMap<SyntaxNodePtr, ExprId>, 65 expr_map: FxHashMap<ExprPtr, ExprId>,
60 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>, 66 expr_map_back: ArenaMap<ExprId, ExprSource>,
61 pat_map: FxHashMap<PatPtr, PatId>, 67 pat_map: FxHashMap<PatPtr, PatId>,
62 pat_map_back: ArenaMap<PatId, PatPtr>, 68 pat_map_back: ArenaMap<PatId, PatSource>,
63 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>, 69 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>,
64} 70}
65 71
66type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
67
68impl Body { 72impl Body {
69 pub fn params(&self) -> &[PatId] { 73 pub fn params(&self) -> &[PatId] {
70 &self.params 74 &self.params
@@ -128,20 +132,16 @@ impl Index<PatId> for Body {
128} 132}
129 133
130impl BodySourceMap { 134impl BodySourceMap {
131 pub(crate) fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> { 135 pub(crate) fn expr_syntax(&self, expr: ExprId) -> Option<ExprSource> {
132 self.expr_map_back.get(expr).cloned() 136 self.expr_map_back.get(expr).copied()
133 }
134
135 pub(crate) fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> {
136 self.expr_map.get(&ptr).cloned()
137 } 137 }
138 138
139 pub(crate) fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> { 139 pub(crate) fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> {
140 self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned() 140 self.expr_map.get(&Either::A(AstPtr::new(node))).cloned()
141 } 141 }
142 142
143 pub(crate) fn pat_syntax(&self, pat: PatId) -> Option<PatPtr> { 143 pub(crate) fn pat_syntax(&self, pat: PatId) -> Option<PatSource> {
144 self.pat_map_back.get(pat).cloned() 144 self.pat_map_back.get(pat).copied()
145 } 145 }
146 146
147 pub(crate) fn node_pat(&self, node: &ast::Pat) -> Option<PatId> { 147 pub(crate) fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
@@ -436,10 +436,6 @@ impl Expr {
436 } 436 }
437} 437}
438 438
439#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
440pub struct PatId(RawId);
441impl_arena_id!(PatId);
442
443/// Explicit binding annotations given in the HIR for a binding. Note 439/// Explicit binding annotations given in the HIR for a binding. Note
444/// that this is not the final binding *mode* that we infer after type 440/// that this is not the final binding *mode* that we infer after type
445/// inference. 441/// inference.
@@ -485,7 +481,7 @@ pub enum Pat {
485 Missing, 481 Missing,
486 Wild, 482 Wild,
487 Tuple(Vec<PatId>), 483 Tuple(Vec<PatId>),
488 Struct { 484 Record {
489 path: Option<Path>, 485 path: Option<Path>,
490 args: Vec<RecordFieldPat>, 486 args: Vec<RecordFieldPat>,
491 // FIXME: 'ellipsis' option 487 // FIXME: 'ellipsis' option
@@ -531,7 +527,7 @@ impl Pat {
531 let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter()); 527 let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter());
532 total_iter.copied().for_each(f); 528 total_iter.copied().for_each(f);
533 } 529 }
534 Pat::Struct { args, .. } => { 530 Pat::Record { args, .. } => {
535 args.iter().map(|f| f.pat).for_each(f); 531 args.iter().map(|f| f.pat).for_each(f);
536 } 532 }
537 } 533 }
@@ -539,624 +535,29 @@ impl Pat {
539} 535}
540 536
541// Queries 537// Queries
542
543pub(crate) struct ExprCollector<DB> {
544 db: DB,
545 owner: DefWithBody,
546 exprs: Arena<ExprId, Expr>,
547 pats: Arena<PatId, Pat>,
548 source_map: BodySourceMap,
549 params: Vec<PatId>,
550 body_expr: Option<ExprId>,
551 resolver: Resolver,
552 // Expr collector expands macros along the way. original points to the file
553 // we started with, current points to the current macro expansion. source
554 // maps don't support macros yet, so we only record info into source map if
555 // current == original (see #1196)
556 original_file_id: HirFileId,
557 current_file_id: HirFileId,
558}
559
560impl<'a, DB> ExprCollector<&'a DB>
561where
562 DB: HirDatabase,
563{
564 fn new(owner: DefWithBody, file_id: HirFileId, resolver: Resolver, db: &'a DB) -> Self {
565 ExprCollector {
566 owner,
567 resolver,
568 db,
569 exprs: Arena::default(),
570 pats: Arena::default(),
571 source_map: BodySourceMap::default(),
572 params: Vec::new(),
573 body_expr: None,
574 original_file_id: file_id,
575 current_file_id: file_id,
576 }
577 }
578 fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId {
579 let id = self.exprs.alloc(expr);
580 if self.current_file_id == self.original_file_id {
581 self.source_map.expr_map.insert(syntax_ptr, id);
582 self.source_map.expr_map_back.insert(id, syntax_ptr);
583 }
584 id
585 }
586
587 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
588 let id = self.pats.alloc(pat);
589
590 if self.current_file_id == self.original_file_id {
591 self.source_map.pat_map.insert(ptr, id);
592 self.source_map.pat_map_back.insert(id, ptr);
593 }
594
595 id
596 }
597
598 fn empty_block(&mut self) -> ExprId {
599 let block = Expr::Block { statements: Vec::new(), tail: None };
600 self.exprs.alloc(block)
601 }
602
603 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
604 let syntax_ptr = SyntaxNodePtr::new(expr.syntax());
605 match expr {
606 ast::Expr::IfExpr(e) => {
607 let then_branch = self.collect_block_opt(e.then_branch());
608
609 let else_branch = e.else_branch().map(|b| match b {
610 ast::ElseBranch::Block(it) => self.collect_block(it),
611 ast::ElseBranch::IfExpr(elif) => {
612 let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap();
613 self.collect_expr(expr)
614 }
615 });
616
617 let condition = match e.condition() {
618 None => self.exprs.alloc(Expr::Missing),
619 Some(condition) => match condition.pat() {
620 None => self.collect_expr_opt(condition.expr()),
621 // if let -- desugar to match
622 Some(pat) => {
623 let pat = self.collect_pat(pat);
624 let match_expr = self.collect_expr_opt(condition.expr());
625 let placeholder_pat = self.pats.alloc(Pat::Missing);
626 let arms = vec![
627 MatchArm { pats: vec![pat], expr: then_branch, guard: None },
628 MatchArm {
629 pats: vec![placeholder_pat],
630 expr: else_branch.unwrap_or_else(|| self.empty_block()),
631 guard: None,
632 },
633 ];
634 return self
635 .alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr);
636 }
637 },
638 };
639
640 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
641 }
642 ast::Expr::TryBlockExpr(e) => {
643 let body = self.collect_block_opt(e.try_body());
644 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
645 }
646 ast::Expr::BlockExpr(e) => self.collect_block_opt(e.block()),
647 ast::Expr::LoopExpr(e) => {
648 let body = self.collect_block_opt(e.loop_body());
649 self.alloc_expr(Expr::Loop { body }, syntax_ptr)
650 }
651 ast::Expr::WhileExpr(e) => {
652 let body = self.collect_block_opt(e.loop_body());
653
654 let condition = match e.condition() {
655 None => self.exprs.alloc(Expr::Missing),
656 Some(condition) => match condition.pat() {
657 None => self.collect_expr_opt(condition.expr()),
658 // if let -- desugar to match
659 Some(pat) => {
660 tested_by!(infer_while_let);
661 let pat = self.collect_pat(pat);
662 let match_expr = self.collect_expr_opt(condition.expr());
663 let placeholder_pat = self.pats.alloc(Pat::Missing);
664 let break_ = self.exprs.alloc(Expr::Break { expr: None });
665 let arms = vec![
666 MatchArm { pats: vec![pat], expr: body, guard: None },
667 MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None },
668 ];
669 let match_expr =
670 self.exprs.alloc(Expr::Match { expr: match_expr, arms });
671 return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr);
672 }
673 },
674 };
675
676 self.alloc_expr(Expr::While { condition, body }, syntax_ptr)
677 }
678 ast::Expr::ForExpr(e) => {
679 let iterable = self.collect_expr_opt(e.iterable());
680 let pat = self.collect_pat_opt(e.pat());
681 let body = self.collect_block_opt(e.loop_body());
682 self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr)
683 }
684 ast::Expr::CallExpr(e) => {
685 let callee = self.collect_expr_opt(e.expr());
686 let args = if let Some(arg_list) = e.arg_list() {
687 arg_list.args().map(|e| self.collect_expr(e)).collect()
688 } else {
689 Vec::new()
690 };
691 self.alloc_expr(Expr::Call { callee, args }, syntax_ptr)
692 }
693 ast::Expr::MethodCallExpr(e) => {
694 let receiver = self.collect_expr_opt(e.expr());
695 let args = if let Some(arg_list) = e.arg_list() {
696 arg_list.args().map(|e| self.collect_expr(e)).collect()
697 } else {
698 Vec::new()
699 };
700 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
701 let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast);
702 self.alloc_expr(
703 Expr::MethodCall { receiver, method_name, args, generic_args },
704 syntax_ptr,
705 )
706 }
707 ast::Expr::MatchExpr(e) => {
708 let expr = self.collect_expr_opt(e.expr());
709 let arms = if let Some(match_arm_list) = e.match_arm_list() {
710 match_arm_list
711 .arms()
712 .map(|arm| MatchArm {
713 pats: arm.pats().map(|p| self.collect_pat(p)).collect(),
714 expr: self.collect_expr_opt(arm.expr()),
715 guard: arm
716 .guard()
717 .and_then(|guard| guard.expr())
718 .map(|e| self.collect_expr(e)),
719 })
720 .collect()
721 } else {
722 Vec::new()
723 };
724 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
725 }
726 ast::Expr::PathExpr(e) => {
727 let path =
728 e.path().and_then(Path::from_ast).map(Expr::Path).unwrap_or(Expr::Missing);
729 self.alloc_expr(path, syntax_ptr)
730 }
731 ast::Expr::ContinueExpr(_e) => {
732 // FIXME: labels
733 self.alloc_expr(Expr::Continue, syntax_ptr)
734 }
735 ast::Expr::BreakExpr(e) => {
736 let expr = e.expr().map(|e| self.collect_expr(e));
737 self.alloc_expr(Expr::Break { expr }, syntax_ptr)
738 }
739 ast::Expr::ParenExpr(e) => {
740 let inner = self.collect_expr_opt(e.expr());
741 // make the paren expr point to the inner expression as well
742 self.source_map.expr_map.insert(syntax_ptr, inner);
743 inner
744 }
745 ast::Expr::ReturnExpr(e) => {
746 let expr = e.expr().map(|e| self.collect_expr(e));
747 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
748 }
749 ast::Expr::RecordLit(e) => {
750 let path = e.path().and_then(Path::from_ast);
751 let mut field_ptrs = Vec::new();
752 let record_lit = if let Some(nfl) = e.record_field_list() {
753 let fields = nfl
754 .fields()
755 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
756 .map(|field| RecordLitField {
757 name: field
758 .name_ref()
759 .map(|nr| nr.as_name())
760 .unwrap_or_else(Name::missing),
761 expr: if let Some(e) = field.expr() {
762 self.collect_expr(e)
763 } else if let Some(nr) = field.name_ref() {
764 // field shorthand
765 let id = self.exprs.alloc(Expr::Path(Path::from_name_ref(&nr)));
766 self.source_map
767 .expr_map
768 .insert(SyntaxNodePtr::new(nr.syntax()), id);
769 self.source_map
770 .expr_map_back
771 .insert(id, SyntaxNodePtr::new(nr.syntax()));
772 id
773 } else {
774 self.exprs.alloc(Expr::Missing)
775 },
776 })
777 .collect();
778 let spread = nfl.spread().map(|s| self.collect_expr(s));
779 Expr::RecordLit { path, fields, spread }
780 } else {
781 Expr::RecordLit { path, fields: Vec::new(), spread: None }
782 };
783
784 let res = self.alloc_expr(record_lit, syntax_ptr);
785 for (i, ptr) in field_ptrs.into_iter().enumerate() {
786 self.source_map.field_map.insert((res, i), ptr);
787 }
788 res
789 }
790 ast::Expr::FieldExpr(e) => {
791 let expr = self.collect_expr_opt(e.expr());
792 let name = match e.field_access() {
793 Some(kind) => kind.as_name(),
794 _ => Name::missing(),
795 };
796 self.alloc_expr(Expr::Field { expr, name }, syntax_ptr)
797 }
798 ast::Expr::AwaitExpr(e) => {
799 let expr = self.collect_expr_opt(e.expr());
800 self.alloc_expr(Expr::Await { expr }, syntax_ptr)
801 }
802 ast::Expr::TryExpr(e) => {
803 let expr = self.collect_expr_opt(e.expr());
804 self.alloc_expr(Expr::Try { expr }, syntax_ptr)
805 }
806 ast::Expr::CastExpr(e) => {
807 let expr = self.collect_expr_opt(e.expr());
808 let type_ref = TypeRef::from_ast_opt(e.type_ref());
809 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
810 }
811 ast::Expr::RefExpr(e) => {
812 let expr = self.collect_expr_opt(e.expr());
813 let mutability = Mutability::from_mutable(e.is_mut());
814 self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr)
815 }
816 ast::Expr::PrefixExpr(e) => {
817 let expr = self.collect_expr_opt(e.expr());
818 if let Some(op) = e.op_kind() {
819 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
820 } else {
821 self.alloc_expr(Expr::Missing, syntax_ptr)
822 }
823 }
824 ast::Expr::LambdaExpr(e) => {
825 let mut args = Vec::new();
826 let mut arg_types = Vec::new();
827 if let Some(pl) = e.param_list() {
828 for param in pl.params() {
829 let pat = self.collect_pat_opt(param.pat());
830 let type_ref = param.ascribed_type().map(TypeRef::from_ast);
831 args.push(pat);
832 arg_types.push(type_ref);
833 }
834 }
835 let body = self.collect_expr_opt(e.body());
836 self.alloc_expr(Expr::Lambda { args, arg_types, body }, syntax_ptr)
837 }
838 ast::Expr::BinExpr(e) => {
839 let lhs = self.collect_expr_opt(e.lhs());
840 let rhs = self.collect_expr_opt(e.rhs());
841 let op = e.op_kind().map(BinaryOp::from);
842 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
843 }
844 ast::Expr::TupleExpr(e) => {
845 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect();
846 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
847 }
848
849 ast::Expr::ArrayExpr(e) => {
850 let kind = e.kind();
851
852 match kind {
853 ArrayExprKind::ElementList(e) => {
854 let exprs = e.map(|expr| self.collect_expr(expr)).collect();
855 self.alloc_expr(Expr::Array(Array::ElementList(exprs)), syntax_ptr)
856 }
857 ArrayExprKind::Repeat { initializer, repeat } => {
858 let initializer = self.collect_expr_opt(initializer);
859 let repeat = self.collect_expr_opt(repeat);
860 self.alloc_expr(
861 Expr::Array(Array::Repeat { initializer, repeat }),
862 syntax_ptr,
863 )
864 }
865 }
866 }
867
868 ast::Expr::Literal(e) => {
869 let lit = match e.kind() {
870 LiteralKind::IntNumber { suffix } => {
871 let known_name = suffix
872 .and_then(|it| IntTy::from_suffix(&it).map(UncertainIntTy::Known));
873
874 Literal::Int(
875 Default::default(),
876 known_name.unwrap_or(UncertainIntTy::Unknown),
877 )
878 }
879 LiteralKind::FloatNumber { suffix } => {
880 let known_name = suffix
881 .and_then(|it| FloatTy::from_suffix(&it).map(UncertainFloatTy::Known));
882
883 Literal::Float(
884 Default::default(),
885 known_name.unwrap_or(UncertainFloatTy::Unknown),
886 )
887 }
888 LiteralKind::ByteString => Literal::ByteString(Default::default()),
889 LiteralKind::String => Literal::String(Default::default()),
890 LiteralKind::Byte => {
891 Literal::Int(Default::default(), UncertainIntTy::Known(IntTy::u8()))
892 }
893 LiteralKind::Bool => Literal::Bool(Default::default()),
894 LiteralKind::Char => Literal::Char(Default::default()),
895 };
896 self.alloc_expr(Expr::Literal(lit), syntax_ptr)
897 }
898 ast::Expr::IndexExpr(e) => {
899 let base = self.collect_expr_opt(e.base());
900 let index = self.collect_expr_opt(e.index());
901 self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
902 }
903
904 // FIXME implement HIR for these:
905 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
906 ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
907 ast::Expr::MacroCall(e) => {
908 let ast_id = self
909 .db
910 .ast_id_map(self.current_file_id)
911 .ast_id(&e)
912 .with_file_id(self.current_file_id);
913
914 if let Some(path) = e.path().and_then(Path::from_ast) {
915 if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) {
916 let call_id = MacroCallLoc { def: def.id, ast_id }.id(self.db);
917 let file_id = call_id.as_file(MacroFileKind::Expr);
918 if let Some(node) = self.db.parse_or_expand(file_id) {
919 if let Some(expr) = ast::Expr::cast(node) {
920 log::debug!("macro expansion {:#?}", expr.syntax());
921 let old_file_id =
922 std::mem::replace(&mut self.current_file_id, file_id);
923 let id = self.collect_expr(expr);
924 self.current_file_id = old_file_id;
925 return id;
926 }
927 }
928 }
929 }
930 // FIXME: Instead of just dropping the error from expansion
931 // report it
932 self.alloc_expr(Expr::Missing, syntax_ptr)
933 }
934 }
935 }
936
937 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
938 if let Some(expr) = expr {
939 self.collect_expr(expr)
940 } else {
941 self.exprs.alloc(Expr::Missing)
942 }
943 }
944
945 fn collect_block(&mut self, block: ast::Block) -> ExprId {
946 let statements = block
947 .statements()
948 .map(|s| match s {
949 ast::Stmt::LetStmt(stmt) => {
950 let pat = self.collect_pat_opt(stmt.pat());
951 let type_ref = stmt.ascribed_type().map(TypeRef::from_ast);
952 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
953 Statement::Let { pat, type_ref, initializer }
954 }
955 ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())),
956 })
957 .collect();
958 let tail = block.expr().map(|e| self.collect_expr(e));
959 self.alloc_expr(Expr::Block { statements, tail }, SyntaxNodePtr::new(block.syntax()))
960 }
961
962 fn collect_block_opt(&mut self, block: Option<ast::Block>) -> ExprId {
963 if let Some(block) = block {
964 self.collect_block(block)
965 } else {
966 self.exprs.alloc(Expr::Missing)
967 }
968 }
969
970 fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
971 let pattern = match &pat {
972 ast::Pat::BindPat(bp) => {
973 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
974 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref());
975 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat));
976 Pat::Bind { name, mode: annotation, subpat }
977 }
978 ast::Pat::TupleStructPat(p) => {
979 let path = p.path().and_then(Path::from_ast);
980 let args = p.args().map(|p| self.collect_pat(p)).collect();
981 Pat::TupleStruct { path, args }
982 }
983 ast::Pat::RefPat(p) => {
984 let pat = self.collect_pat_opt(p.pat());
985 let mutability = Mutability::from_mutable(p.is_mut());
986 Pat::Ref { pat, mutability }
987 }
988 ast::Pat::PathPat(p) => {
989 let path = p.path().and_then(Path::from_ast);
990 path.map(Pat::Path).unwrap_or(Pat::Missing)
991 }
992 ast::Pat::TuplePat(p) => {
993 let args = p.args().map(|p| self.collect_pat(p)).collect();
994 Pat::Tuple(args)
995 }
996 ast::Pat::PlaceholderPat(_) => Pat::Wild,
997 ast::Pat::RecordPat(p) => {
998 let path = p.path().and_then(Path::from_ast);
999 let record_field_pat_list =
1000 p.record_field_pat_list().expect("every struct should have a field list");
1001 let mut fields: Vec<_> = record_field_pat_list
1002 .bind_pats()
1003 .filter_map(|bind_pat| {
1004 let ast_pat =
1005 ast::Pat::cast(bind_pat.syntax().clone()).expect("bind pat is a pat");
1006 let pat = self.collect_pat(ast_pat);
1007 let name = bind_pat.name()?.as_name();
1008 Some(RecordFieldPat { name, pat })
1009 })
1010 .collect();
1011 let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
1012 let ast_pat = f.pat()?;
1013 let pat = self.collect_pat(ast_pat);
1014 let name = f.name()?.as_name();
1015 Some(RecordFieldPat { name, pat })
1016 });
1017 fields.extend(iter);
1018
1019 Pat::Struct { path, args: fields }
1020 }
1021
1022 // FIXME: implement
1023 ast::Pat::BoxPat(_) => Pat::Missing,
1024 ast::Pat::LiteralPat(_) => Pat::Missing,
1025 ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing,
1026 };
1027 let ptr = AstPtr::new(&pat);
1028 self.alloc_pat(pattern, Either::A(ptr))
1029 }
1030
1031 fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId {
1032 if let Some(pat) = pat {
1033 self.collect_pat(pat)
1034 } else {
1035 self.pats.alloc(Pat::Missing)
1036 }
1037 }
1038
1039 fn collect_const_body(&mut self, node: ast::ConstDef) {
1040 let body = self.collect_expr_opt(node.body());
1041 self.body_expr = Some(body);
1042 }
1043
1044 fn collect_static_body(&mut self, node: ast::StaticDef) {
1045 let body = self.collect_expr_opt(node.body());
1046 self.body_expr = Some(body);
1047 }
1048
1049 fn collect_fn_body(&mut self, node: ast::FnDef) {
1050 if let Some(param_list) = node.param_list() {
1051 if let Some(self_param) = param_list.self_param() {
1052 let ptr = AstPtr::new(&self_param);
1053 let param_pat = self.alloc_pat(
1054 Pat::Bind {
1055 name: SELF_PARAM,
1056 mode: BindingAnnotation::Unannotated,
1057 subpat: None,
1058 },
1059 Either::B(ptr),
1060 );
1061 self.params.push(param_pat);
1062 }
1063
1064 for param in param_list.params() {
1065 let pat = if let Some(pat) = param.pat() {
1066 pat
1067 } else {
1068 continue;
1069 };
1070 let param_pat = self.collect_pat(pat);
1071 self.params.push(param_pat);
1072 }
1073 };
1074
1075 let body = self.collect_block_opt(node.body());
1076 self.body_expr = Some(body);
1077 }
1078
1079 fn finish(self) -> (Body, BodySourceMap) {
1080 let body = Body {
1081 owner: self.owner,
1082 exprs: self.exprs,
1083 pats: self.pats,
1084 params: self.params,
1085 body_expr: self.body_expr.expect("A body should have been collected"),
1086 };
1087 (body, self.source_map)
1088 }
1089}
1090
1091impl From<ast::BinOp> for BinaryOp {
1092 fn from(ast_op: ast::BinOp) -> Self {
1093 match ast_op {
1094 ast::BinOp::BooleanOr => BinaryOp::LogicOp(LogicOp::Or),
1095 ast::BinOp::BooleanAnd => BinaryOp::LogicOp(LogicOp::And),
1096 ast::BinOp::EqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
1097 ast::BinOp::NegatedEqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: true }),
1098 ast::BinOp::LesserEqualTest => {
1099 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false })
1100 }
1101 ast::BinOp::GreaterEqualTest => {
1102 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false })
1103 }
1104 ast::BinOp::LesserTest => {
1105 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true })
1106 }
1107 ast::BinOp::GreaterTest => {
1108 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true })
1109 }
1110 ast::BinOp::Addition => BinaryOp::ArithOp(ArithOp::Add),
1111 ast::BinOp::Multiplication => BinaryOp::ArithOp(ArithOp::Mul),
1112 ast::BinOp::Subtraction => BinaryOp::ArithOp(ArithOp::Sub),
1113 ast::BinOp::Division => BinaryOp::ArithOp(ArithOp::Div),
1114 ast::BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Rem),
1115 ast::BinOp::LeftShift => BinaryOp::ArithOp(ArithOp::Shl),
1116 ast::BinOp::RightShift => BinaryOp::ArithOp(ArithOp::Shr),
1117 ast::BinOp::BitwiseXor => BinaryOp::ArithOp(ArithOp::BitXor),
1118 ast::BinOp::BitwiseOr => BinaryOp::ArithOp(ArithOp::BitOr),
1119 ast::BinOp::BitwiseAnd => BinaryOp::ArithOp(ArithOp::BitAnd),
1120 ast::BinOp::Assignment => BinaryOp::Assignment { op: None },
1121 ast::BinOp::AddAssign => BinaryOp::Assignment { op: Some(ArithOp::Add) },
1122 ast::BinOp::DivAssign => BinaryOp::Assignment { op: Some(ArithOp::Div) },
1123 ast::BinOp::MulAssign => BinaryOp::Assignment { op: Some(ArithOp::Mul) },
1124 ast::BinOp::RemAssign => BinaryOp::Assignment { op: Some(ArithOp::Rem) },
1125 ast::BinOp::ShlAssign => BinaryOp::Assignment { op: Some(ArithOp::Shl) },
1126 ast::BinOp::ShrAssign => BinaryOp::Assignment { op: Some(ArithOp::Shr) },
1127 ast::BinOp::SubAssign => BinaryOp::Assignment { op: Some(ArithOp::Sub) },
1128 ast::BinOp::BitOrAssign => BinaryOp::Assignment { op: Some(ArithOp::BitOr) },
1129 ast::BinOp::BitAndAssign => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) },
1130 ast::BinOp::BitXorAssign => BinaryOp::Assignment { op: Some(ArithOp::BitXor) },
1131 }
1132 }
1133}
1134
1135pub(crate) fn body_with_source_map_query( 538pub(crate) fn body_with_source_map_query(
1136 db: &impl HirDatabase, 539 db: &impl HirDatabase,
1137 def: DefWithBody, 540 def: DefWithBody,
1138) -> (Arc<Body>, Arc<BodySourceMap>) { 541) -> (Arc<Body>, Arc<BodySourceMap>) {
1139 let mut collector; 542 let mut params = None;
1140 543
1141 match def { 544 let (file_id, body) = match def {
1142 DefWithBody::Const(ref c) => { 545 DefWithBody::Function(f) => {
1143 let src = c.source(db);
1144 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
1145 collector.collect_const_body(src.ast)
1146 }
1147 DefWithBody::Function(ref f) => {
1148 let src = f.source(db); 546 let src = f.source(db);
1149 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db); 547 params = src.ast.param_list();
1150 collector.collect_fn_body(src.ast) 548 (src.file_id, src.ast.body().map(ast::Expr::from))
549 }
550 DefWithBody::Const(c) => {
551 let src = c.source(db);
552 (src.file_id, src.ast.body())
1151 } 553 }
1152 DefWithBody::Static(ref s) => { 554 DefWithBody::Static(s) => {
1153 let src = s.source(db); 555 let src = s.source(db);
1154 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db); 556 (src.file_id, src.ast.body())
1155 collector.collect_static_body(src.ast)
1156 } 557 }
1157 } 558 };
1158 559
1159 let (body, source_map) = collector.finish(); 560 let (body, source_map) = lower::lower(db, def.resolver(db), file_id, def, params, body);
1160 (Arc::new(body), Arc::new(source_map)) 561 (Arc::new(body), Arc::new(source_map))
1161} 562}
1162 563