diff options
Diffstat (limited to 'crates/ra_hir_def/src/body/lower.rs')
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 174 |
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 | ||
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::{ |
@@ -14,7 +15,7 @@ use ra_syntax::{ | |||
14 | }, | 15 | }, |
15 | AstNode, AstPtr, | 16 | AstNode, AstPtr, |
16 | }; | 17 | }; |
17 | use test_utils::tested_by; | 18 | use test_utils::mark; |
18 | 19 | ||
19 | use crate::{ | 20 | use 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::{ | |||
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, |
@@ -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 | } |