diff options
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 252 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/expr.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests.rs | 2 |
4 files changed, 177 insertions, 100 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 4f2350915..076d1a4fa 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -184,6 +184,7 @@ pub struct Body { | |||
184 | /// The `ExprId` of the actual body expression. | 184 | /// The `ExprId` of the actual body expression. |
185 | pub body_expr: ExprId, | 185 | pub body_expr: ExprId, |
186 | pub item_scope: ItemScope, | 186 | pub item_scope: ItemScope, |
187 | pub parent_map: FxHashMap<ExprId, ExprId>, | ||
187 | } | 188 | } |
188 | 189 | ||
189 | pub type ExprPtr = AstPtr<ast::Expr>; | 190 | pub type ExprPtr = AstPtr<ast::Expr>; |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 6eb72e950..a1678adeb 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -15,6 +15,7 @@ use ra_syntax::{ | |||
15 | }, | 15 | }, |
16 | AstNode, AstPtr, | 16 | AstNode, AstPtr, |
17 | }; | 17 | }; |
18 | use rustc_hash::FxHashMap; | ||
18 | use test_utils::mark; | 19 | use test_utils::mark; |
19 | 20 | ||
20 | use crate::{ | 21 | use crate::{ |
@@ -74,6 +75,7 @@ pub(super) fn lower( | |||
74 | params: Vec::new(), | 75 | params: Vec::new(), |
75 | body_expr: dummy_expr_id(), | 76 | body_expr: dummy_expr_id(), |
76 | item_scope: Default::default(), | 77 | item_scope: Default::default(), |
78 | parent_map: FxHashMap::default(), | ||
77 | }, | 79 | }, |
78 | item_trees: { | 80 | item_trees: { |
79 | let mut map = FxHashMap::default(); | 81 | let mut map = FxHashMap::default(); |
@@ -171,11 +173,28 @@ impl ExprCollector<'_> { | |||
171 | id | 173 | id |
172 | } | 174 | } |
173 | 175 | ||
176 | fn update_parent_map( | ||
177 | &mut self, | ||
178 | (parent_expr, children_exprs): (ExprId, Vec<ExprId>), | ||
179 | ) -> ExprId { | ||
180 | for child_expr in children_exprs { | ||
181 | self.body.parent_map.insert(child_expr, parent_expr); | ||
182 | } | ||
183 | |||
184 | parent_expr | ||
185 | } | ||
186 | |||
174 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { | 187 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { |
188 | let parent_and_children = self.collect_expr_inner(expr); | ||
189 | self.update_parent_map(parent_and_children) | ||
190 | } | ||
191 | |||
192 | fn collect_expr_inner(&mut self, expr: ast::Expr) -> (ExprId, Vec<ExprId>) { | ||
175 | let syntax_ptr = AstPtr::new(&expr); | 193 | let syntax_ptr = AstPtr::new(&expr); |
176 | if !self.expander.is_cfg_enabled(&expr) { | 194 | if !self.expander.is_cfg_enabled(&expr) { |
177 | return self.missing_expr(); | 195 | return (self.missing_expr(), vec![]); |
178 | } | 196 | } |
197 | |||
179 | match expr { | 198 | match expr { |
180 | ast::Expr::IfExpr(e) => { | 199 | ast::Expr::IfExpr(e) => { |
181 | let then_branch = self.collect_block_opt(e.then_branch()); | 200 | let then_branch = self.collect_block_opt(e.then_branch()); |
@@ -205,32 +224,48 @@ impl ExprCollector<'_> { | |||
205 | guard: None, | 224 | guard: None, |
206 | }, | 225 | }, |
207 | ]; | 226 | ]; |
208 | return self | 227 | let children_exprs = if let Some(else_branch) = else_branch { |
209 | .alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr); | 228 | vec![match_expr, then_branch, else_branch] |
229 | } else { | ||
230 | vec![match_expr, then_branch] | ||
231 | }; | ||
232 | return ( | ||
233 | self.alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr), | ||
234 | children_exprs, | ||
235 | ); | ||
210 | } | 236 | } |
211 | }, | 237 | }, |
212 | }; | 238 | }; |
213 | 239 | ||
214 | self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) | 240 | let children_exprs = if let Some(else_branch) = else_branch { |
241 | vec![then_branch, else_branch, condition] | ||
242 | } else { | ||
243 | vec![then_branch, condition] | ||
244 | }; | ||
245 | |||
246 | ( | ||
247 | self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr), | ||
248 | children_exprs, | ||
249 | ) | ||
215 | } | 250 | } |
216 | ast::Expr::EffectExpr(e) => match e.effect() { | 251 | ast::Expr::EffectExpr(e) => match e.effect() { |
217 | ast::Effect::Try(_) => { | 252 | ast::Effect::Try(_) => { |
218 | let body = self.collect_block_opt(e.block_expr()); | 253 | let body = self.collect_block_opt(e.block_expr()); |
219 | self.alloc_expr(Expr::TryBlock { body }, syntax_ptr) | 254 | (self.alloc_expr(Expr::TryBlock { body }, syntax_ptr), vec![body]) |
220 | } | 255 | } |
221 | ast::Effect::Unsafe(_) => { | 256 | ast::Effect::Unsafe(_) => { |
222 | let body = self.collect_block_opt(e.block_expr()); | 257 | let body = self.collect_block_opt(e.block_expr()); |
223 | self.alloc_expr(Expr::Unsafe { body }, syntax_ptr) | 258 | (self.alloc_expr(Expr::Unsafe { body }, syntax_ptr), vec![body]) |
224 | } | 259 | } |
225 | // FIXME: we need to record these effects somewhere... | 260 | // FIXME: we need to record these effects somewhere... |
226 | ast::Effect::Async(_) | ast::Effect::Label(_) => { | 261 | ast::Effect::Async(_) | ast::Effect::Label(_) => { |
227 | self.collect_block_opt(e.block_expr()) | 262 | (self.collect_block_opt(e.block_expr()), vec![]) |
228 | } | 263 | } |
229 | }, | 264 | }, |
230 | ast::Expr::BlockExpr(e) => self.collect_block(e), | 265 | ast::Expr::BlockExpr(e) => (self.collect_block(e), vec![]), |
231 | ast::Expr::LoopExpr(e) => { | 266 | ast::Expr::LoopExpr(e) => { |
232 | let body = self.collect_block_opt(e.loop_body()); | 267 | let body = self.collect_block_opt(e.loop_body()); |
233 | self.alloc_expr( | 268 | (self.alloc_expr( |
234 | Expr::Loop { | 269 | Expr::Loop { |
235 | body, | 270 | body, |
236 | label: e | 271 | label: e |
@@ -239,7 +274,7 @@ impl ExprCollector<'_> { | |||
239 | .map(|l| Name::new_lifetime(&l)), | 274 | .map(|l| Name::new_lifetime(&l)), |
240 | }, | 275 | }, |
241 | syntax_ptr, | 276 | syntax_ptr, |
242 | ) | 277 | ), vec![body]) |
243 | } | 278 | } |
244 | ast::Expr::WhileExpr(e) => { | 279 | ast::Expr::WhileExpr(e) => { |
245 | let body = self.collect_block_opt(e.loop_body()); | 280 | let body = self.collect_block_opt(e.loop_body()); |
@@ -250,6 +285,7 @@ impl ExprCollector<'_> { | |||
250 | None => self.collect_expr_opt(condition.expr()), | 285 | None => self.collect_expr_opt(condition.expr()), |
251 | // if let -- desugar to match | 286 | // if let -- desugar to match |
252 | Some(pat) => { | 287 | Some(pat) => { |
288 | // FIXME(pfaria) track the break and arms parents here? | ||
253 | mark::hit!(infer_resolve_while_let); | 289 | mark::hit!(infer_resolve_while_let); |
254 | let pat = self.collect_pat(pat); | 290 | let pat = self.collect_pat(pat); |
255 | let match_expr = self.collect_expr_opt(condition.expr()); | 291 | let match_expr = self.collect_expr_opt(condition.expr()); |
@@ -262,7 +298,7 @@ impl ExprCollector<'_> { | |||
262 | ]; | 298 | ]; |
263 | let match_expr = | 299 | let match_expr = |
264 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); | 300 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); |
265 | return self.alloc_expr( | 301 | return (self.alloc_expr( |
266 | Expr::Loop { | 302 | Expr::Loop { |
267 | body: match_expr, | 303 | body: match_expr, |
268 | label: e | 304 | label: e |
@@ -271,12 +307,12 @@ impl ExprCollector<'_> { | |||
271 | .map(|l| Name::new_lifetime(&l)), | 307 | .map(|l| Name::new_lifetime(&l)), |
272 | }, | 308 | }, |
273 | syntax_ptr, | 309 | syntax_ptr, |
274 | ); | 310 | ), vec![match_expr]); |
275 | } | 311 | } |
276 | }, | 312 | }, |
277 | }; | 313 | }; |
278 | 314 | ||
279 | self.alloc_expr( | 315 | (self.alloc_expr( |
280 | Expr::While { | 316 | Expr::While { |
281 | condition, | 317 | condition, |
282 | body, | 318 | body, |
@@ -286,13 +322,13 @@ impl ExprCollector<'_> { | |||
286 | .map(|l| Name::new_lifetime(&l)), | 322 | .map(|l| Name::new_lifetime(&l)), |
287 | }, | 323 | }, |
288 | syntax_ptr, | 324 | syntax_ptr, |
289 | ) | 325 | ), vec![body, condition]) |
290 | } | 326 | } |
291 | ast::Expr::ForExpr(e) => { | 327 | ast::Expr::ForExpr(e) => { |
292 | let iterable = self.collect_expr_opt(e.iterable()); | 328 | let iterable = self.collect_expr_opt(e.iterable()); |
293 | let pat = self.collect_pat_opt(e.pat()); | 329 | let pat = self.collect_pat_opt(e.pat()); |
294 | let body = self.collect_block_opt(e.loop_body()); | 330 | let body = self.collect_block_opt(e.loop_body()); |
295 | self.alloc_expr( | 331 | (self.alloc_expr( |
296 | Expr::For { | 332 | Expr::For { |
297 | iterable, | 333 | iterable, |
298 | pat, | 334 | pat, |
@@ -303,7 +339,7 @@ impl ExprCollector<'_> { | |||
303 | .map(|l| Name::new_lifetime(&l)), | 339 | .map(|l| Name::new_lifetime(&l)), |
304 | }, | 340 | }, |
305 | syntax_ptr, | 341 | syntax_ptr, |
306 | ) | 342 | ), vec![iterable, body]) |
307 | } | 343 | } |
308 | ast::Expr::CallExpr(e) => { | 344 | ast::Expr::CallExpr(e) => { |
309 | let callee = self.collect_expr_opt(e.expr()); | 345 | let callee = self.collect_expr_opt(e.expr()); |
@@ -312,41 +348,56 @@ impl ExprCollector<'_> { | |||
312 | } else { | 348 | } else { |
313 | Vec::new() | 349 | Vec::new() |
314 | }; | 350 | }; |
315 | self.alloc_expr(Expr::Call { callee, args }, syntax_ptr) | 351 | let mut children_exprs = args.clone(); |
352 | children_exprs.push(callee); | ||
353 | (self.alloc_expr(Expr::Call { callee, args }, syntax_ptr), children_exprs) | ||
316 | } | 354 | } |
317 | ast::Expr::MethodCallExpr(e) => { | 355 | ast::Expr::MethodCallExpr(e) => { |
318 | let receiver = self.collect_expr_opt(e.expr()); | 356 | let receiver = self.collect_expr_opt(e.expr()); |
319 | let args = if let Some(arg_list) = e.arg_list() { | 357 | let args = if let Some(arg_list) = e.arg_list() { |
320 | arg_list.args().map(|e| self.collect_expr(e)).collect() | 358 | arg_list.args().map(|e| self.collect_expr(e)).collect() |
321 | } else { | 359 | } else { |
322 | Vec::new() | 360 | vec![] |
323 | }; | 361 | }; |
324 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); | 362 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); |
325 | let generic_args = | 363 | let generic_args = |
326 | e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); | 364 | e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); |
327 | self.alloc_expr( | 365 | let mut children_exprs = args.clone(); |
328 | Expr::MethodCall { receiver, method_name, args, generic_args }, | 366 | children_exprs.push(receiver); |
329 | syntax_ptr, | 367 | ( |
368 | self.alloc_expr( | ||
369 | Expr::MethodCall { receiver, method_name, args, generic_args }, | ||
370 | syntax_ptr, | ||
371 | ), | ||
372 | children_exprs, | ||
330 | ) | 373 | ) |
331 | } | 374 | } |
332 | ast::Expr::MatchExpr(e) => { | 375 | ast::Expr::MatchExpr(e) => { |
333 | let expr = self.collect_expr_opt(e.expr()); | 376 | let expr = self.collect_expr_opt(e.expr()); |
334 | let arms = if let Some(match_arm_list) = e.match_arm_list() { | 377 | let (arms, mut children_exprs): (Vec<_>, Vec<_>) = |
335 | match_arm_list | 378 | if let Some(match_arm_list) = e.match_arm_list() { |
336 | .arms() | 379 | match_arm_list |
337 | .map(|arm| MatchArm { | 380 | .arms() |
338 | pat: self.collect_pat_opt(arm.pat()), | 381 | .map(|arm| { |
339 | expr: self.collect_expr_opt(arm.expr()), | 382 | let expr = self.collect_expr_opt(arm.expr()); |
340 | guard: arm | 383 | ( |
341 | .guard() | 384 | MatchArm { |
342 | .and_then(|guard| guard.expr()) | 385 | pat: self.collect_pat_opt(arm.pat()), |
343 | .map(|e| self.collect_expr(e)), | 386 | expr, |
344 | }) | 387 | guard: arm |
345 | .collect() | 388 | .guard() |
346 | } else { | 389 | .and_then(|guard| guard.expr()) |
347 | Vec::new() | 390 | .map(|e| self.collect_expr(e)), |
348 | }; | 391 | }, |
349 | self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr) | 392 | expr, |
393 | ) | ||
394 | }) | ||
395 | .unzip() | ||
396 | } else { | ||
397 | (vec![], vec![]) | ||
398 | }; | ||
399 | children_exprs.push(expr); | ||
400 | (self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr), children_exprs) | ||
350 | } | 401 | } |
351 | ast::Expr::PathExpr(e) => { | 402 | ast::Expr::PathExpr(e) => { |
352 | let path = e | 403 | let path = e |
@@ -354,35 +405,35 @@ impl ExprCollector<'_> { | |||
354 | .and_then(|path| self.expander.parse_path(path)) | 405 | .and_then(|path| self.expander.parse_path(path)) |
355 | .map(Expr::Path) | 406 | .map(Expr::Path) |
356 | .unwrap_or(Expr::Missing); | 407 | .unwrap_or(Expr::Missing); |
357 | self.alloc_expr(path, syntax_ptr) | 408 | (self.alloc_expr(path, syntax_ptr), vec![]) |
358 | } | 409 | } |
359 | ast::Expr::ContinueExpr(e) => self.alloc_expr( | 410 | ast::Expr::ContinueExpr(e) => (self.alloc_expr( |
360 | Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, | 411 | Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, |
361 | syntax_ptr, | 412 | syntax_ptr, |
362 | ), | 413 | ), vec![]), |
363 | ast::Expr::BreakExpr(e) => { | 414 | ast::Expr::BreakExpr(e) => { |
364 | let expr = e.expr().map(|e| self.collect_expr(e)); | 415 | let expr = e.expr().map(|e| self.collect_expr(e)); |
365 | self.alloc_expr( | 416 | (self.alloc_expr( |
366 | Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, | 417 | Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, |
367 | syntax_ptr, | 418 | syntax_ptr, |
368 | ) | 419 | ), expr.into_iter().collect()) |
369 | } | 420 | } |
370 | ast::Expr::ParenExpr(e) => { | 421 | ast::Expr::ParenExpr(e) => { |
371 | let inner = self.collect_expr_opt(e.expr()); | 422 | let inner = self.collect_expr_opt(e.expr()); |
372 | // make the paren expr point to the inner expression as well | 423 | // make the paren expr point to the inner expression as well |
373 | let src = self.expander.to_source(syntax_ptr); | 424 | let src = self.expander.to_source(syntax_ptr); |
374 | self.source_map.expr_map.insert(src, inner); | 425 | self.source_map.expr_map.insert(src, inner); |
375 | inner | 426 | (inner, vec![]) |
376 | } | 427 | } |
377 | ast::Expr::ReturnExpr(e) => { | 428 | ast::Expr::ReturnExpr(e) => { |
378 | let expr = e.expr().map(|e| self.collect_expr(e)); | 429 | let expr = e.expr().map(|e| self.collect_expr(e)); |
379 | self.alloc_expr(Expr::Return { expr }, syntax_ptr) | 430 | (self.alloc_expr(Expr::Return { expr }, syntax_ptr), expr.into_iter().collect()) |
380 | } | 431 | } |
381 | ast::Expr::RecordLit(e) => { | 432 | ast::Expr::RecordLit(e) => { |
382 | let path = e.path().and_then(|path| self.expander.parse_path(path)); | 433 | let path = e.path().and_then(|path| self.expander.parse_path(path)); |
383 | let mut field_ptrs = Vec::new(); | 434 | let mut field_ptrs = Vec::new(); |
384 | let record_lit = if let Some(nfl) = e.record_field_list() { | 435 | let (record_lit, children) = if let Some(nfl) = e.record_field_list() { |
385 | let fields = nfl | 436 | let (fields, children): (Vec<_>, Vec<_>) = nfl |
386 | .fields() | 437 | .fields() |
387 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) | 438 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) |
388 | .filter_map(|field| { | 439 | .filter_map(|field| { |
@@ -391,19 +442,20 @@ impl ExprCollector<'_> { | |||
391 | } | 442 | } |
392 | let name = field.field_name()?.as_name(); | 443 | let name = field.field_name()?.as_name(); |
393 | 444 | ||
394 | Some(RecordLitField { | 445 | let expr = match field.expr() { |
395 | name, | 446 | Some(e) => self.collect_expr(e), |
396 | expr: match field.expr() { | 447 | None => self.missing_expr(), |
397 | Some(e) => self.collect_expr(e), | 448 | }; |
398 | None => self.missing_expr(), | 449 | Some((RecordLitField { name, expr }, expr)) |
399 | }, | ||
400 | }) | ||
401 | }) | 450 | }) |
402 | .collect(); | 451 | .unzip(); |
403 | let spread = nfl.spread().map(|s| self.collect_expr(s)); | 452 | let spread = nfl.spread().map(|s| self.collect_expr(s)); |
404 | Expr::RecordLit { path, fields, spread } | 453 | ( |
454 | Expr::RecordLit { path, fields, spread: spread }, | ||
455 | children.into_iter().chain(spread.into_iter()).collect(), | ||
456 | ) | ||
405 | } else { | 457 | } else { |
406 | Expr::RecordLit { path, fields: Vec::new(), spread: None } | 458 | (Expr::RecordLit { path, fields: Vec::new(), spread: None }, vec![]) |
407 | }; | 459 | }; |
408 | 460 | ||
409 | let res = self.alloc_expr(record_lit, syntax_ptr); | 461 | let res = self.alloc_expr(record_lit, syntax_ptr); |
@@ -411,7 +463,7 @@ impl ExprCollector<'_> { | |||
411 | let src = self.expander.to_source(ptr); | 463 | let src = self.expander.to_source(ptr); |
412 | self.source_map.field_map.insert((res, i), src); | 464 | self.source_map.field_map.insert((res, i), src); |
413 | } | 465 | } |
414 | res | 466 | (res, children) |
415 | } | 467 | } |
416 | ast::Expr::FieldExpr(e) => { | 468 | ast::Expr::FieldExpr(e) => { |
417 | let expr = self.collect_expr_opt(e.expr()); | 469 | let expr = self.collect_expr_opt(e.expr()); |
@@ -419,20 +471,20 @@ impl ExprCollector<'_> { | |||
419 | Some(kind) => kind.as_name(), | 471 | Some(kind) => kind.as_name(), |
420 | _ => Name::missing(), | 472 | _ => Name::missing(), |
421 | }; | 473 | }; |
422 | self.alloc_expr(Expr::Field { expr, name }, syntax_ptr) | 474 | (self.alloc_expr(Expr::Field { expr, name }, syntax_ptr), vec![expr]) |
423 | } | 475 | } |
424 | ast::Expr::AwaitExpr(e) => { | 476 | ast::Expr::AwaitExpr(e) => { |
425 | let expr = self.collect_expr_opt(e.expr()); | 477 | let expr = self.collect_expr_opt(e.expr()); |
426 | self.alloc_expr(Expr::Await { expr }, syntax_ptr) | 478 | (self.alloc_expr(Expr::Await { expr }, syntax_ptr), vec![expr]) |
427 | } | 479 | } |
428 | ast::Expr::TryExpr(e) => { | 480 | ast::Expr::TryExpr(e) => { |
429 | let expr = self.collect_expr_opt(e.expr()); | 481 | let expr = self.collect_expr_opt(e.expr()); |
430 | self.alloc_expr(Expr::Try { expr }, syntax_ptr) | 482 | (self.alloc_expr(Expr::Try { expr }, syntax_ptr), vec![expr]) |
431 | } | 483 | } |
432 | ast::Expr::CastExpr(e) => { | 484 | ast::Expr::CastExpr(e) => { |
433 | let expr = self.collect_expr_opt(e.expr()); | 485 | let expr = self.collect_expr_opt(e.expr()); |
434 | let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref()); | 486 | let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref()); |
435 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) | 487 | (self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr), vec![expr]) |
436 | } | 488 | } |
437 | ast::Expr::RefExpr(e) => { | 489 | ast::Expr::RefExpr(e) => { |
438 | let expr = self.collect_expr_opt(e.expr()); | 490 | let expr = self.collect_expr_opt(e.expr()); |
@@ -455,9 +507,9 @@ impl ExprCollector<'_> { | |||
455 | ast::Expr::PrefixExpr(e) => { | 507 | ast::Expr::PrefixExpr(e) => { |
456 | let expr = self.collect_expr_opt(e.expr()); | 508 | let expr = self.collect_expr_opt(e.expr()); |
457 | if let Some(op) = e.op_kind() { | 509 | if let Some(op) = e.op_kind() { |
458 | self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr) | 510 | (self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr), vec![expr]) |
459 | } else { | 511 | } else { |
460 | self.alloc_expr(Expr::Missing, syntax_ptr) | 512 | (self.alloc_expr(Expr::Missing, syntax_ptr), vec![]) |
461 | } | 513 | } |
462 | } | 514 | } |
463 | ast::Expr::LambdaExpr(e) => { | 515 | ast::Expr::LambdaExpr(e) => { |
@@ -477,21 +529,24 @@ impl ExprCollector<'_> { | |||
477 | .and_then(|r| r.type_ref()) | 529 | .and_then(|r| r.type_ref()) |
478 | .map(|it| TypeRef::from_ast(&self.ctx(), it)); | 530 | .map(|it| TypeRef::from_ast(&self.ctx(), it)); |
479 | let body = self.collect_expr_opt(e.body()); | 531 | let body = self.collect_expr_opt(e.body()); |
480 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) | 532 | ( |
533 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr), | ||
534 | vec![body], | ||
535 | ) | ||
481 | } | 536 | } |
482 | ast::Expr::BinExpr(e) => { | 537 | ast::Expr::BinExpr(e) => { |
483 | let lhs = self.collect_expr_opt(e.lhs()); | 538 | let lhs = self.collect_expr_opt(e.lhs()); |
484 | let rhs = self.collect_expr_opt(e.rhs()); | 539 | let rhs = self.collect_expr_opt(e.rhs()); |
485 | let op = e.op_kind().map(BinaryOp::from); | 540 | let op = e.op_kind().map(BinaryOp::from); |
486 | self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr) | 541 | (self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr), vec![lhs, rhs]) |
487 | } | 542 | } |
488 | ast::Expr::TupleExpr(e) => { | 543 | ast::Expr::TupleExpr(e) => { |
489 | let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); | 544 | let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect::<Vec<_>>(); |
490 | self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr) | 545 | (self.alloc_expr(Expr::Tuple { exprs: exprs.clone() }, syntax_ptr), exprs) |
491 | } | 546 | } |
492 | ast::Expr::BoxExpr(e) => { | 547 | ast::Expr::BoxExpr(e) => { |
493 | let expr = self.collect_expr_opt(e.expr()); | 548 | let expr = self.collect_expr_opt(e.expr()); |
494 | self.alloc_expr(Expr::Box { expr }, syntax_ptr) | 549 | (self.alloc_expr(Expr::Box { expr }, syntax_ptr), vec![expr]) |
495 | } | 550 | } |
496 | 551 | ||
497 | ast::Expr::ArrayExpr(e) => { | 552 | ast::Expr::ArrayExpr(e) => { |
@@ -499,34 +554,46 @@ impl ExprCollector<'_> { | |||
499 | 554 | ||
500 | match kind { | 555 | match kind { |
501 | ArrayExprKind::ElementList(e) => { | 556 | ArrayExprKind::ElementList(e) => { |
502 | let exprs = e.map(|expr| self.collect_expr(expr)).collect(); | 557 | let exprs = e.map(|expr| self.collect_expr(expr)).collect::<Vec<_>>(); |
503 | self.alloc_expr(Expr::Array(Array::ElementList(exprs)), syntax_ptr) | 558 | ( |
559 | self.alloc_expr( | ||
560 | Expr::Array(Array::ElementList(exprs.clone())), | ||
561 | syntax_ptr, | ||
562 | ), | ||
563 | exprs, | ||
564 | ) | ||
504 | } | 565 | } |
505 | ArrayExprKind::Repeat { initializer, repeat } => { | 566 | ArrayExprKind::Repeat { initializer, repeat } => { |
506 | let initializer = self.collect_expr_opt(initializer); | 567 | let initializer = self.collect_expr_opt(initializer); |
507 | let repeat = self.collect_expr_opt(repeat); | 568 | let repeat = self.collect_expr_opt(repeat); |
508 | self.alloc_expr( | 569 | ( |
509 | Expr::Array(Array::Repeat { initializer, repeat }), | 570 | self.alloc_expr( |
510 | syntax_ptr, | 571 | Expr::Array(Array::Repeat { initializer, repeat }), |
572 | syntax_ptr, | ||
573 | ), | ||
574 | vec![initializer, repeat], | ||
511 | ) | 575 | ) |
512 | } | 576 | } |
513 | } | 577 | } |
514 | } | 578 | } |
515 | 579 | ||
516 | ast::Expr::Literal(e) => self.alloc_expr(Expr::Literal(e.kind().into()), syntax_ptr), | 580 | ast::Expr::Literal(e) => { |
581 | (self.alloc_expr(Expr::Literal(e.kind().into()), syntax_ptr), vec![]) | ||
582 | } | ||
517 | ast::Expr::IndexExpr(e) => { | 583 | ast::Expr::IndexExpr(e) => { |
518 | let base = self.collect_expr_opt(e.base()); | 584 | let base = self.collect_expr_opt(e.base()); |
519 | let index = self.collect_expr_opt(e.index()); | 585 | let index = self.collect_expr_opt(e.index()); |
520 | self.alloc_expr(Expr::Index { base, index }, syntax_ptr) | 586 | (self.alloc_expr(Expr::Index { base, index }, syntax_ptr), vec![base, index]) |
521 | } | 587 | } |
522 | ast::Expr::RangeExpr(e) => { | 588 | ast::Expr::RangeExpr(e) => { |
523 | let lhs = e.start().map(|lhs| self.collect_expr(lhs)); | 589 | let lhs = e.start().map(|lhs| self.collect_expr(lhs)); |
524 | let rhs = e.end().map(|rhs| self.collect_expr(rhs)); | 590 | let rhs = e.end().map(|rhs| self.collect_expr(rhs)); |
525 | match e.op_kind() { | 591 | match e.op_kind() { |
526 | Some(range_type) => { | 592 | Some(range_type) => ( |
527 | self.alloc_expr(Expr::Range { lhs, rhs, range_type }, syntax_ptr) | 593 | self.alloc_expr(Expr::Range { lhs, rhs, range_type }, syntax_ptr), |
528 | } | 594 | lhs.into_iter().chain(rhs.into_iter()).collect(), |
529 | None => self.alloc_expr(Expr::Missing, syntax_ptr), | 595 | ), |
596 | None => (self.alloc_expr(Expr::Missing, syntax_ptr), vec![]), | ||
530 | } | 597 | } |
531 | } | 598 | } |
532 | ast::Expr::MacroCall(e) => { | 599 | ast::Expr::MacroCall(e) => { |
@@ -540,7 +607,7 @@ impl ExprCollector<'_> { | |||
540 | self.body.item_scope.define_legacy_macro(name, mac); | 607 | self.body.item_scope.define_legacy_macro(name, mac); |
541 | 608 | ||
542 | // FIXME: do we still need to allocate this as missing ? | 609 | // FIXME: do we still need to allocate this as missing ? |
543 | self.alloc_expr(Expr::Missing, syntax_ptr) | 610 | (self.alloc_expr(Expr::Missing, syntax_ptr), vec![]) |
544 | } else { | 611 | } else { |
545 | let macro_call = self.expander.to_source(AstPtr::new(&e)); | 612 | let macro_call = self.expander.to_source(AstPtr::new(&e)); |
546 | match self.expander.enter_expand(self.db, Some(&self.body.item_scope), e) { | 613 | match self.expander.enter_expand(self.db, Some(&self.body.item_scope), e) { |
@@ -553,15 +620,15 @@ impl ExprCollector<'_> { | |||
553 | self.item_trees.insert(self.expander.current_file_id, item_tree); | 620 | self.item_trees.insert(self.expander.current_file_id, item_tree); |
554 | let id = self.collect_expr(expansion); | 621 | let id = self.collect_expr(expansion); |
555 | self.expander.exit(self.db, mark); | 622 | self.expander.exit(self.db, mark); |
556 | id | 623 | (id, vec![]) |
557 | } | 624 | } |
558 | None => self.alloc_expr(Expr::Missing, syntax_ptr), | 625 | None => (self.alloc_expr(Expr::Missing, syntax_ptr), vec![]), |
559 | } | 626 | } |
560 | } | 627 | } |
561 | } | 628 | } |
562 | 629 | ||
563 | // FIXME implement HIR for these: | 630 | // FIXME implement HIR for these: |
564 | ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 631 | ast::Expr::Label(_e) => (self.alloc_expr(Expr::Missing, syntax_ptr), vec![]), |
565 | } | 632 | } |
566 | } | 633 | } |
567 | 634 | ||
@@ -600,9 +667,14 @@ impl ExprCollector<'_> { | |||
600 | } | 667 | } |
601 | 668 | ||
602 | fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { | 669 | fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { |
670 | let parent_and_children = self.collect_block_inner(block); | ||
671 | self.update_parent_map(parent_and_children) | ||
672 | } | ||
673 | |||
674 | fn collect_block_inner(&mut self, block: ast::BlockExpr) -> (ExprId, Vec<ExprId>) { | ||
603 | let syntax_node_ptr = AstPtr::new(&block.clone().into()); | 675 | let syntax_node_ptr = AstPtr::new(&block.clone().into()); |
604 | self.collect_block_items(&block); | 676 | self.collect_block_items(&block); |
605 | let statements = block | 677 | let (statements, children_exprs): (Vec<_>, Vec<_>) = block |
606 | .statements() | 678 | .statements() |
607 | .map(|s| match s { | 679 | .map(|s| match s { |
608 | ast::Stmt::LetStmt(stmt) => { | 680 | ast::Stmt::LetStmt(stmt) => { |
@@ -610,14 +682,18 @@ impl ExprCollector<'_> { | |||
610 | let type_ref = | 682 | let type_ref = |
611 | stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it)); | 683 | stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it)); |
612 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); | 684 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); |
613 | Statement::Let { pat, type_ref, initializer } | 685 | (Statement::Let { pat, type_ref, initializer }, initializer) |
686 | } | ||
687 | ast::Stmt::ExprStmt(stmt) => { | ||
688 | let expr = self.collect_expr_opt(stmt.expr()); | ||
689 | (Statement::Expr(expr), Some(expr)) | ||
614 | } | 690 | } |
615 | ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())), | ||
616 | }) | 691 | }) |
617 | .collect(); | 692 | .unzip(); |
618 | let tail = block.expr().map(|e| self.collect_expr(e)); | 693 | let tail = block.expr().map(|e| self.collect_expr(e)); |
619 | let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t)); | 694 | let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t)); |
620 | self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr) | 695 | let children_exprs = children_exprs.into_iter().flatten().chain(tail.into_iter()).collect(); |
696 | (self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr), children_exprs) | ||
621 | } | 697 | } |
622 | 698 | ||
623 | fn collect_block_items(&mut self, block: &ast::BlockExpr) { | 699 | fn collect_block_items(&mut self, block: &ast::BlockExpr) { |
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs index 5f332aadb..3942aada5 100644 --- a/crates/ra_hir_ty/src/expr.rs +++ b/crates/ra_hir_ty/src/expr.rs | |||
@@ -333,15 +333,12 @@ pub fn unsafe_expressions( | |||
333 | def: DefWithBodyId, | 333 | def: DefWithBodyId, |
334 | ) -> Vec<UnsafeExpr> { | 334 | ) -> Vec<UnsafeExpr> { |
335 | let mut unsafe_exprs = vec![]; | 335 | let mut unsafe_exprs = vec![]; |
336 | let mut unsafe_block_scopes = vec![]; | 336 | let mut unsafe_block_exprs = FxHashSet::default(); |
337 | let body = db.body(def); | 337 | let body = db.body(def); |
338 | let expr_scopes = db.expr_scopes(def); | ||
339 | for (id, expr) in body.exprs.iter() { | 338 | for (id, expr) in body.exprs.iter() { |
340 | match expr { | 339 | match expr { |
341 | Expr::Unsafe { body } => { | 340 | Expr::Unsafe { .. } => { |
342 | if let Some(scope) = expr_scopes.scope_for(*body) { | 341 | unsafe_block_exprs.insert(id); |
343 | unsafe_block_scopes.push(scope); | ||
344 | } | ||
345 | } | 342 | } |
346 | Expr::Call { callee, .. } => { | 343 | Expr::Call { callee, .. } => { |
347 | let ty = &infer[*callee]; | 344 | let ty = &infer[*callee]; |
@@ -374,12 +371,13 @@ pub fn unsafe_expressions( | |||
374 | } | 371 | } |
375 | 372 | ||
376 | 'unsafe_exprs: for unsafe_expr in &mut unsafe_exprs { | 373 | 'unsafe_exprs: for unsafe_expr in &mut unsafe_exprs { |
377 | let scope = expr_scopes.scope_for(unsafe_expr.expr); | 374 | let mut child = unsafe_expr.expr; |
378 | for scope in expr_scopes.scope_chain(scope) { | 375 | while let Some(parent) = body.parent_map.get(&child) { |
379 | if unsafe_block_scopes.contains(&scope) { | 376 | if unsafe_block_exprs.contains(parent) { |
380 | unsafe_expr.inside_unsafe_block = true; | 377 | unsafe_expr.inside_unsafe_block = true; |
381 | continue 'unsafe_exprs; | 378 | continue 'unsafe_exprs; |
382 | } | 379 | } |
380 | child = *parent; | ||
383 | } | 381 | } |
384 | } | 382 | } |
385 | 383 | ||
@@ -417,8 +415,10 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> { | |||
417 | 415 | ||
418 | let (_, body_source) = db.body_with_source_map(def); | 416 | let (_, body_source) = db.body_with_source_map(def); |
419 | for unsafe_expr in unsafe_expressions { | 417 | for unsafe_expr in unsafe_expressions { |
420 | if let Ok(in_file) = body_source.as_ref().expr_syntax(unsafe_expr.expr) { | 418 | if !unsafe_expr.inside_unsafe_block { |
421 | self.sink.push(MissingUnsafe { file: in_file.file_id, expr: in_file.value }) | 419 | if let Ok(in_file) = body_source.as_ref().expr_syntax(unsafe_expr.expr) { |
420 | self.sink.push(MissingUnsafe { file: in_file.file_id, expr: in_file.value }) | ||
421 | } | ||
422 | } | 422 | } |
423 | } | 423 | } |
424 | } | 424 | } |
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 26b3aeb50..496cb428b 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -638,7 +638,7 @@ fn nothing_to_see_move_along() { | |||
638 | .diagnostics() | 638 | .diagnostics() |
639 | .0; | 639 | .0; |
640 | 640 | ||
641 | assert_snapshot!(diagnostics, @""); | 641 | assert_snapshot!(diagnostics, @r#""*x": This operation is unsafe and requires an unsafe function or block"#); |
642 | } | 642 | } |
643 | 643 | ||
644 | #[test] | 644 | #[test] |