diff options
author | Lukas Wirth <[email protected]> | 2020-12-23 15:34:30 +0000 |
---|---|---|
committer | Lukas Wirth <[email protected]> | 2020-12-24 11:49:40 +0000 |
commit | 262b9c39824b58068d89d6c5cf53d8fea782b11c (patch) | |
tree | 529758599e9c7b4b229d99676e884bb8eaf484a8 /crates/hir_def/src/body | |
parent | fd1fcf2c2e90ab04103a6aa9d033ec64dcc8d555 (diff) |
Track labels in the HIR
Diffstat (limited to 'crates/hir_def/src/body')
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 92 |
1 files changed, 45 insertions, 47 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 978c3a324..e1de39d0c 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -22,13 +22,14 @@ use test_utils::mark; | |||
22 | 22 | ||
23 | use crate::{ | 23 | use crate::{ |
24 | adt::StructKind, | 24 | adt::StructKind, |
25 | body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, | 25 | body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax}, |
26 | builtin_type::{BuiltinFloat, BuiltinInt}, | 26 | builtin_type::{BuiltinFloat, BuiltinInt}, |
27 | db::DefDatabase, | 27 | db::DefDatabase, |
28 | diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro}, | 28 | diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro}, |
29 | expr::{ | 29 | expr::{ |
30 | dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, | 30 | dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Label, |
31 | LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, | 31 | LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, |
32 | Statement, | ||
32 | }, | 33 | }, |
33 | item_scope::BuiltinShadowMode, | 34 | item_scope::BuiltinShadowMode, |
34 | item_tree::{ItemTree, ItemTreeId, ItemTreeNode}, | 35 | item_tree::{ItemTree, ItemTreeId, ItemTreeNode}, |
@@ -72,6 +73,7 @@ pub(super) fn lower( | |||
72 | body: Body { | 73 | body: Body { |
73 | exprs: Arena::default(), | 74 | exprs: Arena::default(), |
74 | pats: Arena::default(), | 75 | pats: Arena::default(), |
76 | labels: Arena::default(), | ||
75 | params: Vec::new(), | 77 | params: Vec::new(), |
76 | body_expr: dummy_expr_id(), | 78 | body_expr: dummy_expr_id(), |
77 | item_scope: Default::default(), | 79 | item_scope: Default::default(), |
@@ -175,6 +177,18 @@ impl ExprCollector<'_> { | |||
175 | id | 177 | id |
176 | } | 178 | } |
177 | 179 | ||
180 | fn alloc_label(&mut self, label: Label, ptr: AstPtr<ast::Label>) -> LabelId { | ||
181 | let src = self.expander.to_source(ptr); | ||
182 | let id = self.make_label(label, src.clone()); | ||
183 | self.source_map.label_map.insert(src, id); | ||
184 | id | ||
185 | } | ||
186 | fn make_label(&mut self, label: Label, src: LabelSource) -> LabelId { | ||
187 | let id = self.body.labels.alloc(label); | ||
188 | self.source_map.label_map_back.insert(id, src); | ||
189 | id | ||
190 | } | ||
191 | |||
178 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { | 192 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { |
179 | let syntax_ptr = AstPtr::new(&expr); | 193 | let syntax_ptr = AstPtr::new(&expr); |
180 | if self.check_cfg(&expr).is_none() { | 194 | if self.check_cfg(&expr).is_none() { |
@@ -228,19 +242,22 @@ impl ExprCollector<'_> { | |||
228 | self.alloc_expr(Expr::Unsafe { body }, syntax_ptr) | 242 | self.alloc_expr(Expr::Unsafe { body }, syntax_ptr) |
229 | } | 243 | } |
230 | // FIXME: we need to record these effects somewhere... | 244 | // FIXME: we need to record these effects somewhere... |
231 | ast::Effect::Label(label) => match e.block_expr() { | 245 | ast::Effect::Label(label) => { |
232 | Some(block) => { | 246 | let label = self.collect_label(label); |
233 | let res = self.collect_block(block); | 247 | match e.block_expr() { |
234 | match &mut self.body.exprs[res] { | 248 | Some(block) => { |
235 | Expr::Block { label: block_label, .. } => { | 249 | let res = self.collect_block(block); |
236 | *block_label = label.lifetime().map(|t| Name::new_lifetime(&t)) | 250 | match &mut self.body.exprs[res] { |
251 | Expr::Block { label: block_label, .. } => { | ||
252 | *block_label = Some(label); | ||
253 | } | ||
254 | _ => unreachable!(), | ||
237 | } | 255 | } |
238 | _ => unreachable!(), | 256 | res |
239 | } | 257 | } |
240 | res | 258 | None => self.missing_expr(), |
241 | } | 259 | } |
242 | None => self.missing_expr(), | 260 | } |
243 | }, | ||
244 | // FIXME: we need to record these effects somewhere... | 261 | // FIXME: we need to record these effects somewhere... |
245 | ast::Effect::Async(_) => { | 262 | ast::Effect::Async(_) => { |
246 | let body = self.collect_block_opt(e.block_expr()); | 263 | let body = self.collect_block_opt(e.block_expr()); |
@@ -249,16 +266,12 @@ impl ExprCollector<'_> { | |||
249 | }, | 266 | }, |
250 | ast::Expr::BlockExpr(e) => self.collect_block(e), | 267 | ast::Expr::BlockExpr(e) => self.collect_block(e), |
251 | ast::Expr::LoopExpr(e) => { | 268 | ast::Expr::LoopExpr(e) => { |
269 | let label = e.label().map(|label| self.collect_label(label)); | ||
252 | let body = self.collect_block_opt(e.loop_body()); | 270 | let body = self.collect_block_opt(e.loop_body()); |
253 | self.alloc_expr( | 271 | self.alloc_expr(Expr::Loop { body, label }, syntax_ptr) |
254 | Expr::Loop { | ||
255 | body, | ||
256 | label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)), | ||
257 | }, | ||
258 | syntax_ptr, | ||
259 | ) | ||
260 | } | 272 | } |
261 | ast::Expr::WhileExpr(e) => { | 273 | ast::Expr::WhileExpr(e) => { |
274 | let label = e.label().map(|label| self.collect_label(label)); | ||
262 | let body = self.collect_block_opt(e.loop_body()); | 275 | let body = self.collect_block_opt(e.loop_body()); |
263 | 276 | ||
264 | let condition = match e.condition() { | 277 | let condition = match e.condition() { |
@@ -279,42 +292,20 @@ impl ExprCollector<'_> { | |||
279 | ]; | 292 | ]; |
280 | let match_expr = | 293 | let match_expr = |
281 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); | 294 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); |
282 | return self.alloc_expr( | 295 | return self |
283 | Expr::Loop { | 296 | .alloc_expr(Expr::Loop { body: match_expr, label }, syntax_ptr); |
284 | body: match_expr, | ||
285 | label: e | ||
286 | .label() | ||
287 | .and_then(|l| l.lifetime()) | ||
288 | .map(|l| Name::new_lifetime(&l)), | ||
289 | }, | ||
290 | syntax_ptr, | ||
291 | ); | ||
292 | } | 297 | } |
293 | }, | 298 | }, |
294 | }; | 299 | }; |
295 | 300 | ||
296 | self.alloc_expr( | 301 | self.alloc_expr(Expr::While { condition, body, label }, syntax_ptr) |
297 | Expr::While { | ||
298 | condition, | ||
299 | body, | ||
300 | label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)), | ||
301 | }, | ||
302 | syntax_ptr, | ||
303 | ) | ||
304 | } | 302 | } |
305 | ast::Expr::ForExpr(e) => { | 303 | ast::Expr::ForExpr(e) => { |
304 | let label = e.label().map(|label| self.collect_label(label)); | ||
306 | let iterable = self.collect_expr_opt(e.iterable()); | 305 | let iterable = self.collect_expr_opt(e.iterable()); |
307 | let pat = self.collect_pat_opt(e.pat()); | 306 | let pat = self.collect_pat_opt(e.pat()); |
308 | let body = self.collect_block_opt(e.loop_body()); | 307 | let body = self.collect_block_opt(e.loop_body()); |
309 | self.alloc_expr( | 308 | self.alloc_expr(Expr::For { iterable, pat, body, label }, syntax_ptr) |
310 | Expr::For { | ||
311 | iterable, | ||
312 | pat, | ||
313 | body, | ||
314 | label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)), | ||
315 | }, | ||
316 | syntax_ptr, | ||
317 | ) | ||
318 | } | 309 | } |
319 | ast::Expr::CallExpr(e) => { | 310 | ast::Expr::CallExpr(e) => { |
320 | let callee = self.collect_expr_opt(e.expr()); | 311 | let callee = self.collect_expr_opt(e.expr()); |
@@ -814,6 +805,13 @@ impl ExprCollector<'_> { | |||
814 | } | 805 | } |
815 | } | 806 | } |
816 | 807 | ||
808 | fn collect_label(&mut self, ast_label: ast::Label) -> LabelId { | ||
809 | let label = Label { | ||
810 | name: ast_label.lifetime().as_ref().map_or_else(Name::missing, Name::new_lifetime), | ||
811 | }; | ||
812 | self.alloc_label(label, AstPtr::new(&ast_label)) | ||
813 | } | ||
814 | |||
817 | fn collect_pat(&mut self, pat: ast::Pat) -> PatId { | 815 | fn collect_pat(&mut self, pat: ast::Pat) -> PatId { |
818 | let pattern = match &pat { | 816 | let pattern = match &pat { |
819 | ast::Pat::IdentPat(bp) => { | 817 | ast::Pat::IdentPat(bp) => { |