aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
authorrobojumper <[email protected]>2020-05-31 09:59:40 +0100
committerrobojumper <[email protected]>2020-05-31 10:40:18 +0100
commit1cd78a3355ea70d3070cabb00c80a5d195499752 (patch)
tree91b2b70dbf3ac73a2fe430fd92a26d41df2a60cb /crates/ra_hir_def/src
parentfb469c3b31e7da962e91269b53b2f53d672cc4ba (diff)
correctly infer labelled breaks
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs56
-rw-r--r--crates/ra_hir_def/src/body/scope.rs4
-rw-r--r--crates/ra_hir_def/src/expr.rs19
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(
138fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { 138fn 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 }