aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/expr.rs663
-rw-r--r--crates/ra_hir/src/expr/lower.rs653
3 files changed, 667 insertions, 653 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 7b7974f5b..f669ab969 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -169,13 +169,13 @@ pub trait HirDatabase: DefDatabase + AstDatabase {
169 #[salsa::invoke(crate::ty::generic_defaults_query)] 169 #[salsa::invoke(crate::ty::generic_defaults_query)]
170 fn generic_defaults(&self, def: GenericDef) -> Substs; 170 fn generic_defaults(&self, def: GenericDef) -> Substs;
171 171
172 #[salsa::invoke(crate::expr::body_with_source_map_query)] 172 #[salsa::invoke(crate::expr::lower::body_with_source_map_query)]
173 fn body_with_source_map( 173 fn body_with_source_map(
174 &self, 174 &self,
175 def: DefWithBody, 175 def: DefWithBody,
176 ) -> (Arc<crate::expr::Body>, Arc<crate::expr::BodySourceMap>); 176 ) -> (Arc<crate::expr::Body>, Arc<crate::expr::BodySourceMap>);
177 177
178 #[salsa::invoke(crate::expr::body_hir_query)] 178 #[salsa::invoke(crate::expr::lower::body_hir_query)]
179 fn body_hir(&self, def: DefWithBody) -> Arc<crate::expr::Body>; 179 fn body_hir(&self, def: DefWithBody) -> Arc<crate::expr::Body>;
180 180
181 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] 181 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 5c95bed40..17e89c48f 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 TypeAscriptionOwner,
11 },
12 AstNode, AstPtr,
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, HirDatabase, Name, Path, Resolver,
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 {
@@ -433,10 +427,6 @@ impl Expr {
433 } 427 }
434} 428}
435 429
436#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
437pub struct PatId(RawId);
438impl_arena_id!(PatId);
439
440/// Explicit binding annotations given in the HIR for a binding. Note 430/// Explicit binding annotations given in the HIR for a binding. Note
441/// that this is not the final binding *mode* that we infer after type 431/// that this is not the final binding *mode* that we infer after type
442/// inference. 432/// inference.
@@ -534,632 +524,3 @@ impl Pat {
534 } 524 }
535 } 525 }
536} 526}
537
538// Queries
539
540pub(crate) struct ExprCollector<DB> {
541 db: DB,
542 owner: DefWithBody,
543 exprs: Arena<ExprId, Expr>,
544 pats: Arena<PatId, Pat>,
545 source_map: BodySourceMap,
546 params: Vec<PatId>,
547 body_expr: Option<ExprId>,
548 resolver: Resolver,
549 // Expr collector expands macros along the way. original points to the file
550 // we started with, current points to the current macro expansion. source
551 // maps don't support macros yet, so we only record info into source map if
552 // current == original (see #1196)
553 original_file_id: HirFileId,
554 current_file_id: HirFileId,
555}
556
557impl<'a, DB> ExprCollector<&'a DB>
558where
559 DB: HirDatabase,
560{
561 fn new(owner: DefWithBody, file_id: HirFileId, resolver: Resolver, db: &'a DB) -> Self {
562 ExprCollector {
563 owner,
564 resolver,
565 db,
566 exprs: Arena::default(),
567 pats: Arena::default(),
568 source_map: BodySourceMap::default(),
569 params: Vec::new(),
570 body_expr: None,
571 original_file_id: file_id,
572 current_file_id: file_id,
573 }
574 }
575 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
576 let ptr = Either::A(ptr);
577 let id = self.exprs.alloc(expr);
578 if self.current_file_id == self.original_file_id {
579 self.source_map.expr_map.insert(ptr, id);
580 self.source_map.expr_map_back.insert(id, ptr);
581 }
582 id
583 }
584
585 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
586 let id = self.pats.alloc(pat);
587
588 if self.current_file_id == self.original_file_id {
589 self.source_map.pat_map.insert(ptr, id);
590 self.source_map.pat_map_back.insert(id, ptr);
591 }
592
593 id
594 }
595
596 fn empty_block(&mut self) -> ExprId {
597 let block = Expr::Block { statements: Vec::new(), tail: None };
598 self.exprs.alloc(block)
599 }
600
601 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
602 let syntax_ptr = AstPtr::new(&expr);
603 match expr {
604 ast::Expr::IfExpr(e) => {
605 let then_branch = self.collect_block_opt(e.then_branch());
606
607 let else_branch = e.else_branch().map(|b| match b {
608 ast::ElseBranch::Block(it) => self.collect_block(it),
609 ast::ElseBranch::IfExpr(elif) => {
610 let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap();
611 self.collect_expr(expr)
612 }
613 });
614
615 let condition = match e.condition() {
616 None => self.exprs.alloc(Expr::Missing),
617 Some(condition) => match condition.pat() {
618 None => self.collect_expr_opt(condition.expr()),
619 // if let -- desugar to match
620 Some(pat) => {
621 let pat = self.collect_pat(pat);
622 let match_expr = self.collect_expr_opt(condition.expr());
623 let placeholder_pat = self.pats.alloc(Pat::Missing);
624 let arms = vec![
625 MatchArm { pats: vec![pat], expr: then_branch, guard: None },
626 MatchArm {
627 pats: vec![placeholder_pat],
628 expr: else_branch.unwrap_or_else(|| self.empty_block()),
629 guard: None,
630 },
631 ];
632 return self
633 .alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr);
634 }
635 },
636 };
637
638 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
639 }
640 ast::Expr::TryBlockExpr(e) => {
641 let body = self.collect_block_opt(e.body());
642 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
643 }
644 ast::Expr::BlockExpr(e) => self.collect_block(e),
645 ast::Expr::LoopExpr(e) => {
646 let body = self.collect_block_opt(e.loop_body());
647 self.alloc_expr(Expr::Loop { body }, syntax_ptr)
648 }
649 ast::Expr::WhileExpr(e) => {
650 let body = self.collect_block_opt(e.loop_body());
651
652 let condition = match e.condition() {
653 None => self.exprs.alloc(Expr::Missing),
654 Some(condition) => match condition.pat() {
655 None => self.collect_expr_opt(condition.expr()),
656 // if let -- desugar to match
657 Some(pat) => {
658 tested_by!(infer_while_let);
659 let pat = self.collect_pat(pat);
660 let match_expr = self.collect_expr_opt(condition.expr());
661 let placeholder_pat = self.pats.alloc(Pat::Missing);
662 let break_ = self.exprs.alloc(Expr::Break { expr: None });
663 let arms = vec![
664 MatchArm { pats: vec![pat], expr: body, guard: None },
665 MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None },
666 ];
667 let match_expr =
668 self.exprs.alloc(Expr::Match { expr: match_expr, arms });
669 return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr);
670 }
671 },
672 };
673
674 self.alloc_expr(Expr::While { condition, body }, syntax_ptr)
675 }
676 ast::Expr::ForExpr(e) => {
677 let iterable = self.collect_expr_opt(e.iterable());
678 let pat = self.collect_pat_opt(e.pat());
679 let body = self.collect_block_opt(e.loop_body());
680 self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr)
681 }
682 ast::Expr::CallExpr(e) => {
683 let callee = self.collect_expr_opt(e.expr());
684 let args = if let Some(arg_list) = e.arg_list() {
685 arg_list.args().map(|e| self.collect_expr(e)).collect()
686 } else {
687 Vec::new()
688 };
689 self.alloc_expr(Expr::Call { callee, args }, syntax_ptr)
690 }
691 ast::Expr::MethodCallExpr(e) => {
692 let receiver = self.collect_expr_opt(e.expr());
693 let args = if let Some(arg_list) = e.arg_list() {
694 arg_list.args().map(|e| self.collect_expr(e)).collect()
695 } else {
696 Vec::new()
697 };
698 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
699 let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast);
700 self.alloc_expr(
701 Expr::MethodCall { receiver, method_name, args, generic_args },
702 syntax_ptr,
703 )
704 }
705 ast::Expr::MatchExpr(e) => {
706 let expr = self.collect_expr_opt(e.expr());
707 let arms = if let Some(match_arm_list) = e.match_arm_list() {
708 match_arm_list
709 .arms()
710 .map(|arm| MatchArm {
711 pats: arm.pats().map(|p| self.collect_pat(p)).collect(),
712 expr: self.collect_expr_opt(arm.expr()),
713 guard: arm
714 .guard()
715 .and_then(|guard| guard.expr())
716 .map(|e| self.collect_expr(e)),
717 })
718 .collect()
719 } else {
720 Vec::new()
721 };
722 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
723 }
724 ast::Expr::PathExpr(e) => {
725 let path =
726 e.path().and_then(Path::from_ast).map(Expr::Path).unwrap_or(Expr::Missing);
727 self.alloc_expr(path, syntax_ptr)
728 }
729 ast::Expr::ContinueExpr(_e) => {
730 // FIXME: labels
731 self.alloc_expr(Expr::Continue, syntax_ptr)
732 }
733 ast::Expr::BreakExpr(e) => {
734 let expr = e.expr().map(|e| self.collect_expr(e));
735 self.alloc_expr(Expr::Break { expr }, syntax_ptr)
736 }
737 ast::Expr::ParenExpr(e) => {
738 let inner = self.collect_expr_opt(e.expr());
739 // make the paren expr point to the inner expression as well
740 self.source_map.expr_map.insert(Either::A(syntax_ptr), inner);
741 inner
742 }
743 ast::Expr::ReturnExpr(e) => {
744 let expr = e.expr().map(|e| self.collect_expr(e));
745 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
746 }
747 ast::Expr::RecordLit(e) => {
748 let path = e.path().and_then(Path::from_ast);
749 let mut field_ptrs = Vec::new();
750 let record_lit = if let Some(nfl) = e.record_field_list() {
751 let fields = nfl
752 .fields()
753 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
754 .map(|field| RecordLitField {
755 name: field
756 .name_ref()
757 .map(|nr| nr.as_name())
758 .unwrap_or_else(Name::missing),
759 expr: if let Some(e) = field.expr() {
760 self.collect_expr(e)
761 } else if let Some(nr) = field.name_ref() {
762 // field shorthand
763 let id = self.exprs.alloc(Expr::Path(Path::from_name_ref(&nr)));
764 let ptr = Either::B(AstPtr::new(&field));
765 self.source_map.expr_map.insert(ptr, id);
766 self.source_map.expr_map_back.insert(id, ptr);
767 id
768 } else {
769 self.exprs.alloc(Expr::Missing)
770 },
771 })
772 .collect();
773 let spread = nfl.spread().map(|s| self.collect_expr(s));
774 Expr::RecordLit { path, fields, spread }
775 } else {
776 Expr::RecordLit { path, fields: Vec::new(), spread: None }
777 };
778
779 let res = self.alloc_expr(record_lit, syntax_ptr);
780 for (i, ptr) in field_ptrs.into_iter().enumerate() {
781 self.source_map.field_map.insert((res, i), ptr);
782 }
783 res
784 }
785 ast::Expr::FieldExpr(e) => {
786 let expr = self.collect_expr_opt(e.expr());
787 let name = match e.field_access() {
788 Some(kind) => kind.as_name(),
789 _ => Name::missing(),
790 };
791 self.alloc_expr(Expr::Field { expr, name }, syntax_ptr)
792 }
793 ast::Expr::AwaitExpr(e) => {
794 let expr = self.collect_expr_opt(e.expr());
795 self.alloc_expr(Expr::Await { expr }, syntax_ptr)
796 }
797 ast::Expr::TryExpr(e) => {
798 let expr = self.collect_expr_opt(e.expr());
799 self.alloc_expr(Expr::Try { expr }, syntax_ptr)
800 }
801 ast::Expr::CastExpr(e) => {
802 let expr = self.collect_expr_opt(e.expr());
803 let type_ref = TypeRef::from_ast_opt(e.type_ref());
804 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
805 }
806 ast::Expr::RefExpr(e) => {
807 let expr = self.collect_expr_opt(e.expr());
808 let mutability = Mutability::from_mutable(e.is_mut());
809 self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr)
810 }
811 ast::Expr::PrefixExpr(e) => {
812 let expr = self.collect_expr_opt(e.expr());
813 if let Some(op) = e.op_kind() {
814 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
815 } else {
816 self.alloc_expr(Expr::Missing, syntax_ptr)
817 }
818 }
819 ast::Expr::LambdaExpr(e) => {
820 let mut args = Vec::new();
821 let mut arg_types = Vec::new();
822 if let Some(pl) = e.param_list() {
823 for param in pl.params() {
824 let pat = self.collect_pat_opt(param.pat());
825 let type_ref = param.ascribed_type().map(TypeRef::from_ast);
826 args.push(pat);
827 arg_types.push(type_ref);
828 }
829 }
830 let body = self.collect_expr_opt(e.body());
831 self.alloc_expr(Expr::Lambda { args, arg_types, body }, syntax_ptr)
832 }
833 ast::Expr::BinExpr(e) => {
834 let lhs = self.collect_expr_opt(e.lhs());
835 let rhs = self.collect_expr_opt(e.rhs());
836 let op = e.op_kind().map(BinaryOp::from);
837 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
838 }
839 ast::Expr::TupleExpr(e) => {
840 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect();
841 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
842 }
843
844 ast::Expr::ArrayExpr(e) => {
845 let kind = e.kind();
846
847 match kind {
848 ArrayExprKind::ElementList(e) => {
849 let exprs = e.map(|expr| self.collect_expr(expr)).collect();
850 self.alloc_expr(Expr::Array(Array::ElementList(exprs)), syntax_ptr)
851 }
852 ArrayExprKind::Repeat { initializer, repeat } => {
853 let initializer = self.collect_expr_opt(initializer);
854 let repeat = self.collect_expr_opt(repeat);
855 self.alloc_expr(
856 Expr::Array(Array::Repeat { initializer, repeat }),
857 syntax_ptr,
858 )
859 }
860 }
861 }
862
863 ast::Expr::Literal(e) => {
864 let lit = match e.kind() {
865 LiteralKind::IntNumber { suffix } => {
866 let known_name = suffix
867 .and_then(|it| IntTy::from_suffix(&it).map(UncertainIntTy::Known));
868
869 Literal::Int(
870 Default::default(),
871 known_name.unwrap_or(UncertainIntTy::Unknown),
872 )
873 }
874 LiteralKind::FloatNumber { suffix } => {
875 let known_name = suffix
876 .and_then(|it| FloatTy::from_suffix(&it).map(UncertainFloatTy::Known));
877
878 Literal::Float(
879 Default::default(),
880 known_name.unwrap_or(UncertainFloatTy::Unknown),
881 )
882 }
883 LiteralKind::ByteString => Literal::ByteString(Default::default()),
884 LiteralKind::String => Literal::String(Default::default()),
885 LiteralKind::Byte => {
886 Literal::Int(Default::default(), UncertainIntTy::Known(IntTy::u8()))
887 }
888 LiteralKind::Bool => Literal::Bool(Default::default()),
889 LiteralKind::Char => Literal::Char(Default::default()),
890 };
891 self.alloc_expr(Expr::Literal(lit), syntax_ptr)
892 }
893 ast::Expr::IndexExpr(e) => {
894 let base = self.collect_expr_opt(e.base());
895 let index = self.collect_expr_opt(e.index());
896 self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
897 }
898
899 // FIXME implement HIR for these:
900 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
901 ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
902 ast::Expr::MacroCall(e) => {
903 let ast_id = self
904 .db
905 .ast_id_map(self.current_file_id)
906 .ast_id(&e)
907 .with_file_id(self.current_file_id);
908
909 if let Some(path) = e.path().and_then(Path::from_ast) {
910 if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) {
911 let call_id = MacroCallLoc { def: def.id, ast_id }.id(self.db);
912 let file_id = call_id.as_file(MacroFileKind::Expr);
913 if let Some(node) = self.db.parse_or_expand(file_id) {
914 if let Some(expr) = ast::Expr::cast(node) {
915 log::debug!("macro expansion {:#?}", expr.syntax());
916 let old_file_id =
917 std::mem::replace(&mut self.current_file_id, file_id);
918 let id = self.collect_expr(expr);
919 self.current_file_id = old_file_id;
920 return id;
921 }
922 }
923 }
924 }
925 // FIXME: Instead of just dropping the error from expansion
926 // report it
927 self.alloc_expr(Expr::Missing, syntax_ptr)
928 }
929 }
930 }
931
932 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
933 if let Some(expr) = expr {
934 self.collect_expr(expr)
935 } else {
936 self.exprs.alloc(Expr::Missing)
937 }
938 }
939
940 fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId {
941 let syntax_node_ptr = AstPtr::new(&expr.clone().into());
942 let block = match expr.block() {
943 Some(block) => block,
944 None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
945 };
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 }, syntax_node_ptr)
960 }
961
962 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
963 if let Some(block) = expr {
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(
1136 db: &impl HirDatabase,
1137 def: DefWithBody,
1138) -> (Arc<Body>, Arc<BodySourceMap>) {
1139 let mut collector;
1140
1141 match def {
1142 DefWithBody::Const(ref c) => {
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);
1149 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
1150 collector.collect_fn_body(src.ast)
1151 }
1152 DefWithBody::Static(ref s) => {
1153 let src = s.source(db);
1154 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
1155 collector.collect_static_body(src.ast)
1156 }
1157 }
1158
1159 let (body, source_map) = collector.finish();
1160 (Arc::new(body), Arc::new(source_map))
1161}
1162
1163pub(crate) fn body_hir_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<Body> {
1164 db.body_with_source_map(def).0
1165}
diff --git a/crates/ra_hir/src/expr/lower.rs b/crates/ra_hir/src/expr/lower.rs
new file mode 100644
index 000000000..01b770149
--- /dev/null
+++ b/crates/ra_hir/src/expr/lower.rs
@@ -0,0 +1,653 @@
1use std::sync::Arc;
2
3use ra_arena::Arena;
4use ra_syntax::{
5 ast::{
6 self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner,
7 TypeAscriptionOwner,
8 },
9 AstNode, AstPtr,
10};
11use test_utils::tested_by;
12
13use crate::{
14 name::{AsName, Name, SELF_PARAM},
15 path::GenericArgs,
16 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy},
17 type_ref::TypeRef,
18 DefWithBody, Either, HasSource, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind,
19 Mutability, Path, Resolver,
20};
21
22use super::{
23 ArithOp, Array, BinaryOp, BindingAnnotation, Body, BodySourceMap, CmpOp, Expr, ExprId,
24 Literal, LogicOp, MatchArm, Ordering, Pat, PatId, PatPtr, RecordFieldPat, RecordLitField,
25 Statement,
26};
27
28pub(crate) struct ExprCollector<DB> {
29 db: DB,
30 owner: DefWithBody,
31 exprs: Arena<ExprId, Expr>,
32 pats: Arena<PatId, Pat>,
33 source_map: BodySourceMap,
34 params: Vec<PatId>,
35 body_expr: Option<ExprId>,
36 resolver: Resolver,
37 // Expr collector expands macros along the way. original points to the file
38 // we started with, current points to the current macro expansion. source
39 // maps don't support macros yet, so we only record info into source map if
40 // current == original (see #1196)
41 original_file_id: HirFileId,
42 current_file_id: HirFileId,
43}
44
45impl<'a, DB> ExprCollector<&'a DB>
46where
47 DB: HirDatabase,
48{
49 fn new(owner: DefWithBody, file_id: HirFileId, resolver: Resolver, db: &'a DB) -> Self {
50 ExprCollector {
51 owner,
52 resolver,
53 db,
54 exprs: Arena::default(),
55 pats: Arena::default(),
56 source_map: BodySourceMap::default(),
57 params: Vec::new(),
58 body_expr: None,
59 original_file_id: file_id,
60 current_file_id: file_id,
61 }
62 }
63 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
64 let ptr = Either::A(ptr);
65 let id = self.exprs.alloc(expr);
66 if self.current_file_id == self.original_file_id {
67 self.source_map.expr_map.insert(ptr, id);
68 self.source_map.expr_map_back.insert(id, ptr);
69 }
70 id
71 }
72
73 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
74 let id = self.pats.alloc(pat);
75
76 if self.current_file_id == self.original_file_id {
77 self.source_map.pat_map.insert(ptr, id);
78 self.source_map.pat_map_back.insert(id, ptr);
79 }
80
81 id
82 }
83
84 fn empty_block(&mut self) -> ExprId {
85 let block = Expr::Block { statements: Vec::new(), tail: None };
86 self.exprs.alloc(block)
87 }
88
89 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
90 let syntax_ptr = AstPtr::new(&expr);
91 match expr {
92 ast::Expr::IfExpr(e) => {
93 let then_branch = self.collect_block_opt(e.then_branch());
94
95 let else_branch = e.else_branch().map(|b| match b {
96 ast::ElseBranch::Block(it) => self.collect_block(it),
97 ast::ElseBranch::IfExpr(elif) => {
98 let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap();
99 self.collect_expr(expr)
100 }
101 });
102
103 let condition = match e.condition() {
104 None => self.exprs.alloc(Expr::Missing),
105 Some(condition) => match condition.pat() {
106 None => self.collect_expr_opt(condition.expr()),
107 // if let -- desugar to match
108 Some(pat) => {
109 let pat = self.collect_pat(pat);
110 let match_expr = self.collect_expr_opt(condition.expr());
111 let placeholder_pat = self.pats.alloc(Pat::Missing);
112 let arms = vec![
113 MatchArm { pats: vec![pat], expr: then_branch, guard: None },
114 MatchArm {
115 pats: vec![placeholder_pat],
116 expr: else_branch.unwrap_or_else(|| self.empty_block()),
117 guard: None,
118 },
119 ];
120 return self
121 .alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr);
122 }
123 },
124 };
125
126 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
127 }
128 ast::Expr::TryBlockExpr(e) => {
129 let body = self.collect_block_opt(e.body());
130 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
131 }
132 ast::Expr::BlockExpr(e) => self.collect_block(e),
133 ast::Expr::LoopExpr(e) => {
134 let body = self.collect_block_opt(e.loop_body());
135 self.alloc_expr(Expr::Loop { body }, syntax_ptr)
136 }
137 ast::Expr::WhileExpr(e) => {
138 let body = self.collect_block_opt(e.loop_body());
139
140 let condition = match e.condition() {
141 None => self.exprs.alloc(Expr::Missing),
142 Some(condition) => match condition.pat() {
143 None => self.collect_expr_opt(condition.expr()),
144 // if let -- desugar to match
145 Some(pat) => {
146 tested_by!(infer_while_let);
147 let pat = self.collect_pat(pat);
148 let match_expr = self.collect_expr_opt(condition.expr());
149 let placeholder_pat = self.pats.alloc(Pat::Missing);
150 let break_ = self.exprs.alloc(Expr::Break { expr: None });
151 let arms = vec![
152 MatchArm { pats: vec![pat], expr: body, guard: None },
153 MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None },
154 ];
155 let match_expr =
156 self.exprs.alloc(Expr::Match { expr: match_expr, arms });
157 return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr);
158 }
159 },
160 };
161
162 self.alloc_expr(Expr::While { condition, body }, syntax_ptr)
163 }
164 ast::Expr::ForExpr(e) => {
165 let iterable = self.collect_expr_opt(e.iterable());
166 let pat = self.collect_pat_opt(e.pat());
167 let body = self.collect_block_opt(e.loop_body());
168 self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr)
169 }
170 ast::Expr::CallExpr(e) => {
171 let callee = self.collect_expr_opt(e.expr());
172 let args = if let Some(arg_list) = e.arg_list() {
173 arg_list.args().map(|e| self.collect_expr(e)).collect()
174 } else {
175 Vec::new()
176 };
177 self.alloc_expr(Expr::Call { callee, args }, syntax_ptr)
178 }
179 ast::Expr::MethodCallExpr(e) => {
180 let receiver = self.collect_expr_opt(e.expr());
181 let args = if let Some(arg_list) = e.arg_list() {
182 arg_list.args().map(|e| self.collect_expr(e)).collect()
183 } else {
184 Vec::new()
185 };
186 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
187 let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast);
188 self.alloc_expr(
189 Expr::MethodCall { receiver, method_name, args, generic_args },
190 syntax_ptr,
191 )
192 }
193 ast::Expr::MatchExpr(e) => {
194 let expr = self.collect_expr_opt(e.expr());
195 let arms = if let Some(match_arm_list) = e.match_arm_list() {
196 match_arm_list
197 .arms()
198 .map(|arm| MatchArm {
199 pats: arm.pats().map(|p| self.collect_pat(p)).collect(),
200 expr: self.collect_expr_opt(arm.expr()),
201 guard: arm
202 .guard()
203 .and_then(|guard| guard.expr())
204 .map(|e| self.collect_expr(e)),
205 })
206 .collect()
207 } else {
208 Vec::new()
209 };
210 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
211 }
212 ast::Expr::PathExpr(e) => {
213 let path =
214 e.path().and_then(Path::from_ast).map(Expr::Path).unwrap_or(Expr::Missing);
215 self.alloc_expr(path, syntax_ptr)
216 }
217 ast::Expr::ContinueExpr(_e) => {
218 // FIXME: labels
219 self.alloc_expr(Expr::Continue, syntax_ptr)
220 }
221 ast::Expr::BreakExpr(e) => {
222 let expr = e.expr().map(|e| self.collect_expr(e));
223 self.alloc_expr(Expr::Break { expr }, syntax_ptr)
224 }
225 ast::Expr::ParenExpr(e) => {
226 let inner = self.collect_expr_opt(e.expr());
227 // make the paren expr point to the inner expression as well
228 self.source_map.expr_map.insert(Either::A(syntax_ptr), inner);
229 inner
230 }
231 ast::Expr::ReturnExpr(e) => {
232 let expr = e.expr().map(|e| self.collect_expr(e));
233 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
234 }
235 ast::Expr::RecordLit(e) => {
236 let path = e.path().and_then(Path::from_ast);
237 let mut field_ptrs = Vec::new();
238 let record_lit = if let Some(nfl) = e.record_field_list() {
239 let fields = nfl
240 .fields()
241 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
242 .map(|field| RecordLitField {
243 name: field
244 .name_ref()
245 .map(|nr| nr.as_name())
246 .unwrap_or_else(Name::missing),
247 expr: if let Some(e) = field.expr() {
248 self.collect_expr(e)
249 } else if let Some(nr) = field.name_ref() {
250 // field shorthand
251 let id = self.exprs.alloc(Expr::Path(Path::from_name_ref(&nr)));
252 let ptr = Either::B(AstPtr::new(&field));
253 self.source_map.expr_map.insert(ptr, id);
254 self.source_map.expr_map_back.insert(id, ptr);
255 id
256 } else {
257 self.exprs.alloc(Expr::Missing)
258 },
259 })
260 .collect();
261 let spread = nfl.spread().map(|s| self.collect_expr(s));
262 Expr::RecordLit { path, fields, spread }
263 } else {
264 Expr::RecordLit { path, fields: Vec::new(), spread: None }
265 };
266
267 let res = self.alloc_expr(record_lit, syntax_ptr);
268 for (i, ptr) in field_ptrs.into_iter().enumerate() {
269 self.source_map.field_map.insert((res, i), ptr);
270 }
271 res
272 }
273 ast::Expr::FieldExpr(e) => {
274 let expr = self.collect_expr_opt(e.expr());
275 let name = match e.field_access() {
276 Some(kind) => kind.as_name(),
277 _ => Name::missing(),
278 };
279 self.alloc_expr(Expr::Field { expr, name }, syntax_ptr)
280 }
281 ast::Expr::AwaitExpr(e) => {
282 let expr = self.collect_expr_opt(e.expr());
283 self.alloc_expr(Expr::Await { expr }, syntax_ptr)
284 }
285 ast::Expr::TryExpr(e) => {
286 let expr = self.collect_expr_opt(e.expr());
287 self.alloc_expr(Expr::Try { expr }, syntax_ptr)
288 }
289 ast::Expr::CastExpr(e) => {
290 let expr = self.collect_expr_opt(e.expr());
291 let type_ref = TypeRef::from_ast_opt(e.type_ref());
292 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
293 }
294 ast::Expr::RefExpr(e) => {
295 let expr = self.collect_expr_opt(e.expr());
296 let mutability = Mutability::from_mutable(e.is_mut());
297 self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr)
298 }
299 ast::Expr::PrefixExpr(e) => {
300 let expr = self.collect_expr_opt(e.expr());
301 if let Some(op) = e.op_kind() {
302 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
303 } else {
304 self.alloc_expr(Expr::Missing, syntax_ptr)
305 }
306 }
307 ast::Expr::LambdaExpr(e) => {
308 let mut args = Vec::new();
309 let mut arg_types = Vec::new();
310 if let Some(pl) = e.param_list() {
311 for param in pl.params() {
312 let pat = self.collect_pat_opt(param.pat());
313 let type_ref = param.ascribed_type().map(TypeRef::from_ast);
314 args.push(pat);
315 arg_types.push(type_ref);
316 }
317 }
318 let body = self.collect_expr_opt(e.body());
319 self.alloc_expr(Expr::Lambda { args, arg_types, body }, syntax_ptr)
320 }
321 ast::Expr::BinExpr(e) => {
322 let lhs = self.collect_expr_opt(e.lhs());
323 let rhs = self.collect_expr_opt(e.rhs());
324 let op = e.op_kind().map(BinaryOp::from);
325 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
326 }
327 ast::Expr::TupleExpr(e) => {
328 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect();
329 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
330 }
331
332 ast::Expr::ArrayExpr(e) => {
333 let kind = e.kind();
334
335 match kind {
336 ArrayExprKind::ElementList(e) => {
337 let exprs = e.map(|expr| self.collect_expr(expr)).collect();
338 self.alloc_expr(Expr::Array(Array::ElementList(exprs)), syntax_ptr)
339 }
340 ArrayExprKind::Repeat { initializer, repeat } => {
341 let initializer = self.collect_expr_opt(initializer);
342 let repeat = self.collect_expr_opt(repeat);
343 self.alloc_expr(
344 Expr::Array(Array::Repeat { initializer, repeat }),
345 syntax_ptr,
346 )
347 }
348 }
349 }
350
351 ast::Expr::Literal(e) => {
352 let lit = match e.kind() {
353 LiteralKind::IntNumber { suffix } => {
354 let known_name = suffix
355 .and_then(|it| IntTy::from_suffix(&it).map(UncertainIntTy::Known));
356
357 Literal::Int(
358 Default::default(),
359 known_name.unwrap_or(UncertainIntTy::Unknown),
360 )
361 }
362 LiteralKind::FloatNumber { suffix } => {
363 let known_name = suffix
364 .and_then(|it| FloatTy::from_suffix(&it).map(UncertainFloatTy::Known));
365
366 Literal::Float(
367 Default::default(),
368 known_name.unwrap_or(UncertainFloatTy::Unknown),
369 )
370 }
371 LiteralKind::ByteString => Literal::ByteString(Default::default()),
372 LiteralKind::String => Literal::String(Default::default()),
373 LiteralKind::Byte => {
374 Literal::Int(Default::default(), UncertainIntTy::Known(IntTy::u8()))
375 }
376 LiteralKind::Bool => Literal::Bool(Default::default()),
377 LiteralKind::Char => Literal::Char(Default::default()),
378 };
379 self.alloc_expr(Expr::Literal(lit), syntax_ptr)
380 }
381 ast::Expr::IndexExpr(e) => {
382 let base = self.collect_expr_opt(e.base());
383 let index = self.collect_expr_opt(e.index());
384 self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
385 }
386
387 // FIXME implement HIR for these:
388 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
389 ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
390 ast::Expr::MacroCall(e) => {
391 let ast_id = self
392 .db
393 .ast_id_map(self.current_file_id)
394 .ast_id(&e)
395 .with_file_id(self.current_file_id);
396
397 if let Some(path) = e.path().and_then(Path::from_ast) {
398 if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) {
399 let call_id = MacroCallLoc { def: def.id, ast_id }.id(self.db);
400 let file_id = call_id.as_file(MacroFileKind::Expr);
401 if let Some(node) = self.db.parse_or_expand(file_id) {
402 if let Some(expr) = ast::Expr::cast(node) {
403 log::debug!("macro expansion {:#?}", expr.syntax());
404 let old_file_id =
405 std::mem::replace(&mut self.current_file_id, file_id);
406 let id = self.collect_expr(expr);
407 self.current_file_id = old_file_id;
408 return id;
409 }
410 }
411 }
412 }
413 // FIXME: Instead of just dropping the error from expansion
414 // report it
415 self.alloc_expr(Expr::Missing, syntax_ptr)
416 }
417 }
418 }
419
420 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
421 if let Some(expr) = expr {
422 self.collect_expr(expr)
423 } else {
424 self.exprs.alloc(Expr::Missing)
425 }
426 }
427
428 fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId {
429 let syntax_node_ptr = AstPtr::new(&expr.clone().into());
430 let block = match expr.block() {
431 Some(block) => block,
432 None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
433 };
434 let statements = block
435 .statements()
436 .map(|s| match s {
437 ast::Stmt::LetStmt(stmt) => {
438 let pat = self.collect_pat_opt(stmt.pat());
439 let type_ref = stmt.ascribed_type().map(TypeRef::from_ast);
440 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
441 Statement::Let { pat, type_ref, initializer }
442 }
443 ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())),
444 })
445 .collect();
446 let tail = block.expr().map(|e| self.collect_expr(e));
447 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
448 }
449
450 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
451 if let Some(block) = expr {
452 self.collect_block(block)
453 } else {
454 self.exprs.alloc(Expr::Missing)
455 }
456 }
457
458 fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
459 let pattern = match &pat {
460 ast::Pat::BindPat(bp) => {
461 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
462 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref());
463 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat));
464 Pat::Bind { name, mode: annotation, subpat }
465 }
466 ast::Pat::TupleStructPat(p) => {
467 let path = p.path().and_then(Path::from_ast);
468 let args = p.args().map(|p| self.collect_pat(p)).collect();
469 Pat::TupleStruct { path, args }
470 }
471 ast::Pat::RefPat(p) => {
472 let pat = self.collect_pat_opt(p.pat());
473 let mutability = Mutability::from_mutable(p.is_mut());
474 Pat::Ref { pat, mutability }
475 }
476 ast::Pat::PathPat(p) => {
477 let path = p.path().and_then(Path::from_ast);
478 path.map(Pat::Path).unwrap_or(Pat::Missing)
479 }
480 ast::Pat::TuplePat(p) => {
481 let args = p.args().map(|p| self.collect_pat(p)).collect();
482 Pat::Tuple(args)
483 }
484 ast::Pat::PlaceholderPat(_) => Pat::Wild,
485 ast::Pat::RecordPat(p) => {
486 let path = p.path().and_then(Path::from_ast);
487 let record_field_pat_list =
488 p.record_field_pat_list().expect("every struct should have a field list");
489 let mut fields: Vec<_> = record_field_pat_list
490 .bind_pats()
491 .filter_map(|bind_pat| {
492 let ast_pat =
493 ast::Pat::cast(bind_pat.syntax().clone()).expect("bind pat is a pat");
494 let pat = self.collect_pat(ast_pat);
495 let name = bind_pat.name()?.as_name();
496 Some(RecordFieldPat { name, pat })
497 })
498 .collect();
499 let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
500 let ast_pat = f.pat()?;
501 let pat = self.collect_pat(ast_pat);
502 let name = f.name()?.as_name();
503 Some(RecordFieldPat { name, pat })
504 });
505 fields.extend(iter);
506
507 Pat::Struct { path, args: fields }
508 }
509
510 // FIXME: implement
511 ast::Pat::BoxPat(_) => Pat::Missing,
512 ast::Pat::LiteralPat(_) => Pat::Missing,
513 ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing,
514 };
515 let ptr = AstPtr::new(&pat);
516 self.alloc_pat(pattern, Either::A(ptr))
517 }
518
519 fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId {
520 if let Some(pat) = pat {
521 self.collect_pat(pat)
522 } else {
523 self.pats.alloc(Pat::Missing)
524 }
525 }
526
527 fn collect_const_body(&mut self, node: ast::ConstDef) {
528 let body = self.collect_expr_opt(node.body());
529 self.body_expr = Some(body);
530 }
531
532 fn collect_static_body(&mut self, node: ast::StaticDef) {
533 let body = self.collect_expr_opt(node.body());
534 self.body_expr = Some(body);
535 }
536
537 fn collect_fn_body(&mut self, node: ast::FnDef) {
538 if let Some(param_list) = node.param_list() {
539 if let Some(self_param) = param_list.self_param() {
540 let ptr = AstPtr::new(&self_param);
541 let param_pat = self.alloc_pat(
542 Pat::Bind {
543 name: SELF_PARAM,
544 mode: BindingAnnotation::Unannotated,
545 subpat: None,
546 },
547 Either::B(ptr),
548 );
549 self.params.push(param_pat);
550 }
551
552 for param in param_list.params() {
553 let pat = if let Some(pat) = param.pat() {
554 pat
555 } else {
556 continue;
557 };
558 let param_pat = self.collect_pat(pat);
559 self.params.push(param_pat);
560 }
561 };
562
563 let body = self.collect_block_opt(node.body());
564 self.body_expr = Some(body);
565 }
566
567 fn finish(self) -> (Body, BodySourceMap) {
568 let body = Body {
569 owner: self.owner,
570 exprs: self.exprs,
571 pats: self.pats,
572 params: self.params,
573 body_expr: self.body_expr.expect("A body should have been collected"),
574 };
575 (body, self.source_map)
576 }
577}
578
579impl From<ast::BinOp> for BinaryOp {
580 fn from(ast_op: ast::BinOp) -> Self {
581 match ast_op {
582 ast::BinOp::BooleanOr => BinaryOp::LogicOp(LogicOp::Or),
583 ast::BinOp::BooleanAnd => BinaryOp::LogicOp(LogicOp::And),
584 ast::BinOp::EqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
585 ast::BinOp::NegatedEqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: true }),
586 ast::BinOp::LesserEqualTest => {
587 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false })
588 }
589 ast::BinOp::GreaterEqualTest => {
590 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false })
591 }
592 ast::BinOp::LesserTest => {
593 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true })
594 }
595 ast::BinOp::GreaterTest => {
596 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true })
597 }
598 ast::BinOp::Addition => BinaryOp::ArithOp(ArithOp::Add),
599 ast::BinOp::Multiplication => BinaryOp::ArithOp(ArithOp::Mul),
600 ast::BinOp::Subtraction => BinaryOp::ArithOp(ArithOp::Sub),
601 ast::BinOp::Division => BinaryOp::ArithOp(ArithOp::Div),
602 ast::BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Rem),
603 ast::BinOp::LeftShift => BinaryOp::ArithOp(ArithOp::Shl),
604 ast::BinOp::RightShift => BinaryOp::ArithOp(ArithOp::Shr),
605 ast::BinOp::BitwiseXor => BinaryOp::ArithOp(ArithOp::BitXor),
606 ast::BinOp::BitwiseOr => BinaryOp::ArithOp(ArithOp::BitOr),
607 ast::BinOp::BitwiseAnd => BinaryOp::ArithOp(ArithOp::BitAnd),
608 ast::BinOp::Assignment => BinaryOp::Assignment { op: None },
609 ast::BinOp::AddAssign => BinaryOp::Assignment { op: Some(ArithOp::Add) },
610 ast::BinOp::DivAssign => BinaryOp::Assignment { op: Some(ArithOp::Div) },
611 ast::BinOp::MulAssign => BinaryOp::Assignment { op: Some(ArithOp::Mul) },
612 ast::BinOp::RemAssign => BinaryOp::Assignment { op: Some(ArithOp::Rem) },
613 ast::BinOp::ShlAssign => BinaryOp::Assignment { op: Some(ArithOp::Shl) },
614 ast::BinOp::ShrAssign => BinaryOp::Assignment { op: Some(ArithOp::Shr) },
615 ast::BinOp::SubAssign => BinaryOp::Assignment { op: Some(ArithOp::Sub) },
616 ast::BinOp::BitOrAssign => BinaryOp::Assignment { op: Some(ArithOp::BitOr) },
617 ast::BinOp::BitAndAssign => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) },
618 ast::BinOp::BitXorAssign => BinaryOp::Assignment { op: Some(ArithOp::BitXor) },
619 }
620 }
621}
622
623pub(crate) fn body_with_source_map_query(
624 db: &impl HirDatabase,
625 def: DefWithBody,
626) -> (Arc<Body>, Arc<BodySourceMap>) {
627 let mut collector;
628
629 match def {
630 DefWithBody::Const(ref c) => {
631 let src = c.source(db);
632 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
633 collector.collect_const_body(src.ast)
634 }
635 DefWithBody::Function(ref f) => {
636 let src = f.source(db);
637 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
638 collector.collect_fn_body(src.ast)
639 }
640 DefWithBody::Static(ref s) => {
641 let src = s.source(db);
642 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
643 collector.collect_static_body(src.ast)
644 }
645 }
646
647 let (body, source_map) = collector.finish();
648 (Arc::new(body), Arc::new(source_map))
649}
650
651pub(crate) fn body_hir_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<Body> {
652 db.body_with_source_map(def).0
653}