aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorPaul Daniel Faria <[email protected]>2020-06-02 23:44:04 +0100
committerPaul Daniel Faria <[email protected]>2020-06-27 15:13:14 +0100
commit2fc92fa28cda858c25fea2e378c2eb73e7f65247 (patch)
tree276b53c89a7ca76b20ea4e8f80f41d85bcfbb9f8 /crates
parentf78df42f813504a376dca555b04ac427582f542c (diff)
Remove track_parent and parent_map, replace with simple walk in missign unsafe validator
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_def/src/body.rs1
-rw-r--r--crates/ra_hir_def/src/body/lower.rs369
-rw-r--r--crates/ra_hir_ty/src/unsafe_validation.rs42
3 files changed, 121 insertions, 291 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 14a1f4773..4f2350915 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -184,7 +184,6 @@ 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: ArenaMap<ExprId, ExprId>,
188} 187}
189 188
190pub type ExprPtr = AstPtr<ast::Expr>; 189pub 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 4240c6ad8..fdd2be843 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -7,7 +7,7 @@ use hir_expand::{
7 name::{name, AsName, Name}, 7 name::{name, AsName, Name},
8 HirFileId, MacroDefId, MacroDefKind, 8 HirFileId, MacroDefId, MacroDefKind,
9}; 9};
10use ra_arena::{map::ArenaMap, Arena}; 10use ra_arena::Arena;
11use ra_syntax::{ 11use ra_syntax::{
12 ast::{ 12 ast::{
13 self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner, 13 self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner,
@@ -74,7 +74,6 @@ pub(super) fn lower(
74 params: Vec::new(), 74 params: Vec::new(),
75 body_expr: dummy_expr_id(), 75 body_expr: dummy_expr_id(),
76 item_scope: Default::default(), 76 item_scope: Default::default(),
77 parent_map: ArenaMap::default(),
78 }, 77 },
79 item_trees: { 78 item_trees: {
80 let mut map = FxHashMap::default(); 79 let mut map = FxHashMap::default();
@@ -96,40 +95,6 @@ struct ExprCollector<'a> {
96 item_trees: FxHashMap<HirFileId, Arc<ItemTree>>, 95 item_trees: FxHashMap<HirFileId, Arc<ItemTree>>,
97} 96}
98 97
99macro_rules! track_parent {
100 (@build $collector:ident, $parent:expr $(,)?) => {
101 $parent
102 };
103 (@build $collector:ident, $parent:expr, opt $expr:ident $($rest:tt)*) => {
104 {
105 if let Some(expr) = $expr {
106 $collector.body.parent_map.insert(expr, $parent);
107 }
108 track_parent!(@build $collector, $parent $($rest)*)
109 }
110 };
111 (@build $collector:ident, $parent:expr, vec $expr:ident $($rest:tt)*) => {
112 {
113 for expr in $expr {
114 $collector.body.parent_map.insert(expr, $parent);
115 }
116 track_parent!(@build $collector, $parent $($rest)*)
117 }
118 };
119 (@build $collector:ident, $parent:expr, $expr:ident $($rest:tt)*) => {
120 {
121 $collector.body.parent_map.insert($expr, $parent);
122 track_parent!(@build $collector, $parent $($rest)*)
123 }
124 };
125 ($collector:ident, $parent:expr, $($rest:tt)*) => {
126 {
127 let parent = $parent;
128 track_parent!(@build $collector, parent, $($rest)*)
129 }
130 }
131}
132
133impl ExprCollector<'_> { 98impl ExprCollector<'_> {
134 fn collect( 99 fn collect(
135 mut self, 100 mut self,
@@ -206,51 +171,7 @@ impl ExprCollector<'_> {
206 id 171 id
207 } 172 }
208 173
209 fn update_parent_map(
210 &mut self,
211 (parent_expr, children_exprs): (ExprId, Vec<ExprId>),
212 ) -> ExprId {
213 for child_expr in children_exprs {
214 self.body.parent_map.insert(child_expr, parent_expr);
215 }
216
217 parent_expr
218 }
219
220 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { 174 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
221 let expr_id = self.collect_expr_inner(expr);
222
223 debug_assert!({
224 let mut found_count = 0;
225 let mut incr = || {
226 found_count += 1;
227 true
228 };
229 let mut all_children_found = true;
230 self.body[expr_id].walk_child_exprs(|child| {
231 all_children_found = all_children_found
232 && self
233 .body
234 .parent_map
235 .get(child)
236 .map(|parent| *parent == expr_id)
237 .unwrap_or(false)
238 && incr()
239 });
240
241 if all_children_found {
242 let child_count_in_map =
243 self.body.parent_map.iter().filter(|&(_, parent)| *parent == expr_id).count();
244 found_count == child_count_in_map
245 } else {
246 false
247 }
248 });
249
250 expr_id
251 }
252
253 fn collect_expr_inner(&mut self, expr: ast::Expr) -> ExprId {
254 let syntax_ptr = AstPtr::new(&expr); 175 let syntax_ptr = AstPtr::new(&expr);
255 if !self.expander.is_cfg_enabled(&expr) { 176 if !self.expander.is_cfg_enabled(&expr) {
256 return self.missing_expr(); 177 return self.missing_expr();
@@ -285,30 +206,22 @@ impl ExprCollector<'_> {
285 guard: None, 206 guard: None,
286 }, 207 },
287 ]; 208 ];
288 let arm_exprs = arms.iter().map(|arm| arm.expr).collect::<Vec<_>>(); 209 return self
289 return track_parent!( 210 .alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr);
290 self,
291 self.alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr),
292 match_expr, vec arm_exprs
293 );
294 } 211 }
295 }, 212 },
296 }; 213 };
297 214
298 track_parent!( 215 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
299 self,
300 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr),
301 then_branch, opt else_branch, condition
302 )
303 } 216 }
304 ast::Expr::EffectExpr(e) => match e.effect() { 217 ast::Expr::EffectExpr(e) => match e.effect() {
305 ast::Effect::Try(_) => { 218 ast::Effect::Try(_) => {
306 let body = self.collect_block_opt(e.block_expr()); 219 let body = self.collect_block_opt(e.block_expr());
307 track_parent!(self, self.alloc_expr(Expr::TryBlock { body }, syntax_ptr), body) 220 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
308 } 221 }
309 ast::Effect::Unsafe(_) => { 222 ast::Effect::Unsafe(_) => {
310 let body = self.collect_block_opt(e.block_expr()); 223 let body = self.collect_block_opt(e.block_expr());
311 track_parent!(self, self.alloc_expr(Expr::Unsafe { body }, syntax_ptr), body) 224 self.alloc_expr(Expr::Unsafe { body }, syntax_ptr)
312 } 225 }
313 // FIXME: we need to record these effects somewhere... 226 // FIXME: we need to record these effects somewhere...
314 ast::Effect::Async(_) | ast::Effect::Label(_) => { 227 ast::Effect::Async(_) | ast::Effect::Label(_) => {
@@ -318,19 +231,15 @@ impl ExprCollector<'_> {
318 ast::Expr::BlockExpr(e) => self.collect_block(e), 231 ast::Expr::BlockExpr(e) => self.collect_block(e),
319 ast::Expr::LoopExpr(e) => { 232 ast::Expr::LoopExpr(e) => {
320 let body = self.collect_block_opt(e.loop_body()); 233 let body = self.collect_block_opt(e.loop_body());
321 track_parent!( 234 self.alloc_expr(
322 self, 235 Expr::Loop {
323 self.alloc_expr( 236 body,
324 Expr::Loop { 237 label: e
325 body, 238 .label()
326 label: e 239 .and_then(|l| l.lifetime_token())
327 .label() 240 .map(|l| Name::new_lifetime(&l)),
328 .and_then(|l| l.lifetime_token()) 241 },
329 .map(|l| Name::new_lifetime(&l)), 242 syntax_ptr,
330 },
331 syntax_ptr,
332 ),
333 body
334 ) 243 )
335 } 244 }
336 ast::Expr::WhileExpr(e) => { 245 ast::Expr::WhileExpr(e) => {
@@ -354,61 +263,47 @@ impl ExprCollector<'_> {
354 ]; 263 ];
355 let match_expr = 264 let match_expr =
356 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); 265 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
357 return track_parent!( 266 return self.alloc_expr(
358 self, 267 Expr::Loop {
359 self.alloc_expr( 268 body: match_expr,
360 Expr::Loop { 269 label: e
361 body: match_expr, 270 .label()
362 label: e 271 .and_then(|l| l.lifetime_token())
363 .label() 272 .map(|l| Name::new_lifetime(&l)),
364 .and_then(|l| l.lifetime_token()) 273 },
365 .map(|l| Name::new_lifetime(&l)), 274 syntax_ptr,
366 },
367 syntax_ptr,
368 ),
369 match_expr
370 ); 275 );
371 } 276 }
372 }, 277 },
373 }; 278 };
374 279
375 track_parent!( 280 self.alloc_expr(
376 self, 281 Expr::While {
377 self.alloc_expr( 282 condition,
378 Expr::While { 283 body,
379 condition, 284 label: e
380 body, 285 .label()
381 label: e 286 .and_then(|l| l.lifetime_token())
382 .label() 287 .map(|l| Name::new_lifetime(&l)),
383 .and_then(|l| l.lifetime_token()) 288 },
384 .map(|l| Name::new_lifetime(&l)), 289 syntax_ptr,
385 },
386 syntax_ptr,
387 ),
388 body,
389 condition
390 ) 290 )
391 } 291 }
392 ast::Expr::ForExpr(e) => { 292 ast::Expr::ForExpr(e) => {
393 let iterable = self.collect_expr_opt(e.iterable()); 293 let iterable = self.collect_expr_opt(e.iterable());
394 let pat = self.collect_pat_opt(e.pat()); 294 let pat = self.collect_pat_opt(e.pat());
395 let body = self.collect_block_opt(e.loop_body()); 295 let body = self.collect_block_opt(e.loop_body());
396 track_parent!( 296 self.alloc_expr(
397 self, 297 Expr::For {
398 self.alloc_expr( 298 iterable,
399 Expr::For { 299 pat,
400 iterable, 300 body,
401 pat, 301 label: e
402 body, 302 .label()
403 label: e 303 .and_then(|l| l.lifetime_token())
404 .label() 304 .map(|l| Name::new_lifetime(&l)),
405 .and_then(|l| l.lifetime_token()) 305 },
406 .map(|l| Name::new_lifetime(&l)), 306 syntax_ptr,
407 },
408 syntax_ptr,
409 ),
410 iterable,
411 body
412 ) 307 )
413 } 308 }
414 ast::Expr::CallExpr(e) => { 309 ast::Expr::CallExpr(e) => {
@@ -418,7 +313,7 @@ impl ExprCollector<'_> {
418 } else { 313 } else {
419 Vec::new() 314 Vec::new()
420 }; 315 };
421 track_parent!(self, self.alloc_expr(Expr::Call { callee, args: args.clone() }, syntax_ptr), callee, vec args) 316 self.alloc_expr(Expr::Call { callee, args: args.clone() }, syntax_ptr)
422 } 317 }
423 ast::Expr::MethodCallExpr(e) => { 318 ast::Expr::MethodCallExpr(e) => {
424 let receiver = self.collect_expr_opt(e.expr()); 319 let receiver = self.collect_expr_opt(e.expr());
@@ -430,46 +325,29 @@ impl ExprCollector<'_> {
430 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 325 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
431 let generic_args = 326 let generic_args =
432 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); 327 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
433 track_parent!( 328 self.alloc_expr(
434 self, 329 Expr::MethodCall { receiver, method_name, args: args.clone(), generic_args },
435 self.alloc_expr( 330 syntax_ptr,
436 Expr::MethodCall {
437 receiver,
438 method_name,
439 args: args.clone(),
440 generic_args
441 },
442 syntax_ptr,
443 ),
444 receiver,
445 vec args
446 ) 331 )
447 } 332 }
448 ast::Expr::MatchExpr(e) => { 333 ast::Expr::MatchExpr(e) => {
449 let expr = self.collect_expr_opt(e.expr()); 334 let expr = self.collect_expr_opt(e.expr());
450 let (arms, children_exprs): (Vec<_>, Vec<_>) = 335 let arms = if let Some(match_arm_list) = e.match_arm_list() {
451 if let Some(match_arm_list) = e.match_arm_list() { 336 match_arm_list
452 match_arm_list 337 .arms()
453 .arms() 338 .map(|arm| MatchArm {
454 .map(|arm| { 339 pat: self.collect_pat_opt(arm.pat()),
455 let expr = self.collect_expr_opt(arm.expr()); 340 expr: self.collect_expr_opt(arm.expr()),
456 ( 341 guard: arm
457 MatchArm { 342 .guard()
458 pat: self.collect_pat_opt(arm.pat()), 343 .and_then(|guard| guard.expr())
459 expr, 344 .map(|e| self.collect_expr(e)),
460 guard: arm 345 })
461 .guard() 346 .collect()
462 .and_then(|guard| guard.expr()) 347 } else {
463 .map(|e| self.collect_expr(e)), 348 vec![]
464 }, 349 };
465 expr, 350 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
466 )
467 })
468 .unzip()
469 } else {
470 (vec![], vec![])
471 };
472 track_parent!(self, self.alloc_expr(Expr::Match { expr, arms: arms.clone() }, syntax_ptr), expr, vec children_exprs)
473 } 351 }
474 ast::Expr::PathExpr(e) => { 352 ast::Expr::PathExpr(e) => {
475 let path = e 353 let path = e
@@ -485,10 +363,10 @@ impl ExprCollector<'_> {
485 ), 363 ),
486 ast::Expr::BreakExpr(e) => { 364 ast::Expr::BreakExpr(e) => {
487 let expr = e.expr().map(|e| self.collect_expr(e)); 365 let expr = e.expr().map(|e| self.collect_expr(e));
488 track_parent!(self, self.alloc_expr( 366 self.alloc_expr(
489 Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, 367 Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
490 syntax_ptr, 368 syntax_ptr,
491 ), opt expr) 369 )
492 } 370 }
493 ast::Expr::ParenExpr(e) => { 371 ast::Expr::ParenExpr(e) => {
494 let inner = self.collect_expr_opt(e.expr()); 372 let inner = self.collect_expr_opt(e.expr());
@@ -499,13 +377,13 @@ impl ExprCollector<'_> {
499 } 377 }
500 ast::Expr::ReturnExpr(e) => { 378 ast::Expr::ReturnExpr(e) => {
501 let expr = e.expr().map(|e| self.collect_expr(e)); 379 let expr = e.expr().map(|e| self.collect_expr(e));
502 track_parent!(self, self.alloc_expr(Expr::Return { expr }, syntax_ptr), opt expr) 380 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
503 } 381 }
504 ast::Expr::RecordLit(e) => { 382 ast::Expr::RecordLit(e) => {
505 let path = e.path().and_then(|path| self.expander.parse_path(path)); 383 let path = e.path().and_then(|path| self.expander.parse_path(path));
506 let mut field_ptrs = Vec::new(); 384 let mut field_ptrs = Vec::new();
507 let (record_lit, children) = if let Some(nfl) = e.record_field_list() { 385 let record_lit = if let Some(nfl) = e.record_field_list() {
508 let (fields, children): (Vec<_>, Vec<_>) = nfl 386 let fields = nfl
509 .fields() 387 .fields()
510 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 388 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
511 .filter_map(|field| { 389 .filter_map(|field| {
@@ -518,16 +396,13 @@ impl ExprCollector<'_> {
518 Some(e) => self.collect_expr(e), 396 Some(e) => self.collect_expr(e),
519 None => self.missing_expr(), 397 None => self.missing_expr(),
520 }; 398 };
521 Some((RecordLitField { name, expr }, expr)) 399 Some(RecordLitField { name, expr })
522 }) 400 })
523 .unzip(); 401 .collect();
524 let spread = nfl.spread().map(|s| self.collect_expr(s)); 402 let spread = nfl.spread().map(|s| self.collect_expr(s));
525 ( 403 Expr::RecordLit { path, fields, spread: spread }
526 Expr::RecordLit { path, fields, spread: spread },
527 children.into_iter().chain(spread.into_iter()).collect(),
528 )
529 } else { 404 } else {
530 (Expr::RecordLit { path, fields: Vec::new(), spread: None }, vec![]) 405 Expr::RecordLit { path, fields: Vec::new(), spread: None }
531 }; 406 };
532 407
533 let res = self.alloc_expr(record_lit, syntax_ptr); 408 let res = self.alloc_expr(record_lit, syntax_ptr);
@@ -535,7 +410,7 @@ impl ExprCollector<'_> {
535 let src = self.expander.to_source(ptr); 410 let src = self.expander.to_source(ptr);
536 self.source_map.field_map.insert((res, i), src); 411 self.source_map.field_map.insert((res, i), src);
537 } 412 }
538 track_parent!(self, res, vec children) 413 res
539 } 414 }
540 ast::Expr::FieldExpr(e) => { 415 ast::Expr::FieldExpr(e) => {
541 let expr = self.collect_expr_opt(e.expr()); 416 let expr = self.collect_expr_opt(e.expr());
@@ -543,24 +418,20 @@ impl ExprCollector<'_> {
543 Some(kind) => kind.as_name(), 418 Some(kind) => kind.as_name(),
544 _ => Name::missing(), 419 _ => Name::missing(),
545 }; 420 };
546 track_parent!(self, self.alloc_expr(Expr::Field { expr, name }, syntax_ptr), expr) 421 self.alloc_expr(Expr::Field { expr, name }, syntax_ptr)
547 } 422 }
548 ast::Expr::AwaitExpr(e) => { 423 ast::Expr::AwaitExpr(e) => {
549 let expr = self.collect_expr_opt(e.expr()); 424 let expr = self.collect_expr_opt(e.expr());
550 track_parent!(self, self.alloc_expr(Expr::Await { expr }, syntax_ptr), expr) 425 self.alloc_expr(Expr::Await { expr }, syntax_ptr)
551 } 426 }
552 ast::Expr::TryExpr(e) => { 427 ast::Expr::TryExpr(e) => {
553 let expr = self.collect_expr_opt(e.expr()); 428 let expr = self.collect_expr_opt(e.expr());
554 track_parent!(self, self.alloc_expr(Expr::Try { expr }, syntax_ptr), expr) 429 self.alloc_expr(Expr::Try { expr }, syntax_ptr)
555 } 430 }
556 ast::Expr::CastExpr(e) => { 431 ast::Expr::CastExpr(e) => {
557 let expr = self.collect_expr_opt(e.expr()); 432 let expr = self.collect_expr_opt(e.expr());
558 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref()); 433 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref());
559 track_parent!( 434 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
560 self,
561 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr),
562 expr
563 )
564 } 435 }
565 ast::Expr::RefExpr(e) => { 436 ast::Expr::RefExpr(e) => {
566 let expr = self.collect_expr_opt(e.expr()); 437 let expr = self.collect_expr_opt(e.expr());
@@ -577,20 +448,12 @@ impl ExprCollector<'_> {
577 Mutability::from_mutable(e.mut_token().is_some()) 448 Mutability::from_mutable(e.mut_token().is_some())
578 }; 449 };
579 let rawness = Rawness::from_raw(raw_tok); 450 let rawness = Rawness::from_raw(raw_tok);
580 track_parent!( 451 self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr)
581 self,
582 self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr),
583 expr
584 )
585 } 452 }
586 ast::Expr::PrefixExpr(e) => { 453 ast::Expr::PrefixExpr(e) => {
587 let expr = self.collect_expr_opt(e.expr()); 454 let expr = self.collect_expr_opt(e.expr());
588 if let Some(op) = e.op_kind() { 455 if let Some(op) = e.op_kind() {
589 track_parent!( 456 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
590 self,
591 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr),
592 expr
593 )
594 } else { 457 } else {
595 self.alloc_expr(Expr::Missing, syntax_ptr) 458 self.alloc_expr(Expr::Missing, syntax_ptr)
596 } 459 }
@@ -612,30 +475,21 @@ impl ExprCollector<'_> {
612 .and_then(|r| r.type_ref()) 475 .and_then(|r| r.type_ref())
613 .map(|it| TypeRef::from_ast(&self.ctx(), it)); 476 .map(|it| TypeRef::from_ast(&self.ctx(), it));
614 let body = self.collect_expr_opt(e.body()); 477 let body = self.collect_expr_opt(e.body());
615 track_parent!( 478 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
616 self,
617 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr),
618 body,
619 )
620 } 479 }
621 ast::Expr::BinExpr(e) => { 480 ast::Expr::BinExpr(e) => {
622 let lhs = self.collect_expr_opt(e.lhs()); 481 let lhs = self.collect_expr_opt(e.lhs());
623 let rhs = self.collect_expr_opt(e.rhs()); 482 let rhs = self.collect_expr_opt(e.rhs());
624 let op = e.op_kind().map(BinaryOp::from); 483 let op = e.op_kind().map(BinaryOp::from);
625 track_parent!( 484 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
626 self,
627 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr),
628 lhs,
629 rhs
630 )
631 } 485 }
632 ast::Expr::TupleExpr(e) => { 486 ast::Expr::TupleExpr(e) => {
633 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect::<Vec<_>>(); 487 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect::<Vec<_>>();
634 track_parent!(self, self.alloc_expr(Expr::Tuple { exprs: exprs.clone() }, syntax_ptr), vec exprs) 488 self.alloc_expr(Expr::Tuple { exprs: exprs.clone() }, syntax_ptr)
635 } 489 }
636 ast::Expr::BoxExpr(e) => { 490 ast::Expr::BoxExpr(e) => {
637 let expr = self.collect_expr_opt(e.expr()); 491 let expr = self.collect_expr_opt(e.expr());
638 track_parent!(self, self.alloc_expr(Expr::Box { expr }, syntax_ptr), expr) 492 self.alloc_expr(Expr::Box { expr }, syntax_ptr)
639 } 493 }
640 494
641 ast::Expr::ArrayExpr(e) => { 495 ast::Expr::ArrayExpr(e) => {
@@ -644,25 +498,14 @@ impl ExprCollector<'_> {
644 match kind { 498 match kind {
645 ArrayExprKind::ElementList(e) => { 499 ArrayExprKind::ElementList(e) => {
646 let exprs = e.map(|expr| self.collect_expr(expr)).collect::<Vec<_>>(); 500 let exprs = e.map(|expr| self.collect_expr(expr)).collect::<Vec<_>>();
647 track_parent!(self, 501 self.alloc_expr(Expr::Array(Array::ElementList(exprs.clone())), syntax_ptr)
648 self.alloc_expr(
649 Expr::Array(Array::ElementList(exprs.clone())),
650 syntax_ptr,
651 ),
652 vec exprs,
653 )
654 } 502 }
655 ArrayExprKind::Repeat { initializer, repeat } => { 503 ArrayExprKind::Repeat { initializer, repeat } => {
656 let initializer = self.collect_expr_opt(initializer); 504 let initializer = self.collect_expr_opt(initializer);
657 let repeat = self.collect_expr_opt(repeat); 505 let repeat = self.collect_expr_opt(repeat);
658 track_parent!( 506 self.alloc_expr(
659 self, 507 Expr::Array(Array::Repeat { initializer, repeat }),
660 self.alloc_expr( 508 syntax_ptr,
661 Expr::Array(Array::Repeat { initializer, repeat }),
662 syntax_ptr,
663 ),
664 initializer,
665 repeat,
666 ) 509 )
667 } 510 }
668 } 511 }
@@ -672,22 +515,15 @@ impl ExprCollector<'_> {
672 ast::Expr::IndexExpr(e) => { 515 ast::Expr::IndexExpr(e) => {
673 let base = self.collect_expr_opt(e.base()); 516 let base = self.collect_expr_opt(e.base());
674 let index = self.collect_expr_opt(e.index()); 517 let index = self.collect_expr_opt(e.index());
675 track_parent!( 518 self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
676 self,
677 self.alloc_expr(Expr::Index { base, index }, syntax_ptr),
678 base,
679 index
680 )
681 } 519 }
682 ast::Expr::RangeExpr(e) => { 520 ast::Expr::RangeExpr(e) => {
683 let lhs = e.start().map(|lhs| self.collect_expr(lhs)); 521 let lhs = e.start().map(|lhs| self.collect_expr(lhs));
684 let rhs = e.end().map(|rhs| self.collect_expr(rhs)); 522 let rhs = e.end().map(|rhs| self.collect_expr(rhs));
685 match e.op_kind() { 523 match e.op_kind() {
686 Some(range_type) => track_parent!( 524 Some(range_type) => {
687 self, 525 self.alloc_expr(Expr::Range { lhs, rhs, range_type }, syntax_ptr)
688 self.alloc_expr(Expr::Range { lhs, rhs, range_type }, syntax_ptr), 526 }
689 opt lhs, opt rhs
690 ),
691 None => self.alloc_expr(Expr::Missing, syntax_ptr), 527 None => self.alloc_expr(Expr::Missing, syntax_ptr),
692 } 528 }
693 } 529 }
@@ -762,14 +598,9 @@ impl ExprCollector<'_> {
762 } 598 }
763 599
764 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { 600 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
765 let parent_and_children = self.collect_block_inner(block);
766 self.update_parent_map(parent_and_children)
767 }
768
769 fn collect_block_inner(&mut self, block: ast::BlockExpr) -> (ExprId, Vec<ExprId>) {
770 let syntax_node_ptr = AstPtr::new(&block.clone().into()); 601 let syntax_node_ptr = AstPtr::new(&block.clone().into());
771 self.collect_block_items(&block); 602 self.collect_block_items(&block);
772 let (statements, children_exprs): (Vec<_>, Vec<_>) = block 603 let statements = block
773 .statements() 604 .statements()
774 .map(|s| match s { 605 .map(|s| match s {
775 ast::Stmt::LetStmt(stmt) => { 606 ast::Stmt::LetStmt(stmt) => {
@@ -777,18 +608,14 @@ impl ExprCollector<'_> {
777 let type_ref = 608 let type_ref =
778 stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it)); 609 stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
779 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 610 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
780 (Statement::Let { pat, type_ref, initializer }, initializer) 611 Statement::Let { pat, type_ref, initializer }
781 }
782 ast::Stmt::ExprStmt(stmt) => {
783 let expr = self.collect_expr_opt(stmt.expr());
784 (Statement::Expr(expr), Some(expr))
785 } 612 }
613 ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())),
786 }) 614 })
787 .unzip(); 615 .collect();
788 let tail = block.expr().map(|e| self.collect_expr(e)); 616 let tail = block.expr().map(|e| self.collect_expr(e));
789 let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t)); 617 let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t));
790 let children_exprs = children_exprs.into_iter().flatten().chain(tail.into_iter()).collect(); 618 self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr)
791 (self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr), children_exprs)
792 } 619 }
793 620
794 fn collect_block_items(&mut self, block: &ast::BlockExpr) { 621 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
diff --git a/crates/ra_hir_ty/src/unsafe_validation.rs b/crates/ra_hir_ty/src/unsafe_validation.rs
index 430182803..f3ce7112a 100644
--- a/crates/ra_hir_ty/src/unsafe_validation.rs
+++ b/crates/ra_hir_ty/src/unsafe_validation.rs
@@ -13,16 +13,9 @@ use crate::{
13 13
14use rustc_hash::FxHashSet; 14use rustc_hash::FxHashSet;
15 15
16pub use hir_def::{ 16use hir_def::{
17 body::{ 17 body::Body,
18 scope::{ExprScopes, ScopeEntry, ScopeId}, 18 expr::{Expr, ExprId, UnaryOp},
19 Body, BodySourceMap, ExprPtr, ExprSource, PatPtr, PatSource,
20 },
21 expr::{
22 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
23 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp,
24 },
25 LocalFieldId, VariantId,
26}; 19};
27 20
28pub struct UnsafeValidator<'a, 'b: 'a> { 21pub struct UnsafeValidator<'a, 'b: 'a> {
@@ -119,16 +112,27 @@ pub fn unsafe_expressions(
119 } 112 }
120 } 113 }
121 114
122 'unsafe_exprs: for unsafe_expr in &mut unsafe_exprs { 115 for unsafe_expr in &mut unsafe_exprs {
123 let mut child = unsafe_expr.expr; 116 unsafe_expr.inside_unsafe_block =
124 while let Some(parent) = body.parent_map.get(child) { 117 is_in_unsafe(&body, body.body_expr, unsafe_expr.expr, false);
125 if unsafe_block_exprs.contains(parent) {
126 unsafe_expr.inside_unsafe_block = true;
127 continue 'unsafe_exprs;
128 }
129 child = *parent;
130 }
131 } 118 }
132 119
133 unsafe_exprs 120 unsafe_exprs
134} 121}
122
123fn is_in_unsafe(body: &Body, current: ExprId, needle: ExprId, within_unsafe: bool) -> bool {
124 if current == needle {
125 return within_unsafe;
126 }
127
128 let expr = &body.exprs[current];
129 if let &Expr::Unsafe { body: child } = expr {
130 return is_in_unsafe(body, child, needle, true);
131 }
132
133 let mut found = false;
134 expr.walk_child_exprs(|child| {
135 found = found || is_in_unsafe(body, child, needle, within_unsafe);
136 });
137 found
138}