diff options
Diffstat (limited to 'crates/ra_hir_def/src/body')
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 86 |
1 files changed, 62 insertions, 24 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 0caedd8d8..443b057ab 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 | } |
@@ -141,6 +162,9 @@ impl ExprCollector<'_> { | |||
141 | 162 | ||
142 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { | 163 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { |
143 | let syntax_ptr = AstPtr::new(&expr); | 164 | let syntax_ptr = AstPtr::new(&expr); |
165 | if !self.expander.is_cfg_enabled(&expr) { | ||
166 | return self.missing_expr(); | ||
167 | } | ||
144 | match expr { | 168 | match expr { |
145 | ast::Expr::IfExpr(e) => { | 169 | ast::Expr::IfExpr(e) => { |
146 | let then_branch = self.collect_block_opt(e.then_branch()); | 170 | let then_branch = self.collect_block_opt(e.then_branch()); |
@@ -178,10 +202,16 @@ impl ExprCollector<'_> { | |||
178 | 202 | ||
179 | self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) | 203 | self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) |
180 | } | 204 | } |
181 | ast::Expr::TryBlockExpr(e) => { | 205 | ast::Expr::EffectExpr(e) => match e.effect() { |
182 | let body = self.collect_block_opt(e.body()); | 206 | ast::Effect::Try(_) => { |
183 | self.alloc_expr(Expr::TryBlock { body }, syntax_ptr) | 207 | let body = self.collect_block_opt(e.block_expr()); |
184 | } | 208 | self.alloc_expr(Expr::TryBlock { body }, syntax_ptr) |
209 | } | ||
210 | // FIXME: we need to record these effects somewhere... | ||
211 | ast::Effect::Async(_) | ast::Effect::Label(_) | ast::Effect::Unsafe(_) => { | ||
212 | self.collect_block_opt(e.block_expr()) | ||
213 | } | ||
214 | }, | ||
185 | ast::Expr::BlockExpr(e) => self.collect_block(e), | 215 | ast::Expr::BlockExpr(e) => self.collect_block(e), |
186 | ast::Expr::LoopExpr(e) => { | 216 | ast::Expr::LoopExpr(e) => { |
187 | let body = self.collect_block_opt(e.loop_body()); | 217 | let body = self.collect_block_opt(e.loop_body()); |
@@ -237,7 +267,8 @@ impl ExprCollector<'_> { | |||
237 | Vec::new() | 267 | Vec::new() |
238 | }; | 268 | }; |
239 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); | 269 | 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); | 270 | let generic_args = |
271 | e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx, it)); | ||
241 | self.alloc_expr( | 272 | self.alloc_expr( |
242 | Expr::MethodCall { receiver, method_name, args, generic_args }, | 273 | Expr::MethodCall { receiver, method_name, args, generic_args }, |
243 | syntax_ptr, | 274 | syntax_ptr, |
@@ -297,8 +328,7 @@ impl ExprCollector<'_> { | |||
297 | .fields() | 328 | .fields() |
298 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) | 329 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) |
299 | .filter_map(|field| { | 330 | .filter_map(|field| { |
300 | let attrs = self.expander.parse_attrs(&field); | 331 | if !self.expander.is_cfg_enabled(&field) { |
301 | if !self.expander.is_cfg_enabled(&attrs) { | ||
302 | return None; | 332 | return None; |
303 | } | 333 | } |
304 | let name = field.field_name()?.as_name(); | 334 | let name = field.field_name()?.as_name(); |
@@ -343,7 +373,7 @@ impl ExprCollector<'_> { | |||
343 | } | 373 | } |
344 | ast::Expr::CastExpr(e) => { | 374 | ast::Expr::CastExpr(e) => { |
345 | let expr = self.collect_expr_opt(e.expr()); | 375 | let expr = self.collect_expr_opt(e.expr()); |
346 | let type_ref = TypeRef::from_ast_opt(e.type_ref()); | 376 | let type_ref = TypeRef::from_ast_opt(&self.ctx, e.type_ref()); |
347 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) | 377 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) |
348 | } | 378 | } |
349 | ast::Expr::RefExpr(e) => { | 379 | ast::Expr::RefExpr(e) => { |
@@ -365,12 +395,16 @@ impl ExprCollector<'_> { | |||
365 | if let Some(pl) = e.param_list() { | 395 | if let Some(pl) = e.param_list() { |
366 | for param in pl.params() { | 396 | for param in pl.params() { |
367 | let pat = self.collect_pat_opt(param.pat()); | 397 | let pat = self.collect_pat_opt(param.pat()); |
368 | let type_ref = param.ascribed_type().map(TypeRef::from_ast); | 398 | let type_ref = |
399 | param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it)); | ||
369 | args.push(pat); | 400 | args.push(pat); |
370 | arg_types.push(type_ref); | 401 | arg_types.push(type_ref); |
371 | } | 402 | } |
372 | } | 403 | } |
373 | let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast); | 404 | let ret_type = e |
405 | .ret_type() | ||
406 | .and_then(|r| r.type_ref()) | ||
407 | .map(|it| TypeRef::from_ast(&self.ctx, it)); | ||
374 | let body = self.collect_expr_opt(e.body()); | 408 | let body = self.collect_expr_opt(e.body()); |
375 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) | 409 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) |
376 | } | 410 | } |
@@ -430,6 +464,7 @@ impl ExprCollector<'_> { | |||
430 | krate: Some(self.expander.module.krate), | 464 | krate: Some(self.expander.module.krate), |
431 | ast_id: Some(self.expander.ast_id(&e)), | 465 | ast_id: Some(self.expander.ast_id(&e)), |
432 | kind: MacroDefKind::Declarative, | 466 | kind: MacroDefKind::Declarative, |
467 | local_inner: false, | ||
433 | }; | 468 | }; |
434 | self.body.item_scope.define_legacy_macro(name, mac); | 469 | self.body.item_scope.define_legacy_macro(name, mac); |
435 | 470 | ||
@@ -464,19 +499,15 @@ impl ExprCollector<'_> { | |||
464 | } | 499 | } |
465 | } | 500 | } |
466 | 501 | ||
467 | fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId { | 502 | fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { |
468 | let syntax_node_ptr = AstPtr::new(&expr.clone().into()); | 503 | let syntax_node_ptr = AstPtr::new(&block.clone().into()); |
469 | let block = match expr.block() { | ||
470 | Some(block) => block, | ||
471 | None => return self.alloc_expr(Expr::Missing, syntax_node_ptr), | ||
472 | }; | ||
473 | self.collect_block_items(&block); | 504 | self.collect_block_items(&block); |
474 | let statements = block | 505 | let statements = block |
475 | .statements() | 506 | .statements() |
476 | .map(|s| match s { | 507 | .map(|s| match s { |
477 | ast::Stmt::LetStmt(stmt) => { | 508 | ast::Stmt::LetStmt(stmt) => { |
478 | let pat = self.collect_pat_opt(stmt.pat()); | 509 | let pat = self.collect_pat_opt(stmt.pat()); |
479 | let type_ref = stmt.ascribed_type().map(TypeRef::from_ast); | 510 | let type_ref = stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it)); |
480 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); | 511 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); |
481 | Statement::Let { pat, type_ref, initializer } | 512 | Statement::Let { pat, type_ref, initializer } |
482 | } | 513 | } |
@@ -487,7 +518,7 @@ impl ExprCollector<'_> { | |||
487 | self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) | 518 | self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) |
488 | } | 519 | } |
489 | 520 | ||
490 | fn collect_block_items(&mut self, block: &ast::Block) { | 521 | fn collect_block_items(&mut self, block: &ast::BlockExpr) { |
491 | let container = ContainerId::DefWithBodyId(self.def); | 522 | let container = ContainerId::DefWithBodyId(self.def); |
492 | for item in block.items() { | 523 | for item in block.items() { |
493 | let (def, name): (ModuleDefId, Option<ast::Name>) = match item { | 524 | let (def, name): (ModuleDefId, Option<ast::Name>) = match item { |
@@ -542,9 +573,16 @@ impl ExprCollector<'_> { | |||
542 | self.body.item_scope.define_def(def); | 573 | self.body.item_scope.define_def(def); |
543 | if let Some(name) = name { | 574 | if let Some(name) = name { |
544 | let vis = crate::visibility::Visibility::Public; // FIXME determine correctly | 575 | let vis = crate::visibility::Visibility::Public; // FIXME determine correctly |
545 | self.body | 576 | let has_constructor = match def { |
546 | .item_scope | 577 | ModuleDefId::AdtId(AdtId::StructId(s)) => { |
547 | .push_res(name.as_name(), crate::per_ns::PerNs::from_def(def, vis)); | 578 | self.db.struct_data(s).variant_data.kind() != StructKind::Record |
579 | } | ||
580 | _ => true, | ||
581 | }; | ||
582 | self.body.item_scope.push_res( | ||
583 | name.as_name(), | ||
584 | crate::per_ns::PerNs::from_def(def, vis, has_constructor), | ||
585 | ); | ||
548 | } | 586 | } |
549 | } | 587 | } |
550 | } | 588 | } |