aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src
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
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')
-rw-r--r--crates/ra_hir_ty/src/expr.rs71
-rw-r--r--crates/ra_hir_ty/src/unsafe_validation.rs75
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
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{path::path, resolver::HasResolver, AdtId, DefWithBodyId, FunctionId}; 5use hir_def::{path::path, resolver::HasResolver, AdtId, FunctionId};
6use hir_expand::diagnostics::DiagnosticSink; 6use hir_expand::diagnostics::DiagnosticSink;
7use ra_syntax::{ast, AstPtr}; 7use ra_syntax::{ast, AstPtr};
8use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
@@ -10,7 +10,6 @@ use rustc_hash::FxHashSet;
10use crate::{ 10use 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
317pub struct UnsafeExpr {
318 pub expr: ExprId,
319 pub inside_unsafe_block: bool,
320}
321
322impl UnsafeExpr {
323 fn new(expr: ExprId) -> Self {
324 Self { expr, inside_unsafe_block: false }
325 }
326}
327
328pub 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
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}