diff options
author | Paul Daniel Faria <[email protected]> | 2020-05-29 13:55:47 +0100 |
---|---|---|
committer | Paul Daniel Faria <[email protected]> | 2020-06-27 15:13:14 +0100 |
commit | 2608a6fd3a024206d4776cc391e46ef28c018434 (patch) | |
tree | 55ab44a0a8c6574b8a27c24863a0badbee063d44 /crates/ra_hir_ty | |
parent | f678e0d837e472dc2f1421f89f794d33f3ade55c (diff) |
unsafe: Clean up, improve tracking, add debug_assert
Move unsafe_expressions to unsafe_validation.rs, replace vec tracking of
child exprs with inline macro, add debug assert to ensure tracked
children match walked children exactly
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/expr.rs | 71 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/unsafe_validation.rs | 75 |
2 files changed, 74 insertions, 72 deletions
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs index 99eed949f..7db928dde 100644 --- a/crates/ra_hir_ty/src/expr.rs +++ b/crates/ra_hir_ty/src/expr.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::{path::path, resolver::HasResolver, AdtId, DefWithBodyId, FunctionId}; | 5 | use hir_def::{path::path, resolver::HasResolver, AdtId, FunctionId}; |
6 | use hir_expand::diagnostics::DiagnosticSink; | 6 | use hir_expand::diagnostics::DiagnosticSink; |
7 | use ra_syntax::{ast, AstPtr}; | 7 | use ra_syntax::{ast, AstPtr}; |
8 | use rustc_hash::FxHashSet; | 8 | use rustc_hash::FxHashSet; |
@@ -10,7 +10,6 @@ use rustc_hash::FxHashSet; | |||
10 | use crate::{ | 10 | use crate::{ |
11 | db::HirDatabase, | 11 | db::HirDatabase, |
12 | diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields}, | 12 | diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields}, |
13 | lower::CallableDef, | ||
14 | utils::variant_data, | 13 | utils::variant_data, |
15 | ApplicationTy, InferenceResult, Ty, TypeCtor, | 14 | ApplicationTy, InferenceResult, Ty, TypeCtor, |
16 | _match::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, | 15 | _match::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, |
@@ -313,71 +312,3 @@ pub fn record_pattern_missing_fields( | |||
313 | } | 312 | } |
314 | Some((variant_def, missed_fields, exhaustive)) | 313 | Some((variant_def, missed_fields, exhaustive)) |
315 | } | 314 | } |
316 | |||
317 | pub struct UnsafeExpr { | ||
318 | pub expr: ExprId, | ||
319 | pub inside_unsafe_block: bool, | ||
320 | } | ||
321 | |||
322 | impl UnsafeExpr { | ||
323 | fn new(expr: ExprId) -> Self { | ||
324 | Self { expr, inside_unsafe_block: false } | ||
325 | } | ||
326 | } | ||
327 | |||
328 | pub fn unsafe_expressions( | ||
329 | db: &dyn HirDatabase, | ||
330 | infer: &InferenceResult, | ||
331 | def: DefWithBodyId, | ||
332 | ) -> Vec<UnsafeExpr> { | ||
333 | let mut unsafe_exprs = vec![]; | ||
334 | let mut unsafe_block_exprs = FxHashSet::default(); | ||
335 | let body = db.body(def); | ||
336 | for (id, expr) in body.exprs.iter() { | ||
337 | match expr { | ||
338 | Expr::Unsafe { .. } => { | ||
339 | unsafe_block_exprs.insert(id); | ||
340 | } | ||
341 | Expr::Call { callee, .. } => { | ||
342 | let ty = &infer[*callee]; | ||
343 | if let &Ty::Apply(ApplicationTy { | ||
344 | ctor: TypeCtor::FnDef(CallableDef::FunctionId(func)), | ||
345 | .. | ||
346 | }) = ty | ||
347 | { | ||
348 | if db.function_data(func).is_unsafe { | ||
349 | unsafe_exprs.push(UnsafeExpr::new(id)); | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | Expr::MethodCall { .. } => { | ||
354 | if infer | ||
355 | .method_resolution(id) | ||
356 | .map(|func| db.function_data(func).is_unsafe) | ||
357 | .unwrap_or(false) | ||
358 | { | ||
359 | unsafe_exprs.push(UnsafeExpr::new(id)); | ||
360 | } | ||
361 | } | ||
362 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { | ||
363 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }) = &infer[*expr] { | ||
364 | unsafe_exprs.push(UnsafeExpr::new(id)); | ||
365 | } | ||
366 | } | ||
367 | _ => {} | ||
368 | } | ||
369 | } | ||
370 | |||
371 | 'unsafe_exprs: for unsafe_expr in &mut unsafe_exprs { | ||
372 | let mut child = unsafe_expr.expr; | ||
373 | while let Some(parent) = body.parent_map.get(&child) { | ||
374 | if unsafe_block_exprs.contains(parent) { | ||
375 | unsafe_expr.inside_unsafe_block = true; | ||
376 | continue 'unsafe_exprs; | ||
377 | } | ||
378 | child = *parent; | ||
379 | } | ||
380 | } | ||
381 | |||
382 | unsafe_exprs | ||
383 | } | ||
diff --git a/crates/ra_hir_ty/src/unsafe_validation.rs b/crates/ra_hir_ty/src/unsafe_validation.rs index 55dbe23fa..430182803 100644 --- a/crates/ra_hir_ty/src/unsafe_validation.rs +++ b/crates/ra_hir_ty/src/unsafe_validation.rs | |||
@@ -3,13 +3,16 @@ | |||
3 | 3 | ||
4 | use std::sync::Arc; | 4 | use std::sync::Arc; |
5 | 5 | ||
6 | use hir_def::FunctionId; | 6 | use hir_def::{DefWithBodyId, FunctionId}; |
7 | use hir_expand::diagnostics::DiagnosticSink; | 7 | use hir_expand::diagnostics::DiagnosticSink; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | db::HirDatabase, diagnostics::MissingUnsafe, expr::unsafe_expressions, InferenceResult, | 10 | db::HirDatabase, diagnostics::MissingUnsafe, lower::CallableDef, ApplicationTy, |
11 | InferenceResult, Ty, TypeCtor, | ||
11 | }; | 12 | }; |
12 | 13 | ||
14 | use rustc_hash::FxHashSet; | ||
15 | |||
13 | pub use hir_def::{ | 16 | pub use hir_def::{ |
14 | body::{ | 17 | body::{ |
15 | scope::{ExprScopes, ScopeEntry, ScopeId}, | 18 | scope::{ExprScopes, ScopeEntry, ScopeId}, |
@@ -61,3 +64,71 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> { | |||
61 | } | 64 | } |
62 | } | 65 | } |
63 | } | 66 | } |
67 | |||
68 | pub struct UnsafeExpr { | ||
69 | pub expr: ExprId, | ||
70 | pub inside_unsafe_block: bool, | ||
71 | } | ||
72 | |||
73 | impl UnsafeExpr { | ||
74 | fn new(expr: ExprId) -> Self { | ||
75 | Self { expr, inside_unsafe_block: false } | ||
76 | } | ||
77 | } | ||
78 | |||
79 | pub fn unsafe_expressions( | ||
80 | db: &dyn HirDatabase, | ||
81 | infer: &InferenceResult, | ||
82 | def: DefWithBodyId, | ||
83 | ) -> Vec<UnsafeExpr> { | ||
84 | let mut unsafe_exprs = vec![]; | ||
85 | let mut unsafe_block_exprs = FxHashSet::default(); | ||
86 | let body = db.body(def); | ||
87 | for (id, expr) in body.exprs.iter() { | ||
88 | match expr { | ||
89 | Expr::Unsafe { .. } => { | ||
90 | unsafe_block_exprs.insert(id); | ||
91 | } | ||
92 | Expr::Call { callee, .. } => { | ||
93 | let ty = &infer[*callee]; | ||
94 | if let &Ty::Apply(ApplicationTy { | ||
95 | ctor: TypeCtor::FnDef(CallableDef::FunctionId(func)), | ||
96 | .. | ||
97 | }) = ty | ||
98 | { | ||
99 | if db.function_data(func).is_unsafe { | ||
100 | unsafe_exprs.push(UnsafeExpr::new(id)); | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | Expr::MethodCall { .. } => { | ||
105 | if infer | ||
106 | .method_resolution(id) | ||
107 | .map(|func| db.function_data(func).is_unsafe) | ||
108 | .unwrap_or(false) | ||
109 | { | ||
110 | unsafe_exprs.push(UnsafeExpr::new(id)); | ||
111 | } | ||
112 | } | ||
113 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { | ||
114 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }) = &infer[*expr] { | ||
115 | unsafe_exprs.push(UnsafeExpr::new(id)); | ||
116 | } | ||
117 | } | ||
118 | _ => {} | ||
119 | } | ||
120 | } | ||
121 | |||
122 | 'unsafe_exprs: for unsafe_expr in &mut unsafe_exprs { | ||
123 | let mut child = unsafe_expr.expr; | ||
124 | while let Some(parent) = body.parent_map.get(child) { | ||
125 | if unsafe_block_exprs.contains(parent) { | ||
126 | unsafe_expr.inside_unsafe_block = true; | ||
127 | continue 'unsafe_exprs; | ||
128 | } | ||
129 | child = *parent; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | unsafe_exprs | ||
134 | } | ||