aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/unsafe_validation.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/unsafe_validation.rs')
-rw-r--r--crates/ra_hir_ty/src/unsafe_validation.rs63
1 files changed, 63 insertions, 0 deletions
diff --git a/crates/ra_hir_ty/src/unsafe_validation.rs b/crates/ra_hir_ty/src/unsafe_validation.rs
new file mode 100644
index 000000000..55dbe23fa
--- /dev/null
+++ b/crates/ra_hir_ty/src/unsafe_validation.rs
@@ -0,0 +1,63 @@
1//! Provides validations for unsafe code. Currently checks if unsafe functions are missing
2//! unsafe blocks.
3
4use std::sync::Arc;
5
6use hir_def::FunctionId;
7use hir_expand::diagnostics::DiagnosticSink;
8
9use crate::{
10 db::HirDatabase, diagnostics::MissingUnsafe, expr::unsafe_expressions, InferenceResult,
11};
12
13pub use hir_def::{
14 body::{
15 scope::{ExprScopes, ScopeEntry, ScopeId},
16 Body, BodySourceMap, ExprPtr, ExprSource, PatPtr, PatSource,
17 },
18 expr::{
19 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
20 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp,
21 },
22 LocalFieldId, VariantId,
23};
24
25pub struct UnsafeValidator<'a, 'b: 'a> {
26 func: FunctionId,
27 infer: Arc<InferenceResult>,
28 sink: &'a mut DiagnosticSink<'b>,
29}
30
31impl<'a, 'b> UnsafeValidator<'a, 'b> {
32 pub fn new(
33 func: FunctionId,
34 infer: Arc<InferenceResult>,
35 sink: &'a mut DiagnosticSink<'b>,
36 ) -> UnsafeValidator<'a, 'b> {
37 UnsafeValidator { func, infer, sink }
38 }
39
40 pub fn validate_body(&mut self, db: &dyn HirDatabase) {
41 let def = self.func.into();
42 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
43 let func_data = db.function_data(self.func);
44 if func_data.is_unsafe
45 || unsafe_expressions
46 .iter()
47 .filter(|unsafe_expr| !unsafe_expr.inside_unsafe_block)
48 .count()
49 == 0
50 {
51 return;
52 }
53
54 let (_, body_source) = db.body_with_source_map(def);
55 for unsafe_expr in unsafe_expressions {
56 if !unsafe_expr.inside_unsafe_block {
57 if let Ok(in_file) = body_source.as_ref().expr_syntax(unsafe_expr.expr) {
58 self.sink.push(MissingUnsafe { file: in_file.file_id, expr: in_file.value })
59 }
60 }
61 }
62 }
63}