aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/expr.rs33
-rw-r--r--crates/ra_hir/src/expr/lower.rs228
3 files changed, 136 insertions, 129 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index f669ab969..7b7974f5b 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::lower::body_with_source_map_query)] 172 #[salsa::invoke(crate::expr::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::lower::body_hir_query)] 178 #[salsa::invoke(crate::expr::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 bfd250f38..5f6a4b320 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -12,7 +12,7 @@ use crate::{
12 path::GenericArgs, 12 path::GenericArgs,
13 ty::primitive::{UncertainFloatTy, UncertainIntTy}, 13 ty::primitive::{UncertainFloatTy, UncertainIntTy},
14 type_ref::{Mutability, TypeRef}, 14 type_ref::{Mutability, TypeRef},
15 DefWithBody, Either, HirDatabase, Name, Path, Resolver, 15 DefWithBody, Either, HasSource, HirDatabase, Name, Path, Resolver,
16}; 16};
17 17
18pub use self::scope::ExprScopes; 18pub use self::scope::ExprScopes;
@@ -524,3 +524,34 @@ impl Pat {
524 } 524 }
525 } 525 }
526} 526}
527
528// Queries
529pub(crate) fn body_with_source_map_query(
530 db: &impl HirDatabase,
531 def: DefWithBody,
532) -> (Arc<Body>, Arc<BodySourceMap>) {
533 let mut params = None;
534
535 let (file_id, body) = match def {
536 DefWithBody::Function(f) => {
537 let src = f.source(db);
538 params = src.ast.param_list();
539 (src.file_id, src.ast.body().map(ast::Expr::from))
540 }
541 DefWithBody::Const(c) => {
542 let src = c.source(db);
543 (src.file_id, src.ast.body())
544 }
545 DefWithBody::Static(s) => {
546 let src = s.source(db);
547 (src.file_id, src.ast.body())
548 }
549 };
550
551 let (body, source_map) = lower::lower(db, def.resolver(db), file_id, def, params, body);
552 (Arc::new(body), Arc::new(source_map))
553}
554
555pub(crate) fn body_hir_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<Body> {
556 db.body_with_source_map(def).0
557}
diff --git a/crates/ra_hir/src/expr/lower.rs b/crates/ra_hir/src/expr/lower.rs
index f6a75a379..7b3e55b7e 100644
--- a/crates/ra_hir/src/expr/lower.rs
+++ b/crates/ra_hir/src/expr/lower.rs
@@ -1,5 +1,3 @@
1use std::sync::Arc;
2
3use ra_arena::Arena; 1use ra_arena::Arena;
4use ra_syntax::{ 2use ra_syntax::{
5 ast::{ 3 ast::{
@@ -15,8 +13,8 @@ use crate::{
15 path::GenericArgs, 13 path::GenericArgs,
16 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy}, 14 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy},
17 type_ref::TypeRef, 15 type_ref::TypeRef,
18 DefWithBody, Either, HasSource, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind, 16 DefWithBody, Either, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind, Mutability, Path,
19 Mutability, Path, Resolver, 17 Resolver,
20}; 18};
21 19
22use super::{ 20use super::{
@@ -24,14 +22,33 @@ use super::{
24 LogicOp, MatchArm, Ordering, Pat, PatId, PatPtr, RecordFieldPat, RecordLitField, Statement, 22 LogicOp, MatchArm, Ordering, Pat, PatId, PatPtr, RecordFieldPat, RecordLitField, Statement,
25}; 23};
26 24
27pub(crate) struct ExprCollector<DB> { 25pub(super) fn lower(
28 db: DB, 26 db: &impl HirDatabase,
27 resolver: Resolver,
28 file_id: HirFileId,
29 owner: DefWithBody, 29 owner: DefWithBody,
30 exprs: Arena<ExprId, Expr>, 30 params: Option<ast::ParamList>,
31 pats: Arena<PatId, Pat>, 31 body: Option<ast::Expr>,
32 source_map: BodySourceMap, 32) -> (Body, BodySourceMap) {
33 params: Vec<PatId>, 33 ExprCollector {
34 body_expr: Option<ExprId>, 34 resolver,
35 db,
36 original_file_id: file_id,
37 current_file_id: file_id,
38 source_map: BodySourceMap::default(),
39 body: Body {
40 owner,
41 exprs: Arena::default(),
42 pats: Arena::default(),
43 params: Vec::new(),
44 body_expr: ExprId((!0).into()),
45 },
46 }
47 .collect(params, body)
48}
49
50struct ExprCollector<DB> {
51 db: DB,
35 resolver: Resolver, 52 resolver: Resolver,
36 // Expr collector expands macros along the way. original points to the file 53 // Expr collector expands macros along the way. original points to the file
37 // we started with, current points to the current macro expansion. source 54 // we started with, current points to the current macro expansion. source
@@ -39,38 +56,73 @@ pub(crate) struct ExprCollector<DB> {
39 // current == original (see #1196) 56 // current == original (see #1196)
40 original_file_id: HirFileId, 57 original_file_id: HirFileId,
41 current_file_id: HirFileId, 58 current_file_id: HirFileId,
59
60 body: Body,
61 source_map: BodySourceMap,
42} 62}
43 63
44impl<'a, DB> ExprCollector<&'a DB> 64impl<'a, DB> ExprCollector<&'a DB>
45where 65where
46 DB: HirDatabase, 66 DB: HirDatabase,
47{ 67{
48 fn new(owner: DefWithBody, file_id: HirFileId, resolver: Resolver, db: &'a DB) -> Self { 68 fn collect(
49 ExprCollector { 69 mut self,
50 owner, 70 param_list: Option<ast::ParamList>,
51 resolver, 71 body: Option<ast::Expr>,
52 db, 72 ) -> (Body, BodySourceMap) {
53 exprs: Arena::default(), 73 if let Some(param_list) = param_list {
54 pats: Arena::default(), 74 if let Some(self_param) = param_list.self_param() {
55 source_map: BodySourceMap::default(), 75 let ptr = AstPtr::new(&self_param);
56 params: Vec::new(), 76 let param_pat = self.alloc_pat(
57 body_expr: None, 77 Pat::Bind {
58 original_file_id: file_id, 78 name: SELF_PARAM,
59 current_file_id: file_id, 79 mode: BindingAnnotation::Unannotated,
60 } 80 subpat: None,
81 },
82 Either::B(ptr),
83 );
84 self.body.params.push(param_pat);
85 }
86
87 for param in param_list.params() {
88 let pat = match param.pat() {
89 None => continue,
90 Some(pat) => pat,
91 };
92 let param_pat = self.collect_pat(pat);
93 self.body.params.push(param_pat);
94 }
95 };
96
97 self.body.body_expr = self.collect_expr_opt(body);
98 (self.body, self.source_map)
61 } 99 }
100
62 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 101 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
63 let ptr = Either::A(ptr); 102 let ptr = Either::A(ptr);
64 let id = self.exprs.alloc(expr); 103 let id = self.body.exprs.alloc(expr);
104 if self.current_file_id == self.original_file_id {
105 self.source_map.expr_map.insert(ptr, id);
106 self.source_map.expr_map_back.insert(id, ptr);
107 }
108 id
109 }
110 // deshugared exprs don't have ptr, that's wrong and should be fixed
111 // somehow.
112 fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
113 self.body.exprs.alloc(expr)
114 }
115 fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId {
116 let ptr = Either::B(ptr);
117 let id = self.body.exprs.alloc(expr);
65 if self.current_file_id == self.original_file_id { 118 if self.current_file_id == self.original_file_id {
66 self.source_map.expr_map.insert(ptr, id); 119 self.source_map.expr_map.insert(ptr, id);
67 self.source_map.expr_map_back.insert(id, ptr); 120 self.source_map.expr_map_back.insert(id, ptr);
68 } 121 }
69 id 122 id
70 } 123 }
71
72 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { 124 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
73 let id = self.pats.alloc(pat); 125 let id = self.body.pats.alloc(pat);
74 126
75 if self.current_file_id == self.original_file_id { 127 if self.current_file_id == self.original_file_id {
76 self.source_map.pat_map.insert(ptr, id); 128 self.source_map.pat_map.insert(ptr, id);
@@ -82,7 +134,15 @@ where
82 134
83 fn empty_block(&mut self) -> ExprId { 135 fn empty_block(&mut self) -> ExprId {
84 let block = Expr::Block { statements: Vec::new(), tail: None }; 136 let block = Expr::Block { statements: Vec::new(), tail: None };
85 self.exprs.alloc(block) 137 self.body.exprs.alloc(block)
138 }
139
140 fn missing_expr(&mut self) -> ExprId {
141 self.body.exprs.alloc(Expr::Missing)
142 }
143
144 fn missing_pat(&mut self) -> PatId {
145 self.body.pats.alloc(Pat::Missing)
86 } 146 }
87 147
88 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { 148 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
@@ -100,14 +160,14 @@ where
100 }); 160 });
101 161
102 let condition = match e.condition() { 162 let condition = match e.condition() {
103 None => self.exprs.alloc(Expr::Missing), 163 None => self.missing_expr(),
104 Some(condition) => match condition.pat() { 164 Some(condition) => match condition.pat() {
105 None => self.collect_expr_opt(condition.expr()), 165 None => self.collect_expr_opt(condition.expr()),
106 // if let -- desugar to match 166 // if let -- desugar to match
107 Some(pat) => { 167 Some(pat) => {
108 let pat = self.collect_pat(pat); 168 let pat = self.collect_pat(pat);
109 let match_expr = self.collect_expr_opt(condition.expr()); 169 let match_expr = self.collect_expr_opt(condition.expr());
110 let placeholder_pat = self.pats.alloc(Pat::Missing); 170 let placeholder_pat = self.missing_pat();
111 let arms = vec![ 171 let arms = vec![
112 MatchArm { pats: vec![pat], expr: then_branch, guard: None }, 172 MatchArm { pats: vec![pat], expr: then_branch, guard: None },
113 MatchArm { 173 MatchArm {
@@ -137,7 +197,7 @@ where
137 let body = self.collect_block_opt(e.loop_body()); 197 let body = self.collect_block_opt(e.loop_body());
138 198
139 let condition = match e.condition() { 199 let condition = match e.condition() {
140 None => self.exprs.alloc(Expr::Missing), 200 None => self.missing_expr(),
141 Some(condition) => match condition.pat() { 201 Some(condition) => match condition.pat() {
142 None => self.collect_expr_opt(condition.expr()), 202 None => self.collect_expr_opt(condition.expr()),
143 // if let -- desugar to match 203 // if let -- desugar to match
@@ -145,14 +205,14 @@ where
145 tested_by!(infer_while_let); 205 tested_by!(infer_while_let);
146 let pat = self.collect_pat(pat); 206 let pat = self.collect_pat(pat);
147 let match_expr = self.collect_expr_opt(condition.expr()); 207 let match_expr = self.collect_expr_opt(condition.expr());
148 let placeholder_pat = self.pats.alloc(Pat::Missing); 208 let placeholder_pat = self.missing_pat();
149 let break_ = self.exprs.alloc(Expr::Break { expr: None }); 209 let break_ = self.alloc_expr_desugared(Expr::Break { expr: None });
150 let arms = vec![ 210 let arms = vec![
151 MatchArm { pats: vec![pat], expr: body, guard: None }, 211 MatchArm { pats: vec![pat], expr: body, guard: None },
152 MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None }, 212 MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None },
153 ]; 213 ];
154 let match_expr = 214 let match_expr =
155 self.exprs.alloc(Expr::Match { expr: match_expr, arms }); 215 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
156 return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr); 216 return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr);
157 } 217 }
158 }, 218 },
@@ -247,13 +307,12 @@ where
247 self.collect_expr(e) 307 self.collect_expr(e)
248 } else if let Some(nr) = field.name_ref() { 308 } else if let Some(nr) = field.name_ref() {
249 // field shorthand 309 // field shorthand
250 let id = self.exprs.alloc(Expr::Path(Path::from_name_ref(&nr))); 310 self.alloc_expr_field_shorthand(
251 let ptr = Either::B(AstPtr::new(&field)); 311 Expr::Path(Path::from_name_ref(&nr)),
252 self.source_map.expr_map.insert(ptr, id); 312 AstPtr::new(&field),
253 self.source_map.expr_map_back.insert(id, ptr); 313 )
254 id
255 } else { 314 } else {
256 self.exprs.alloc(Expr::Missing) 315 self.missing_expr()
257 }, 316 },
258 }) 317 })
259 .collect(); 318 .collect();
@@ -420,7 +479,7 @@ where
420 if let Some(expr) = expr { 479 if let Some(expr) = expr {
421 self.collect_expr(expr) 480 self.collect_expr(expr)
422 } else { 481 } else {
423 self.exprs.alloc(Expr::Missing) 482 self.missing_expr()
424 } 483 }
425 } 484 }
426 485
@@ -450,7 +509,7 @@ where
450 if let Some(block) = expr { 509 if let Some(block) = expr {
451 self.collect_block(block) 510 self.collect_block(block)
452 } else { 511 } else {
453 self.exprs.alloc(Expr::Missing) 512 self.missing_expr()
454 } 513 }
455 } 514 }
456 515
@@ -519,60 +578,9 @@ where
519 if let Some(pat) = pat { 578 if let Some(pat) = pat {
520 self.collect_pat(pat) 579 self.collect_pat(pat)
521 } else { 580 } else {
522 self.pats.alloc(Pat::Missing) 581 self.missing_pat()
523 } 582 }
524 } 583 }
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} 584}
577 585
578impl From<ast::BinOp> for BinaryOp { 586impl From<ast::BinOp> for BinaryOp {
@@ -618,35 +626,3 @@ impl From<ast::BinOp> for BinaryOp {
618 } 626 }
619 } 627 }
620} 628}
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}