aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/unsafe_validation.rs
diff options
context:
space:
mode:
authorPaul Daniel Faria <[email protected]>2020-05-29 13:55:47 +0100
committerPaul Daniel Faria <[email protected]>2020-06-27 15:13:14 +0100
commit2608a6fd3a024206d4776cc391e46ef28c018434 (patch)
tree55ab44a0a8c6574b8a27c24863a0badbee063d44 /crates/ra_hir_ty/src/unsafe_validation.rs
parentf678e0d837e472dc2f1421f89f794d33f3ade55c (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/src/unsafe_validation.rs')
-rw-r--r--crates/ra_hir_ty/src/unsafe_validation.rs75
1 files changed, 73 insertions, 2 deletions
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
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use hir_def::FunctionId; 6use hir_def::{DefWithBodyId, FunctionId};
7use hir_expand::diagnostics::DiagnosticSink; 7use hir_expand::diagnostics::DiagnosticSink;
8 8
9use crate::{ 9use 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
14use rustc_hash::FxHashSet;
15
13pub use hir_def::{ 16pub 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
68pub struct UnsafeExpr {
69 pub expr: ExprId,
70 pub inside_unsafe_block: bool,
71}
72
73impl UnsafeExpr {
74 fn new(expr: ExprId) -> Self {
75 Self { expr, inside_unsafe_block: false }
76 }
77}
78
79pub 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}