diff options
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 369 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/unsafe_validation.rs | 42 |
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 | ||
190 | pub type ExprPtr = AstPtr<ast::Expr>; | 189 | 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 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 | }; |
10 | use ra_arena::{map::ArenaMap, Arena}; | 10 | use ra_arena::Arena; |
11 | use ra_syntax::{ | 11 | use 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 | ||
99 | macro_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 | |||
133 | impl ExprCollector<'_> { | 98 | impl 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 | ||
14 | use rustc_hash::FxHashSet; | 14 | use rustc_hash::FxHashSet; |
15 | 15 | ||
16 | pub use hir_def::{ | 16 | use 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 | ||
28 | pub struct UnsafeValidator<'a, 'b: 'a> { | 21 | pub 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 | |||
123 | fn 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 | } | ||