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.rs667
-rw-r--r--crates/ra_hir/src/expr/lower.rs652
-rw-r--r--crates/ra_hir/src/ty/infer.rs8
4 files changed, 672 insertions, 659 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..bfd250f38 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.
@@ -482,7 +472,7 @@ pub enum Pat {
482 Missing, 472 Missing,
483 Wild, 473 Wild,
484 Tuple(Vec<PatId>), 474 Tuple(Vec<PatId>),
485 Struct { 475 Record {
486 path: Option<Path>, 476 path: Option<Path>,
487 args: Vec<RecordFieldPat>, 477 args: Vec<RecordFieldPat>,
488 // FIXME: 'ellipsis' option 478 // FIXME: 'ellipsis' option
@@ -528,638 +518,9 @@ impl Pat {
528 let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter()); 518 let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter());
529 total_iter.copied().for_each(f); 519 total_iter.copied().for_each(f);
530 } 520 }
531 Pat::Struct { args, .. } => { 521 Pat::Record { args, .. } => {
532 args.iter().map(|f| f.pat).for_each(f); 522 args.iter().map(|f| f.pat).for_each(f);
533 } 523 }
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..f6a75a379
--- /dev/null
+++ b/crates/ra_hir/src/expr/lower.rs
@@ -0,0 +1,652 @@
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, Literal,
24 LogicOp, MatchArm, Ordering, Pat, PatId, PatPtr, RecordFieldPat, RecordLitField, Statement,
25};
26
27pub(crate) struct ExprCollector<DB> {
28 db: DB,
29 owner: DefWithBody,
30 exprs: Arena<ExprId, Expr>,
31 pats: Arena<PatId, Pat>,
32 source_map: BodySourceMap,
33 params: Vec<PatId>,
34 body_expr: Option<ExprId>,
35 resolver: Resolver,
36 // Expr collector expands macros along the way. original points to the file
37 // we started with, current points to the current macro expansion. source
38 // maps don't support macros yet, so we only record info into source map if
39 // current == original (see #1196)
40 original_file_id: HirFileId,
41 current_file_id: HirFileId,
42}
43
44impl<'a, DB> ExprCollector<&'a DB>
45where
46 DB: HirDatabase,
47{
48 fn new(owner: DefWithBody, file_id: HirFileId, resolver: Resolver, db: &'a DB) -> Self {
49 ExprCollector {
50 owner,
51 resolver,
52 db,
53 exprs: Arena::default(),
54 pats: Arena::default(),
55 source_map: BodySourceMap::default(),
56 params: Vec::new(),
57 body_expr: None,
58 original_file_id: file_id,
59 current_file_id: file_id,
60 }
61 }
62 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
63 let ptr = Either::A(ptr);
64 let id = self.exprs.alloc(expr);
65 if self.current_file_id == self.original_file_id {
66 self.source_map.expr_map.insert(ptr, id);
67 self.source_map.expr_map_back.insert(id, ptr);
68 }
69 id
70 }
71
72 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
73 let id = self.pats.alloc(pat);
74
75 if self.current_file_id == self.original_file_id {
76 self.source_map.pat_map.insert(ptr, id);
77 self.source_map.pat_map_back.insert(id, ptr);
78 }
79
80 id
81 }
82
83 fn empty_block(&mut self) -> ExprId {
84 let block = Expr::Block { statements: Vec::new(), tail: None };
85 self.exprs.alloc(block)
86 }
87
88 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
89 let syntax_ptr = AstPtr::new(&expr);
90 match expr {
91 ast::Expr::IfExpr(e) => {
92 let then_branch = self.collect_block_opt(e.then_branch());
93
94 let else_branch = e.else_branch().map(|b| match b {
95 ast::ElseBranch::Block(it) => self.collect_block(it),
96 ast::ElseBranch::IfExpr(elif) => {
97 let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap();
98 self.collect_expr(expr)
99 }
100 });
101
102 let condition = match e.condition() {
103 None => self.exprs.alloc(Expr::Missing),
104 Some(condition) => match condition.pat() {
105 None => self.collect_expr_opt(condition.expr()),
106 // if let -- desugar to match
107 Some(pat) => {
108 let pat = self.collect_pat(pat);
109 let match_expr = self.collect_expr_opt(condition.expr());
110 let placeholder_pat = self.pats.alloc(Pat::Missing);
111 let arms = vec![
112 MatchArm { pats: vec![pat], expr: then_branch, guard: None },
113 MatchArm {
114 pats: vec![placeholder_pat],
115 expr: else_branch.unwrap_or_else(|| self.empty_block()),
116 guard: None,
117 },
118 ];
119 return self
120 .alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr);
121 }
122 },
123 };
124
125 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
126 }
127 ast::Expr::TryBlockExpr(e) => {
128 let body = self.collect_block_opt(e.body());
129 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
130 }
131 ast::Expr::BlockExpr(e) => self.collect_block(e),
132 ast::Expr::LoopExpr(e) => {
133 let body = self.collect_block_opt(e.loop_body());
134 self.alloc_expr(Expr::Loop { body }, syntax_ptr)
135 }
136 ast::Expr::WhileExpr(e) => {
137 let body = self.collect_block_opt(e.loop_body());
138
139 let condition = match e.condition() {
140 None => self.exprs.alloc(Expr::Missing),
141 Some(condition) => match condition.pat() {
142 None => self.collect_expr_opt(condition.expr()),
143 // if let -- desugar to match
144 Some(pat) => {
145 tested_by!(infer_while_let);
146 let pat = self.collect_pat(pat);
147 let match_expr = self.collect_expr_opt(condition.expr());
148 let placeholder_pat = self.pats.alloc(Pat::Missing);
149 let break_ = self.exprs.alloc(Expr::Break { expr: None });
150 let arms = vec![
151 MatchArm { pats: vec![pat], expr: body, guard: None },
152 MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None },
153 ];
154 let match_expr =
155 self.exprs.alloc(Expr::Match { expr: match_expr, arms });
156 return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr);
157 }
158 },
159 };
160
161 self.alloc_expr(Expr::While { condition, body }, syntax_ptr)
162 }
163 ast::Expr::ForExpr(e) => {
164 let iterable = self.collect_expr_opt(e.iterable());
165 let pat = self.collect_pat_opt(e.pat());
166 let body = self.collect_block_opt(e.loop_body());
167 self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr)
168 }
169 ast::Expr::CallExpr(e) => {
170 let callee = self.collect_expr_opt(e.expr());
171 let args = if let Some(arg_list) = e.arg_list() {
172 arg_list.args().map(|e| self.collect_expr(e)).collect()
173 } else {
174 Vec::new()
175 };
176 self.alloc_expr(Expr::Call { callee, args }, syntax_ptr)
177 }
178 ast::Expr::MethodCallExpr(e) => {
179 let receiver = self.collect_expr_opt(e.expr());
180 let args = if let Some(arg_list) = e.arg_list() {
181 arg_list.args().map(|e| self.collect_expr(e)).collect()
182 } else {
183 Vec::new()
184 };
185 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
186 let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast);
187 self.alloc_expr(
188 Expr::MethodCall { receiver, method_name, args, generic_args },
189 syntax_ptr,
190 )
191 }
192 ast::Expr::MatchExpr(e) => {
193 let expr = self.collect_expr_opt(e.expr());
194 let arms = if let Some(match_arm_list) = e.match_arm_list() {
195 match_arm_list
196 .arms()
197 .map(|arm| MatchArm {
198 pats: arm.pats().map(|p| self.collect_pat(p)).collect(),
199 expr: self.collect_expr_opt(arm.expr()),
200 guard: arm
201 .guard()
202 .and_then(|guard| guard.expr())
203 .map(|e| self.collect_expr(e)),
204 })
205 .collect()
206 } else {
207 Vec::new()
208 };
209 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
210 }
211 ast::Expr::PathExpr(e) => {
212 let path =
213 e.path().and_then(Path::from_ast).map(Expr::Path).unwrap_or(Expr::Missing);
214 self.alloc_expr(path, syntax_ptr)
215 }
216 ast::Expr::ContinueExpr(_e) => {
217 // FIXME: labels
218 self.alloc_expr(Expr::Continue, syntax_ptr)
219 }
220 ast::Expr::BreakExpr(e) => {
221 let expr = e.expr().map(|e| self.collect_expr(e));
222 self.alloc_expr(Expr::Break { expr }, syntax_ptr)
223 }
224 ast::Expr::ParenExpr(e) => {
225 let inner = self.collect_expr_opt(e.expr());
226 // make the paren expr point to the inner expression as well
227 self.source_map.expr_map.insert(Either::A(syntax_ptr), inner);
228 inner
229 }
230 ast::Expr::ReturnExpr(e) => {
231 let expr = e.expr().map(|e| self.collect_expr(e));
232 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
233 }
234 ast::Expr::RecordLit(e) => {
235 let path = e.path().and_then(Path::from_ast);
236 let mut field_ptrs = Vec::new();
237 let record_lit = if let Some(nfl) = e.record_field_list() {
238 let fields = nfl
239 .fields()
240 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
241 .map(|field| RecordLitField {
242 name: field
243 .name_ref()
244 .map(|nr| nr.as_name())
245 .unwrap_or_else(Name::missing),
246 expr: if let Some(e) = field.expr() {
247 self.collect_expr(e)
248 } else if let Some(nr) = field.name_ref() {
249 // field shorthand
250 let id = self.exprs.alloc(Expr::Path(Path::from_name_ref(&nr)));
251 let ptr = Either::B(AstPtr::new(&field));
252 self.source_map.expr_map.insert(ptr, id);
253 self.source_map.expr_map_back.insert(id, ptr);
254 id
255 } else {
256 self.exprs.alloc(Expr::Missing)
257 },
258 })
259 .collect();
260 let spread = nfl.spread().map(|s| self.collect_expr(s));
261 Expr::RecordLit { path, fields, spread }
262 } else {
263 Expr::RecordLit { path, fields: Vec::new(), spread: None }
264 };
265
266 let res = self.alloc_expr(record_lit, syntax_ptr);
267 for (i, ptr) in field_ptrs.into_iter().enumerate() {
268 self.source_map.field_map.insert((res, i), ptr);
269 }
270 res
271 }
272 ast::Expr::FieldExpr(e) => {
273 let expr = self.collect_expr_opt(e.expr());
274 let name = match e.field_access() {
275 Some(kind) => kind.as_name(),
276 _ => Name::missing(),
277 };
278 self.alloc_expr(Expr::Field { expr, name }, syntax_ptr)
279 }
280 ast::Expr::AwaitExpr(e) => {
281 let expr = self.collect_expr_opt(e.expr());
282 self.alloc_expr(Expr::Await { expr }, syntax_ptr)
283 }
284 ast::Expr::TryExpr(e) => {
285 let expr = self.collect_expr_opt(e.expr());
286 self.alloc_expr(Expr::Try { expr }, syntax_ptr)
287 }
288 ast::Expr::CastExpr(e) => {
289 let expr = self.collect_expr_opt(e.expr());
290 let type_ref = TypeRef::from_ast_opt(e.type_ref());
291 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
292 }
293 ast::Expr::RefExpr(e) => {
294 let expr = self.collect_expr_opt(e.expr());
295 let mutability = Mutability::from_mutable(e.is_mut());
296 self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr)
297 }
298 ast::Expr::PrefixExpr(e) => {
299 let expr = self.collect_expr_opt(e.expr());
300 if let Some(op) = e.op_kind() {
301 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
302 } else {
303 self.alloc_expr(Expr::Missing, syntax_ptr)
304 }
305 }
306 ast::Expr::LambdaExpr(e) => {
307 let mut args = Vec::new();
308 let mut arg_types = Vec::new();
309 if let Some(pl) = e.param_list() {
310 for param in pl.params() {
311 let pat = self.collect_pat_opt(param.pat());
312 let type_ref = param.ascribed_type().map(TypeRef::from_ast);
313 args.push(pat);
314 arg_types.push(type_ref);
315 }
316 }
317 let body = self.collect_expr_opt(e.body());
318 self.alloc_expr(Expr::Lambda { args, arg_types, body }, syntax_ptr)
319 }
320 ast::Expr::BinExpr(e) => {
321 let lhs = self.collect_expr_opt(e.lhs());
322 let rhs = self.collect_expr_opt(e.rhs());
323 let op = e.op_kind().map(BinaryOp::from);
324 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
325 }
326 ast::Expr::TupleExpr(e) => {
327 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect();
328 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
329 }
330
331 ast::Expr::ArrayExpr(e) => {
332 let kind = e.kind();
333
334 match kind {
335 ArrayExprKind::ElementList(e) => {
336 let exprs = e.map(|expr| self.collect_expr(expr)).collect();
337 self.alloc_expr(Expr::Array(Array::ElementList(exprs)), syntax_ptr)
338 }
339 ArrayExprKind::Repeat { initializer, repeat } => {
340 let initializer = self.collect_expr_opt(initializer);
341 let repeat = self.collect_expr_opt(repeat);
342 self.alloc_expr(
343 Expr::Array(Array::Repeat { initializer, repeat }),
344 syntax_ptr,
345 )
346 }
347 }
348 }
349
350 ast::Expr::Literal(e) => {
351 let lit = match e.kind() {
352 LiteralKind::IntNumber { suffix } => {
353 let known_name = suffix
354 .and_then(|it| IntTy::from_suffix(&it).map(UncertainIntTy::Known));
355
356 Literal::Int(
357 Default::default(),
358 known_name.unwrap_or(UncertainIntTy::Unknown),
359 )
360 }
361 LiteralKind::FloatNumber { suffix } => {
362 let known_name = suffix
363 .and_then(|it| FloatTy::from_suffix(&it).map(UncertainFloatTy::Known));
364
365 Literal::Float(
366 Default::default(),
367 known_name.unwrap_or(UncertainFloatTy::Unknown),
368 )
369 }
370 LiteralKind::ByteString => Literal::ByteString(Default::default()),
371 LiteralKind::String => Literal::String(Default::default()),
372 LiteralKind::Byte => {
373 Literal::Int(Default::default(), UncertainIntTy::Known(IntTy::u8()))
374 }
375 LiteralKind::Bool => Literal::Bool(Default::default()),
376 LiteralKind::Char => Literal::Char(Default::default()),
377 };
378 self.alloc_expr(Expr::Literal(lit), syntax_ptr)
379 }
380 ast::Expr::IndexExpr(e) => {
381 let base = self.collect_expr_opt(e.base());
382 let index = self.collect_expr_opt(e.index());
383 self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
384 }
385
386 // FIXME implement HIR for these:
387 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
388 ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
389 ast::Expr::MacroCall(e) => {
390 let ast_id = self
391 .db
392 .ast_id_map(self.current_file_id)
393 .ast_id(&e)
394 .with_file_id(self.current_file_id);
395
396 if let Some(path) = e.path().and_then(Path::from_ast) {
397 if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) {
398 let call_id = MacroCallLoc { def: def.id, ast_id }.id(self.db);
399 let file_id = call_id.as_file(MacroFileKind::Expr);
400 if let Some(node) = self.db.parse_or_expand(file_id) {
401 if let Some(expr) = ast::Expr::cast(node) {
402 log::debug!("macro expansion {:#?}", expr.syntax());
403 let old_file_id =
404 std::mem::replace(&mut self.current_file_id, file_id);
405 let id = self.collect_expr(expr);
406 self.current_file_id = old_file_id;
407 return id;
408 }
409 }
410 }
411 }
412 // FIXME: Instead of just dropping the error from expansion
413 // report it
414 self.alloc_expr(Expr::Missing, syntax_ptr)
415 }
416 }
417 }
418
419 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
420 if let Some(expr) = expr {
421 self.collect_expr(expr)
422 } else {
423 self.exprs.alloc(Expr::Missing)
424 }
425 }
426
427 fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId {
428 let syntax_node_ptr = AstPtr::new(&expr.clone().into());
429 let block = match expr.block() {
430 Some(block) => block,
431 None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
432 };
433 let statements = block
434 .statements()
435 .map(|s| match s {
436 ast::Stmt::LetStmt(stmt) => {
437 let pat = self.collect_pat_opt(stmt.pat());
438 let type_ref = stmt.ascribed_type().map(TypeRef::from_ast);
439 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
440 Statement::Let { pat, type_ref, initializer }
441 }
442 ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())),
443 })
444 .collect();
445 let tail = block.expr().map(|e| self.collect_expr(e));
446 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
447 }
448
449 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
450 if let Some(block) = expr {
451 self.collect_block(block)
452 } else {
453 self.exprs.alloc(Expr::Missing)
454 }
455 }
456
457 fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
458 let pattern = match &pat {
459 ast::Pat::BindPat(bp) => {
460 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
461 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref());
462 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat));
463 Pat::Bind { name, mode: annotation, subpat }
464 }
465 ast::Pat::TupleStructPat(p) => {
466 let path = p.path().and_then(Path::from_ast);
467 let args = p.args().map(|p| self.collect_pat(p)).collect();
468 Pat::TupleStruct { path, args }
469 }
470 ast::Pat::RefPat(p) => {
471 let pat = self.collect_pat_opt(p.pat());
472 let mutability = Mutability::from_mutable(p.is_mut());
473 Pat::Ref { pat, mutability }
474 }
475 ast::Pat::PathPat(p) => {
476 let path = p.path().and_then(Path::from_ast);
477 path.map(Pat::Path).unwrap_or(Pat::Missing)
478 }
479 ast::Pat::TuplePat(p) => {
480 let args = p.args().map(|p| self.collect_pat(p)).collect();
481 Pat::Tuple(args)
482 }
483 ast::Pat::PlaceholderPat(_) => Pat::Wild,
484 ast::Pat::RecordPat(p) => {
485 let path = p.path().and_then(Path::from_ast);
486 let record_field_pat_list =
487 p.record_field_pat_list().expect("every struct should have a field list");
488 let mut fields: Vec<_> = record_field_pat_list
489 .bind_pats()
490 .filter_map(|bind_pat| {
491 let ast_pat =
492 ast::Pat::cast(bind_pat.syntax().clone()).expect("bind pat is a pat");
493 let pat = self.collect_pat(ast_pat);
494 let name = bind_pat.name()?.as_name();
495 Some(RecordFieldPat { name, pat })
496 })
497 .collect();
498 let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
499 let ast_pat = f.pat()?;
500 let pat = self.collect_pat(ast_pat);
501 let name = f.name()?.as_name();
502 Some(RecordFieldPat { name, pat })
503 });
504 fields.extend(iter);
505
506 Pat::Record { path, args: fields }
507 }
508
509 // FIXME: implement
510 ast::Pat::BoxPat(_) => Pat::Missing,
511 ast::Pat::LiteralPat(_) => Pat::Missing,
512 ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing,
513 };
514 let ptr = AstPtr::new(&pat);
515 self.alloc_pat(pattern, Either::A(ptr))
516 }
517
518 fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId {
519 if let Some(pat) = pat {
520 self.collect_pat(pat)
521 } else {
522 self.pats.alloc(Pat::Missing)
523 }
524 }
525
526 fn collect_const_body(&mut self, node: ast::ConstDef) {
527 let body = self.collect_expr_opt(node.body());
528 self.body_expr = Some(body);
529 }
530
531 fn collect_static_body(&mut self, node: ast::StaticDef) {
532 let body = self.collect_expr_opt(node.body());
533 self.body_expr = Some(body);
534 }
535
536 fn collect_fn_body(&mut self, node: ast::FnDef) {
537 if let Some(param_list) = node.param_list() {
538 if let Some(self_param) = param_list.self_param() {
539 let ptr = AstPtr::new(&self_param);
540 let param_pat = self.alloc_pat(
541 Pat::Bind {
542 name: SELF_PARAM,
543 mode: BindingAnnotation::Unannotated,
544 subpat: None,
545 },
546 Either::B(ptr),
547 );
548 self.params.push(param_pat);
549 }
550
551 for param in param_list.params() {
552 let pat = if let Some(pat) = param.pat() {
553 pat
554 } else {
555 continue;
556 };
557 let param_pat = self.collect_pat(pat);
558 self.params.push(param_pat);
559 }
560 };
561
562 let body = self.collect_block_opt(node.body());
563 self.body_expr = Some(body);
564 }
565
566 fn finish(self) -> (Body, BodySourceMap) {
567 let body = Body {
568 owner: self.owner,
569 exprs: self.exprs,
570 pats: self.pats,
571 params: self.params,
572 body_expr: self.body_expr.expect("A body should have been collected"),
573 };
574 (body, self.source_map)
575 }
576}
577
578impl From<ast::BinOp> for BinaryOp {
579 fn from(ast_op: ast::BinOp) -> Self {
580 match ast_op {
581 ast::BinOp::BooleanOr => BinaryOp::LogicOp(LogicOp::Or),
582 ast::BinOp::BooleanAnd => BinaryOp::LogicOp(LogicOp::And),
583 ast::BinOp::EqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
584 ast::BinOp::NegatedEqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: true }),
585 ast::BinOp::LesserEqualTest => {
586 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false })
587 }
588 ast::BinOp::GreaterEqualTest => {
589 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false })
590 }
591 ast::BinOp::LesserTest => {
592 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true })
593 }
594 ast::BinOp::GreaterTest => {
595 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true })
596 }
597 ast::BinOp::Addition => BinaryOp::ArithOp(ArithOp::Add),
598 ast::BinOp::Multiplication => BinaryOp::ArithOp(ArithOp::Mul),
599 ast::BinOp::Subtraction => BinaryOp::ArithOp(ArithOp::Sub),
600 ast::BinOp::Division => BinaryOp::ArithOp(ArithOp::Div),
601 ast::BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Rem),
602 ast::BinOp::LeftShift => BinaryOp::ArithOp(ArithOp::Shl),
603 ast::BinOp::RightShift => BinaryOp::ArithOp(ArithOp::Shr),
604 ast::BinOp::BitwiseXor => BinaryOp::ArithOp(ArithOp::BitXor),
605 ast::BinOp::BitwiseOr => BinaryOp::ArithOp(ArithOp::BitOr),
606 ast::BinOp::BitwiseAnd => BinaryOp::ArithOp(ArithOp::BitAnd),
607 ast::BinOp::Assignment => BinaryOp::Assignment { op: None },
608 ast::BinOp::AddAssign => BinaryOp::Assignment { op: Some(ArithOp::Add) },
609 ast::BinOp::DivAssign => BinaryOp::Assignment { op: Some(ArithOp::Div) },
610 ast::BinOp::MulAssign => BinaryOp::Assignment { op: Some(ArithOp::Mul) },
611 ast::BinOp::RemAssign => BinaryOp::Assignment { op: Some(ArithOp::Rem) },
612 ast::BinOp::ShlAssign => BinaryOp::Assignment { op: Some(ArithOp::Shl) },
613 ast::BinOp::ShrAssign => BinaryOp::Assignment { op: Some(ArithOp::Shr) },
614 ast::BinOp::SubAssign => BinaryOp::Assignment { op: Some(ArithOp::Sub) },
615 ast::BinOp::BitOrAssign => BinaryOp::Assignment { op: Some(ArithOp::BitOr) },
616 ast::BinOp::BitAndAssign => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) },
617 ast::BinOp::BitXorAssign => BinaryOp::Assignment { op: Some(ArithOp::BitXor) },
618 }
619 }
620}
621
622pub(crate) fn body_with_source_map_query(
623 db: &impl HirDatabase,
624 def: DefWithBody,
625) -> (Arc<Body>, Arc<BodySourceMap>) {
626 let mut collector;
627
628 match def {
629 DefWithBody::Const(ref c) => {
630 let src = c.source(db);
631 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
632 collector.collect_const_body(src.ast)
633 }
634 DefWithBody::Function(ref f) => {
635 let src = f.source(db);
636 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
637 collector.collect_fn_body(src.ast)
638 }
639 DefWithBody::Static(ref s) => {
640 let src = s.source(db);
641 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
642 collector.collect_static_body(src.ast)
643 }
644 }
645
646 let (body, source_map) = collector.finish();
647 (Arc::new(body), Arc::new(source_map))
648}
649
650pub(crate) fn body_hir_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<Body> {
651 db.body_with_source_map(def).0
652}
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 9ba146299..b89a40b4b 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -749,7 +749,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
749 let is_non_ref_pat = match &body[pat] { 749 let is_non_ref_pat = match &body[pat] {
750 Pat::Tuple(..) 750 Pat::Tuple(..)
751 | Pat::TupleStruct { .. } 751 | Pat::TupleStruct { .. }
752 | Pat::Struct { .. } 752 | Pat::Record { .. }
753 | Pat::Range { .. } 753 | Pat::Range { .. }
754 | Pat::Slice { .. } => true, 754 | Pat::Slice { .. } => true,
755 // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented. 755 // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented.
@@ -806,10 +806,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
806 let subty = self.infer_pat(*pat, expectation, default_bm); 806 let subty = self.infer_pat(*pat, expectation, default_bm);
807 Ty::apply_one(TypeCtor::Ref(*mutability), subty) 807 Ty::apply_one(TypeCtor::Ref(*mutability), subty)
808 } 808 }
809 Pat::TupleStruct { path: ref p, args: ref subpats } => { 809 Pat::TupleStruct { path: p, args: subpats } => {
810 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm) 810 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm)
811 } 811 }
812 Pat::Struct { path: ref p, args: ref fields } => { 812 Pat::Record { path: p, args: fields } => {
813 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) 813 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat)
814 } 814 }
815 Pat::Path(path) => { 815 Pat::Path(path) => {
@@ -817,7 +817,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
817 let resolver = self.resolver.clone(); 817 let resolver = self.resolver.clone();
818 self.infer_path_expr(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown) 818 self.infer_path_expr(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown)
819 } 819 }
820 Pat::Bind { mode, name: _name, subpat } => { 820 Pat::Bind { mode, name: _, subpat } => {
821 let mode = if mode == &BindingAnnotation::Unannotated { 821 let mode = if mode == &BindingAnnotation::Unannotated {
822 default_bm 822 default_bm
823 } else { 823 } else {