diff options
author | robojumper <[email protected]> | 2020-05-31 09:59:40 +0100 |
---|---|---|
committer | robojumper <[email protected]> | 2020-05-31 10:40:18 +0100 |
commit | 1cd78a3355ea70d3070cabb00c80a5d195499752 (patch) | |
tree | 91b2b70dbf3ac73a2fe430fd92a26d41df2a60cb /crates/ra_hir_def/src | |
parent | fb469c3b31e7da962e91269b53b2f53d672cc4ba (diff) |
correctly infer labelled breaks
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 56 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/scope.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_def/src/expr.rs | 19 |
3 files changed, 60 insertions, 19 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 905c0cf5d..dc52c6bd9 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -134,7 +134,7 @@ impl ExprCollector<'_> { | |||
134 | self.make_expr(expr, Err(SyntheticSyntax)) | 134 | self.make_expr(expr, Err(SyntheticSyntax)) |
135 | } | 135 | } |
136 | fn empty_block(&mut self) -> ExprId { | 136 | fn empty_block(&mut self) -> ExprId { |
137 | 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 }) |
138 | } | 138 | } |
139 | fn missing_expr(&mut self) -> ExprId { | 139 | fn missing_expr(&mut self) -> ExprId { |
140 | self.alloc_expr_desugared(Expr::Missing) | 140 | self.alloc_expr_desugared(Expr::Missing) |
@@ -215,7 +215,13 @@ impl ExprCollector<'_> { | |||
215 | ast::Expr::BlockExpr(e) => self.collect_block(e), | 215 | ast::Expr::BlockExpr(e) => self.collect_block(e), |
216 | ast::Expr::LoopExpr(e) => { | 216 | ast::Expr::LoopExpr(e) => { |
217 | let body = self.collect_block_opt(e.loop_body()); | 217 | let body = self.collect_block_opt(e.loop_body()); |
218 | self.alloc_expr(Expr::Loop { body }, syntax_ptr) | 218 | self.alloc_expr( |
219 | Expr::Loop { | ||
220 | body, | ||
221 | label: e.label().and_then(|l| l.lifetime_token()).map(|l| Name::new_lifetime(&l)), | ||
222 | }, | ||
223 | syntax_ptr, | ||
224 | ) | ||
219 | } | 225 | } |
220 | ast::Expr::WhileExpr(e) => { | 226 | ast::Expr::WhileExpr(e) => { |
221 | let body = self.collect_block_opt(e.loop_body()); | 227 | let body = self.collect_block_opt(e.loop_body()); |
@@ -230,25 +236,47 @@ impl ExprCollector<'_> { | |||
230 | let pat = self.collect_pat(pat); | 236 | let pat = self.collect_pat(pat); |
231 | let match_expr = self.collect_expr_opt(condition.expr()); | 237 | let match_expr = self.collect_expr_opt(condition.expr()); |
232 | let placeholder_pat = self.missing_pat(); | 238 | let placeholder_pat = self.missing_pat(); |
233 | let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); | 239 | let break_ = |
240 | self.alloc_expr_desugared(Expr::Break { expr: None, label: None }); | ||
234 | let arms = vec![ | 241 | let arms = vec![ |
235 | MatchArm { pat, expr: body, guard: None }, | 242 | MatchArm { pat, expr: body, guard: None }, |
236 | MatchArm { pat: placeholder_pat, expr: break_, guard: None }, | 243 | MatchArm { pat: placeholder_pat, expr: break_, guard: None }, |
237 | ]; | 244 | ]; |
238 | let match_expr = | 245 | let match_expr = |
239 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); | 246 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); |
240 | return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr); | 247 | return self.alloc_expr( |
248 | Expr::Loop { | ||
249 | body: match_expr, | ||
250 | label: e.label().and_then(|l| l.lifetime_token()).map(|l| Name::new_lifetime(&l)), | ||
251 | }, | ||
252 | syntax_ptr, | ||
253 | ); | ||
241 | } | 254 | } |
242 | }, | 255 | }, |
243 | }; | 256 | }; |
244 | 257 | ||
245 | self.alloc_expr(Expr::While { condition, body }, syntax_ptr) | 258 | self.alloc_expr( |
259 | Expr::While { | ||
260 | condition, | ||
261 | body, | ||
262 | label: e.label().and_then(|l| l.lifetime_token()).map(|l| Name::new_lifetime(&l)), | ||
263 | }, | ||
264 | syntax_ptr, | ||
265 | ) | ||
246 | } | 266 | } |
247 | ast::Expr::ForExpr(e) => { | 267 | ast::Expr::ForExpr(e) => { |
248 | let iterable = self.collect_expr_opt(e.iterable()); | 268 | let iterable = self.collect_expr_opt(e.iterable()); |
249 | let pat = self.collect_pat_opt(e.pat()); | 269 | let pat = self.collect_pat_opt(e.pat()); |
250 | let body = self.collect_block_opt(e.loop_body()); | 270 | let body = self.collect_block_opt(e.loop_body()); |
251 | self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr) | 271 | self.alloc_expr( |
272 | Expr::For { | ||
273 | iterable, | ||
274 | pat, | ||
275 | body, | ||
276 | label: e.label().and_then(|l| l.lifetime_token()).map(|l| Name::new_lifetime(&l)), | ||
277 | }, | ||
278 | syntax_ptr, | ||
279 | ) | ||
252 | } | 280 | } |
253 | ast::Expr::CallExpr(e) => { | 281 | ast::Expr::CallExpr(e) => { |
254 | let callee = self.collect_expr_opt(e.expr()); | 282 | let callee = self.collect_expr_opt(e.expr()); |
@@ -301,13 +329,18 @@ impl ExprCollector<'_> { | |||
301 | .unwrap_or(Expr::Missing); | 329 | .unwrap_or(Expr::Missing); |
302 | self.alloc_expr(path, syntax_ptr) | 330 | self.alloc_expr(path, syntax_ptr) |
303 | } | 331 | } |
304 | ast::Expr::ContinueExpr(_e) => { | 332 | ast::Expr::ContinueExpr(e) => { |
305 | // FIXME: labels | 333 | self.alloc_expr( |
306 | self.alloc_expr(Expr::Continue, syntax_ptr) | 334 | Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, |
335 | syntax_ptr, | ||
336 | ) | ||
307 | } | 337 | } |
308 | ast::Expr::BreakExpr(e) => { | 338 | ast::Expr::BreakExpr(e) => { |
309 | let expr = e.expr().map(|e| self.collect_expr(e)); | 339 | let expr = e.expr().map(|e| self.collect_expr(e)); |
310 | self.alloc_expr(Expr::Break { expr }, syntax_ptr) | 340 | self.alloc_expr( |
341 | Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, | ||
342 | syntax_ptr, | ||
343 | ) | ||
311 | } | 344 | } |
312 | ast::Expr::ParenExpr(e) => { | 345 | ast::Expr::ParenExpr(e) => { |
313 | let inner = self.collect_expr_opt(e.expr()); | 346 | let inner = self.collect_expr_opt(e.expr()); |
@@ -529,7 +562,8 @@ impl ExprCollector<'_> { | |||
529 | }) | 562 | }) |
530 | .collect(); | 563 | .collect(); |
531 | let tail = block.expr().map(|e| self.collect_expr(e)); | 564 | let tail = block.expr().map(|e| self.collect_expr(e)); |
532 | self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) | 565 | let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t)); |
566 | self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr) | ||
533 | } | 567 | } |
534 | 568 | ||
535 | fn collect_block_items(&mut self, block: &ast::BlockExpr) { | 569 | fn collect_block_items(&mut self, block: &ast::BlockExpr) { |
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index 09e92b74e..e48ff38f9 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs | |||
@@ -138,10 +138,10 @@ fn compute_block_scopes( | |||
138 | fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { | 138 | fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { |
139 | scopes.set_scope(expr, scope); | 139 | scopes.set_scope(expr, scope); |
140 | match &body[expr] { | 140 | match &body[expr] { |
141 | Expr::Block { statements, tail } => { | 141 | Expr::Block { statements, tail, .. } => { |
142 | compute_block_scopes(&statements, *tail, body, scopes, scope); | 142 | compute_block_scopes(&statements, *tail, body, scopes, scope); |
143 | } | 143 | } |
144 | Expr::For { iterable, pat, body: body_expr } => { | 144 | Expr::For { iterable, pat, body: body_expr, .. } => { |
145 | compute_expr_scopes(*iterable, body, scopes, scope); | 145 | compute_expr_scopes(*iterable, body, scopes, scope); |
146 | let scope = scopes.new_scope(scope); | 146 | let scope = scopes.new_scope(scope); |
147 | scopes.add_bindings(body, scope, *pat); | 147 | scopes.add_bindings(body, scope, *pat); |
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index f25c6f958..8683f6c7f 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs | |||
@@ -52,18 +52,22 @@ pub enum Expr { | |||
52 | Block { | 52 | Block { |
53 | statements: Vec<Statement>, | 53 | statements: Vec<Statement>, |
54 | tail: Option<ExprId>, | 54 | tail: Option<ExprId>, |
55 | label: Option<Name>, | ||
55 | }, | 56 | }, |
56 | Loop { | 57 | Loop { |
57 | body: ExprId, | 58 | body: ExprId, |
59 | label: Option<Name>, | ||
58 | }, | 60 | }, |
59 | While { | 61 | While { |
60 | condition: ExprId, | 62 | condition: ExprId, |
61 | body: ExprId, | 63 | body: ExprId, |
64 | label: Option<Name>, | ||
62 | }, | 65 | }, |
63 | For { | 66 | For { |
64 | iterable: ExprId, | 67 | iterable: ExprId, |
65 | pat: PatId, | 68 | pat: PatId, |
66 | body: ExprId, | 69 | body: ExprId, |
70 | label: Option<Name>, | ||
67 | }, | 71 | }, |
68 | Call { | 72 | Call { |
69 | callee: ExprId, | 73 | callee: ExprId, |
@@ -79,9 +83,12 @@ pub enum Expr { | |||
79 | expr: ExprId, | 83 | expr: ExprId, |
80 | arms: Vec<MatchArm>, | 84 | arms: Vec<MatchArm>, |
81 | }, | 85 | }, |
82 | Continue, | 86 | Continue { |
87 | label: Option<Name>, | ||
88 | }, | ||
83 | Break { | 89 | Break { |
84 | expr: Option<ExprId>, | 90 | expr: Option<ExprId>, |
91 | label: Option<Name>, | ||
85 | }, | 92 | }, |
86 | Return { | 93 | Return { |
87 | expr: Option<ExprId>, | 94 | expr: Option<ExprId>, |
@@ -225,7 +232,7 @@ impl Expr { | |||
225 | f(*else_branch); | 232 | f(*else_branch); |
226 | } | 233 | } |
227 | } | 234 | } |
228 | Expr::Block { statements, tail } => { | 235 | Expr::Block { statements, tail, .. } => { |
229 | for stmt in statements { | 236 | for stmt in statements { |
230 | match stmt { | 237 | match stmt { |
231 | Statement::Let { initializer, .. } => { | 238 | Statement::Let { initializer, .. } => { |
@@ -241,8 +248,8 @@ impl Expr { | |||
241 | } | 248 | } |
242 | } | 249 | } |
243 | Expr::TryBlock { body } => f(*body), | 250 | Expr::TryBlock { body } => f(*body), |
244 | Expr::Loop { body } => f(*body), | 251 | Expr::Loop { body, .. } => f(*body), |
245 | Expr::While { condition, body } => { | 252 | Expr::While { condition, body, .. } => { |
246 | f(*condition); | 253 | f(*condition); |
247 | f(*body); | 254 | f(*body); |
248 | } | 255 | } |
@@ -268,8 +275,8 @@ impl Expr { | |||
268 | f(arm.expr); | 275 | f(arm.expr); |
269 | } | 276 | } |
270 | } | 277 | } |
271 | Expr::Continue => {} | 278 | Expr::Continue { .. } => {}, |
272 | Expr::Break { expr } | Expr::Return { expr } => { | 279 | Expr::Break { expr, .. } | Expr::Return { expr } => { |
273 | if let Some(expr) = expr { | 280 | if let Some(expr) = expr { |
274 | f(*expr); | 281 | f(*expr); |
275 | } | 282 | } |