diff options
Diffstat (limited to 'crates/ra_hir_def/src/body/lower.rs')
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 8c1aefbf5..687216dc3 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -3,8 +3,9 @@ | |||
3 | 3 | ||
4 | use either::Either; | 4 | use either::Either; |
5 | use hir_expand::{ | 5 | use hir_expand::{ |
6 | hygiene::Hygiene, | ||
6 | name::{name, AsName, Name}, | 7 | name::{name, AsName, Name}, |
7 | MacroDefId, MacroDefKind, | 8 | HirFileId, MacroDefId, MacroDefKind, |
8 | }; | 9 | }; |
9 | use ra_arena::Arena; | 10 | use ra_arena::Arena; |
10 | use ra_syntax::{ | 11 | use ra_syntax::{ |
@@ -26,7 +27,7 @@ use crate::{ | |||
26 | LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, | 27 | LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, |
27 | }, | 28 | }, |
28 | item_scope::BuiltinShadowMode, | 29 | item_scope::BuiltinShadowMode, |
29 | path::GenericArgs, | 30 | path::{GenericArgs, Path}, |
30 | type_ref::{Mutability, TypeRef}, | 31 | type_ref::{Mutability, TypeRef}, |
31 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, | 32 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, |
32 | StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, | 33 | StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, |
@@ -35,6 +36,23 @@ use crate::{ | |||
35 | use super::{ExprSource, PatSource}; | 36 | use super::{ExprSource, PatSource}; |
36 | use ast::AstChildren; | 37 | use ast::AstChildren; |
37 | 38 | ||
39 | pub(crate) struct LowerCtx { | ||
40 | hygiene: Hygiene, | ||
41 | } | ||
42 | |||
43 | impl LowerCtx { | ||
44 | pub fn new(db: &dyn DefDatabase, file_id: HirFileId) -> Self { | ||
45 | LowerCtx { hygiene: Hygiene::new(db.upcast(), file_id) } | ||
46 | } | ||
47 | pub fn with_hygiene(hygiene: &Hygiene) -> Self { | ||
48 | LowerCtx { hygiene: hygiene.clone() } | ||
49 | } | ||
50 | |||
51 | pub fn lower_path(&self, ast: ast::Path) -> Option<Path> { | ||
52 | Path::from_src(ast, &self.hygiene) | ||
53 | } | ||
54 | } | ||
55 | |||
38 | pub(super) fn lower( | 56 | pub(super) fn lower( |
39 | db: &dyn DefDatabase, | 57 | db: &dyn DefDatabase, |
40 | def: DefWithBodyId, | 58 | def: DefWithBodyId, |
@@ -42,10 +60,13 @@ pub(super) fn lower( | |||
42 | params: Option<ast::ParamList>, | 60 | params: Option<ast::ParamList>, |
43 | body: Option<ast::Expr>, | 61 | body: Option<ast::Expr>, |
44 | ) -> (Body, BodySourceMap) { | 62 | ) -> (Body, BodySourceMap) { |
63 | let ctx = LowerCtx::new(db, expander.current_file_id.clone()); | ||
64 | |||
45 | ExprCollector { | 65 | ExprCollector { |
46 | db, | 66 | db, |
47 | def, | 67 | def, |
48 | expander, | 68 | expander, |
69 | ctx, | ||
49 | source_map: BodySourceMap::default(), | 70 | source_map: BodySourceMap::default(), |
50 | body: Body { | 71 | body: Body { |
51 | exprs: Arena::default(), | 72 | exprs: Arena::default(), |
@@ -62,7 +83,7 @@ struct ExprCollector<'a> { | |||
62 | db: &'a dyn DefDatabase, | 83 | db: &'a dyn DefDatabase, |
63 | def: DefWithBodyId, | 84 | def: DefWithBodyId, |
64 | expander: Expander, | 85 | expander: Expander, |
65 | 86 | ctx: LowerCtx, | |
66 | body: Body, | 87 | body: Body, |
67 | source_map: BodySourceMap, | 88 | source_map: BodySourceMap, |
68 | } | 89 | } |
@@ -182,6 +203,16 @@ impl ExprCollector<'_> { | |||
182 | 203 | ||
183 | self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) | 204 | self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) |
184 | } | 205 | } |
206 | ast::Expr::EffectExpr(e) => match e.effect() { | ||
207 | ast::Effect::Try(_) => { | ||
208 | let body = self.collect_block_opt(e.block_expr()); | ||
209 | self.alloc_expr(Expr::TryBlock { body }, syntax_ptr) | ||
210 | } | ||
211 | // FIXME: we need to record these effects somewhere... | ||
212 | ast::Effect::Async(_) | ast::Effect::Label(_) | ast::Effect::Unsafe(_) => { | ||
213 | self.collect_block_opt(e.block_expr()) | ||
214 | } | ||
215 | }, | ||
185 | ast::Expr::BlockExpr(e) => self.collect_block(e), | 216 | ast::Expr::BlockExpr(e) => self.collect_block(e), |
186 | ast::Expr::LoopExpr(e) => { | 217 | ast::Expr::LoopExpr(e) => { |
187 | let body = self.collect_block_opt(e.loop_body()); | 218 | let body = self.collect_block_opt(e.loop_body()); |
@@ -237,7 +268,8 @@ impl ExprCollector<'_> { | |||
237 | Vec::new() | 268 | Vec::new() |
238 | }; | 269 | }; |
239 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); | 270 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); |
240 | let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast); | 271 | let generic_args = |
272 | e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx, it)); | ||
241 | self.alloc_expr( | 273 | self.alloc_expr( |
242 | Expr::MethodCall { receiver, method_name, args, generic_args }, | 274 | Expr::MethodCall { receiver, method_name, args, generic_args }, |
243 | syntax_ptr, | 275 | syntax_ptr, |
@@ -343,7 +375,7 @@ impl ExprCollector<'_> { | |||
343 | } | 375 | } |
344 | ast::Expr::CastExpr(e) => { | 376 | ast::Expr::CastExpr(e) => { |
345 | let expr = self.collect_expr_opt(e.expr()); | 377 | let expr = self.collect_expr_opt(e.expr()); |
346 | let type_ref = TypeRef::from_ast_opt(e.type_ref()); | 378 | let type_ref = TypeRef::from_ast_opt(&self.ctx, e.type_ref()); |
347 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) | 379 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) |
348 | } | 380 | } |
349 | ast::Expr::RefExpr(e) => { | 381 | ast::Expr::RefExpr(e) => { |
@@ -365,12 +397,16 @@ impl ExprCollector<'_> { | |||
365 | if let Some(pl) = e.param_list() { | 397 | if let Some(pl) = e.param_list() { |
366 | for param in pl.params() { | 398 | for param in pl.params() { |
367 | let pat = self.collect_pat_opt(param.pat()); | 399 | let pat = self.collect_pat_opt(param.pat()); |
368 | let type_ref = param.ascribed_type().map(TypeRef::from_ast); | 400 | let type_ref = |
401 | param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it)); | ||
369 | args.push(pat); | 402 | args.push(pat); |
370 | arg_types.push(type_ref); | 403 | arg_types.push(type_ref); |
371 | } | 404 | } |
372 | } | 405 | } |
373 | let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast); | 406 | let ret_type = e |
407 | .ret_type() | ||
408 | .and_then(|r| r.type_ref()) | ||
409 | .map(|it| TypeRef::from_ast(&self.ctx, it)); | ||
374 | let body = self.collect_expr_opt(e.body()); | 410 | let body = self.collect_expr_opt(e.body()); |
375 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) | 411 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) |
376 | } | 412 | } |
@@ -465,19 +501,15 @@ impl ExprCollector<'_> { | |||
465 | } | 501 | } |
466 | } | 502 | } |
467 | 503 | ||
468 | fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId { | 504 | fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { |
469 | let syntax_node_ptr = AstPtr::new(&expr.clone().into()); | 505 | let syntax_node_ptr = AstPtr::new(&block.clone().into()); |
470 | let block = match expr.block() { | ||
471 | Some(block) => block, | ||
472 | None => return self.alloc_expr(Expr::Missing, syntax_node_ptr), | ||
473 | }; | ||
474 | self.collect_block_items(&block); | 506 | self.collect_block_items(&block); |
475 | let statements = block | 507 | let statements = block |
476 | .statements() | 508 | .statements() |
477 | .map(|s| match s { | 509 | .map(|s| match s { |
478 | ast::Stmt::LetStmt(stmt) => { | 510 | ast::Stmt::LetStmt(stmt) => { |
479 | let pat = self.collect_pat_opt(stmt.pat()); | 511 | let pat = self.collect_pat_opt(stmt.pat()); |
480 | let type_ref = stmt.ascribed_type().map(TypeRef::from_ast); | 512 | let type_ref = stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it)); |
481 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); | 513 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); |
482 | Statement::Let { pat, type_ref, initializer } | 514 | Statement::Let { pat, type_ref, initializer } |
483 | } | 515 | } |
@@ -488,7 +520,7 @@ impl ExprCollector<'_> { | |||
488 | self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) | 520 | self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) |
489 | } | 521 | } |
490 | 522 | ||
491 | fn collect_block_items(&mut self, block: &ast::Block) { | 523 | fn collect_block_items(&mut self, block: &ast::BlockExpr) { |
492 | let container = ContainerId::DefWithBodyId(self.def); | 524 | let container = ContainerId::DefWithBodyId(self.def); |
493 | for item in block.items() { | 525 | for item in block.items() { |
494 | let (def, name): (ModuleDefId, Option<ast::Name>) = match item { | 526 | let (def, name): (ModuleDefId, Option<ast::Name>) = match item { |