aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/body/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/body/lower.rs')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs174
1 files changed, 135 insertions, 39 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index f467ed3fe..f159f80af 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
4use either::Either; 4use either::Either;
5use hir_expand::{ 5use hir_expand::{
6 hygiene::Hygiene,
6 name::{name, AsName, Name}, 7 name::{name, AsName, Name},
7 MacroDefId, MacroDefKind, 8 HirFileId, MacroDefId, MacroDefKind,
8}; 9};
9use ra_arena::Arena; 10use ra_arena::Arena;
10use ra_syntax::{ 11use ra_syntax::{
@@ -14,7 +15,7 @@ use ra_syntax::{
14 }, 15 },
15 AstNode, AstPtr, 16 AstNode, AstPtr,
16}; 17};
17use test_utils::tested_by; 18use test_utils::mark;
18 19
19use crate::{ 20use crate::{
20 adt::StructKind, 21 adt::StructKind,
@@ -26,8 +27,8 @@ 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, Rawness, 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,
33}; 34};
@@ -35,6 +36,23 @@ use crate::{
35use super::{ExprSource, PatSource}; 36use super::{ExprSource, PatSource};
36use ast::AstChildren; 37use ast::AstChildren;
37 38
39pub(crate) struct LowerCtx {
40 hygiene: Hygiene,
41}
42
43impl 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
38pub(super) fn lower( 56pub(super) fn lower(
39 db: &dyn DefDatabase, 57 db: &dyn DefDatabase,
40 def: DefWithBodyId, 58 def: DefWithBodyId,
@@ -62,7 +80,6 @@ struct ExprCollector<'a> {
62 db: &'a dyn DefDatabase, 80 db: &'a dyn DefDatabase,
63 def: DefWithBodyId, 81 def: DefWithBodyId,
64 expander: Expander, 82 expander: Expander,
65
66 body: Body, 83 body: Body,
67 source_map: BodySourceMap, 84 source_map: BodySourceMap,
68} 85}
@@ -101,6 +118,10 @@ impl ExprCollector<'_> {
101 (self.body, self.source_map) 118 (self.body, self.source_map)
102 } 119 }
103 120
121 fn ctx(&self) -> LowerCtx {
122 LowerCtx::new(self.db, self.expander.current_file_id)
123 }
124
104 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 125 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
105 let src = self.expander.to_source(ptr); 126 let src = self.expander.to_source(ptr);
106 let id = self.make_expr(expr, Ok(src.clone())); 127 let id = self.make_expr(expr, Ok(src.clone()));
@@ -113,7 +134,7 @@ impl ExprCollector<'_> {
113 self.make_expr(expr, Err(SyntheticSyntax)) 134 self.make_expr(expr, Err(SyntheticSyntax))
114 } 135 }
115 fn empty_block(&mut self) -> ExprId { 136 fn empty_block(&mut self) -> ExprId {
116 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None }) 137 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None, label: None })
117 } 138 }
118 fn missing_expr(&mut self) -> ExprId { 139 fn missing_expr(&mut self) -> ExprId {
119 self.alloc_expr_desugared(Expr::Missing) 140 self.alloc_expr_desugared(Expr::Missing)
@@ -141,8 +162,7 @@ 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);
144 let attrs = self.expander.parse_attrs(&expr); 165 if !self.expander.is_cfg_enabled(&expr) {
145 if !self.expander.is_cfg_enabled(&attrs) {
146 return self.missing_expr(); 166 return self.missing_expr();
147 } 167 }
148 match expr { 168 match expr {
@@ -182,10 +202,29 @@ impl ExprCollector<'_> {
182 202
183 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)
184 } 204 }
205 ast::Expr::EffectExpr(e) => match e.effect() {
206 ast::Effect::Try(_) => {
207 let body = self.collect_block_opt(e.block_expr());
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());
188 self.alloc_expr(Expr::Loop { body }, syntax_ptr) 218 self.alloc_expr(
219 Expr::Loop {
220 body,
221 label: e
222 .label()
223 .and_then(|l| l.lifetime_token())
224 .map(|l| Name::new_lifetime(&l)),
225 },
226 syntax_ptr,
227 )
189 } 228 }
190 ast::Expr::WhileExpr(e) => { 229 ast::Expr::WhileExpr(e) => {
191 let body = self.collect_block_opt(e.loop_body()); 230 let body = self.collect_block_opt(e.loop_body());
@@ -196,29 +235,60 @@ impl ExprCollector<'_> {
196 None => self.collect_expr_opt(condition.expr()), 235 None => self.collect_expr_opt(condition.expr()),
197 // if let -- desugar to match 236 // if let -- desugar to match
198 Some(pat) => { 237 Some(pat) => {
199 tested_by!(infer_resolve_while_let); 238 mark::hit!(infer_resolve_while_let);
200 let pat = self.collect_pat(pat); 239 let pat = self.collect_pat(pat);
201 let match_expr = self.collect_expr_opt(condition.expr()); 240 let match_expr = self.collect_expr_opt(condition.expr());
202 let placeholder_pat = self.missing_pat(); 241 let placeholder_pat = self.missing_pat();
203 let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); 242 let break_ =
243 self.alloc_expr_desugared(Expr::Break { expr: None, label: None });
204 let arms = vec![ 244 let arms = vec![
205 MatchArm { pat, expr: body, guard: None }, 245 MatchArm { pat, expr: body, guard: None },
206 MatchArm { pat: placeholder_pat, expr: break_, guard: None }, 246 MatchArm { pat: placeholder_pat, expr: break_, guard: None },
207 ]; 247 ];
208 let match_expr = 248 let match_expr =
209 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); 249 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
210 return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr); 250 return self.alloc_expr(
251 Expr::Loop {
252 body: match_expr,
253 label: e
254 .label()
255 .and_then(|l| l.lifetime_token())
256 .map(|l| Name::new_lifetime(&l)),
257 },
258 syntax_ptr,
259 );
211 } 260 }
212 }, 261 },
213 }; 262 };
214 263
215 self.alloc_expr(Expr::While { condition, body }, syntax_ptr) 264 self.alloc_expr(
265 Expr::While {
266 condition,
267 body,
268 label: e
269 .label()
270 .and_then(|l| l.lifetime_token())
271 .map(|l| Name::new_lifetime(&l)),
272 },
273 syntax_ptr,
274 )
216 } 275 }
217 ast::Expr::ForExpr(e) => { 276 ast::Expr::ForExpr(e) => {
218 let iterable = self.collect_expr_opt(e.iterable()); 277 let iterable = self.collect_expr_opt(e.iterable());
219 let pat = self.collect_pat_opt(e.pat()); 278 let pat = self.collect_pat_opt(e.pat());
220 let body = self.collect_block_opt(e.loop_body()); 279 let body = self.collect_block_opt(e.loop_body());
221 self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr) 280 self.alloc_expr(
281 Expr::For {
282 iterable,
283 pat,
284 body,
285 label: e
286 .label()
287 .and_then(|l| l.lifetime_token())
288 .map(|l| Name::new_lifetime(&l)),
289 },
290 syntax_ptr,
291 )
222 } 292 }
223 ast::Expr::CallExpr(e) => { 293 ast::Expr::CallExpr(e) => {
224 let callee = self.collect_expr_opt(e.expr()); 294 let callee = self.collect_expr_opt(e.expr());
@@ -237,7 +307,8 @@ impl ExprCollector<'_> {
237 Vec::new() 307 Vec::new()
238 }; 308 };
239 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 309 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); 310 let generic_args =
311 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
241 self.alloc_expr( 312 self.alloc_expr(
242 Expr::MethodCall { receiver, method_name, args, generic_args }, 313 Expr::MethodCall { receiver, method_name, args, generic_args },
243 syntax_ptr, 314 syntax_ptr,
@@ -270,13 +341,16 @@ impl ExprCollector<'_> {
270 .unwrap_or(Expr::Missing); 341 .unwrap_or(Expr::Missing);
271 self.alloc_expr(path, syntax_ptr) 342 self.alloc_expr(path, syntax_ptr)
272 } 343 }
273 ast::Expr::ContinueExpr(_e) => { 344 ast::Expr::ContinueExpr(e) => self.alloc_expr(
274 // FIXME: labels 345 Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
275 self.alloc_expr(Expr::Continue, syntax_ptr) 346 syntax_ptr,
276 } 347 ),
277 ast::Expr::BreakExpr(e) => { 348 ast::Expr::BreakExpr(e) => {
278 let expr = e.expr().map(|e| self.collect_expr(e)); 349 let expr = e.expr().map(|e| self.collect_expr(e));
279 self.alloc_expr(Expr::Break { expr }, syntax_ptr) 350 self.alloc_expr(
351 Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
352 syntax_ptr,
353 )
280 } 354 }
281 ast::Expr::ParenExpr(e) => { 355 ast::Expr::ParenExpr(e) => {
282 let inner = self.collect_expr_opt(e.expr()); 356 let inner = self.collect_expr_opt(e.expr());
@@ -297,8 +371,7 @@ impl ExprCollector<'_> {
297 .fields() 371 .fields()
298 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 372 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
299 .filter_map(|field| { 373 .filter_map(|field| {
300 let attrs = self.expander.parse_attrs(&field); 374 if !self.expander.is_cfg_enabled(&field) {
301 if !self.expander.is_cfg_enabled(&attrs) {
302 return None; 375 return None;
303 } 376 }
304 let name = field.field_name()?.as_name(); 377 let name = field.field_name()?.as_name();
@@ -343,13 +416,26 @@ impl ExprCollector<'_> {
343 } 416 }
344 ast::Expr::CastExpr(e) => { 417 ast::Expr::CastExpr(e) => {
345 let expr = self.collect_expr_opt(e.expr()); 418 let expr = self.collect_expr_opt(e.expr());
346 let type_ref = TypeRef::from_ast_opt(e.type_ref()); 419 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref());
347 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 420 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
348 } 421 }
349 ast::Expr::RefExpr(e) => { 422 ast::Expr::RefExpr(e) => {
350 let expr = self.collect_expr_opt(e.expr()); 423 let expr = self.collect_expr_opt(e.expr());
351 let mutability = Mutability::from_mutable(e.mut_token().is_some()); 424 let raw_tok = e.raw_token().is_some();
352 self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr) 425 let mutability = if raw_tok {
426 if e.mut_token().is_some() {
427 Mutability::Mut
428 } else if e.const_token().is_some() {
429 Mutability::Shared
430 } else {
431 unreachable!("parser only remaps to raw_token() if matching mutability token follows")
432 }
433 } else {
434 Mutability::from_mutable(e.mut_token().is_some())
435 };
436 let rawness = Rawness::from_raw(raw_tok);
437
438 self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr)
353 } 439 }
354 ast::Expr::PrefixExpr(e) => { 440 ast::Expr::PrefixExpr(e) => {
355 let expr = self.collect_expr_opt(e.expr()); 441 let expr = self.collect_expr_opt(e.expr());
@@ -365,12 +451,16 @@ impl ExprCollector<'_> {
365 if let Some(pl) = e.param_list() { 451 if let Some(pl) = e.param_list() {
366 for param in pl.params() { 452 for param in pl.params() {
367 let pat = self.collect_pat_opt(param.pat()); 453 let pat = self.collect_pat_opt(param.pat());
368 let type_ref = param.ascribed_type().map(TypeRef::from_ast); 454 let type_ref =
455 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
369 args.push(pat); 456 args.push(pat);
370 arg_types.push(type_ref); 457 arg_types.push(type_ref);
371 } 458 }
372 } 459 }
373 let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast); 460 let ret_type = e
461 .ret_type()
462 .and_then(|r| r.type_ref())
463 .map(|it| TypeRef::from_ast(&self.ctx(), it));
374 let body = self.collect_expr_opt(e.body()); 464 let body = self.collect_expr_opt(e.body());
375 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 465 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
376 } 466 }
@@ -430,6 +520,7 @@ impl ExprCollector<'_> {
430 krate: Some(self.expander.module.krate), 520 krate: Some(self.expander.module.krate),
431 ast_id: Some(self.expander.ast_id(&e)), 521 ast_id: Some(self.expander.ast_id(&e)),
432 kind: MacroDefKind::Declarative, 522 kind: MacroDefKind::Declarative,
523 local_inner: false,
433 }; 524 };
434 self.body.item_scope.define_legacy_macro(name, mac); 525 self.body.item_scope.define_legacy_macro(name, mac);
435 526
@@ -464,19 +555,16 @@ impl ExprCollector<'_> {
464 } 555 }
465 } 556 }
466 557
467 fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId { 558 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
468 let syntax_node_ptr = AstPtr::new(&expr.clone().into()); 559 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); 560 self.collect_block_items(&block);
474 let statements = block 561 let statements = block
475 .statements() 562 .statements()
476 .map(|s| match s { 563 .map(|s| match s {
477 ast::Stmt::LetStmt(stmt) => { 564 ast::Stmt::LetStmt(stmt) => {
478 let pat = self.collect_pat_opt(stmt.pat()); 565 let pat = self.collect_pat_opt(stmt.pat());
479 let type_ref = stmt.ascribed_type().map(TypeRef::from_ast); 566 let type_ref =
567 stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
480 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 568 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
481 Statement::Let { pat, type_ref, initializer } 569 Statement::Let { pat, type_ref, initializer }
482 } 570 }
@@ -484,10 +572,11 @@ impl ExprCollector<'_> {
484 }) 572 })
485 .collect(); 573 .collect();
486 let tail = block.expr().map(|e| self.collect_expr(e)); 574 let tail = block.expr().map(|e| self.collect_expr(e));
487 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) 575 let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t));
576 self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr)
488 } 577 }
489 578
490 fn collect_block_items(&mut self, block: &ast::Block) { 579 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
491 let container = ContainerId::DefWithBodyId(self.def); 580 let container = ContainerId::DefWithBodyId(self.def);
492 for item in block.items() { 581 for item in block.items() {
493 let (def, name): (ModuleDefId, Option<ast::Name>) = match item { 582 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
@@ -542,9 +631,16 @@ impl ExprCollector<'_> {
542 self.body.item_scope.define_def(def); 631 self.body.item_scope.define_def(def);
543 if let Some(name) = name { 632 if let Some(name) = name {
544 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly 633 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
545 self.body 634 let has_constructor = match def {
546 .item_scope 635 ModuleDefId::AdtId(AdtId::StructId(s)) => {
547 .push_res(name.as_name(), crate::per_ns::PerNs::from_def(def, vis)); 636 self.db.struct_data(s).variant_data.kind() != StructKind::Record
637 }
638 _ => true,
639 };
640 self.body.item_scope.push_res(
641 name.as_name(),
642 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
643 );
548 } 644 }
549 } 645 }
550 } 646 }