Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir_ty/src/diagnostics/unsafe_check.rs')
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs50
1 files changed, 27 insertions, 23 deletions
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index 2a18df253e..b0fc49fc61 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -12,54 +12,58 @@ use crate::{db::HirDatabase, InferenceResult, Interner, TyExt, TyKind};
pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> Vec<ExprId> {
let infer = db.infer(def);
+ let mut res = Vec::new();
let is_unsafe = match def {
DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe(),
DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
};
if is_unsafe {
- return Vec::new();
+ return res;
}
- unsafe_expressions(db, &infer, def)
- .into_iter()
- .filter(|it| !it.inside_unsafe_block)
- .map(|it| it.expr)
- .collect()
+ let body = db.body(def);
+ unsafe_expressions(db, &infer, def, &body, body.body_expr, &mut |expr| {
+ if !expr.inside_unsafe_block {
+ res.push(expr.expr);
+ }
+ });
+
+ res
}
-struct UnsafeExpr {
- pub(crate) expr: ExprId,
- pub(crate) inside_unsafe_block: bool,
+pub struct UnsafeExpr {
+ pub expr: ExprId,
+ pub inside_unsafe_block: bool,
}
-fn unsafe_expressions(
+// FIXME: Move this out, its not a diagnostic only thing anymore, and handle unsafe pattern accesses as well
+pub fn unsafe_expressions(
db: &dyn HirDatabase,
infer: &InferenceResult,
def: DefWithBodyId,
-) -> Vec<UnsafeExpr> {
- let mut unsafe_exprs = vec![];
- let body = db.body(def);
- walk_unsafe(&mut unsafe_exprs, db, infer, def, &body, body.body_expr, false);
-
- unsafe_exprs
+ body: &Body,
+ current: ExprId,
+ unsafe_expr_cb: &mut dyn FnMut(UnsafeExpr),
+) {
+ walk_unsafe(db, infer, def, body, current, false, unsafe_expr_cb)
}
fn walk_unsafe(
- unsafe_exprs: &mut Vec<UnsafeExpr>,
db: &dyn HirDatabase,
infer: &InferenceResult,
def: DefWithBodyId,
body: &Body,
current: ExprId,
inside_unsafe_block: bool,
+ unsafe_expr_cb: &mut dyn FnMut(UnsafeExpr),
) {
let expr = &body.exprs[current];
match expr {
&Expr::Call { callee, .. } => {
if let Some(func) = infer[callee].as_fn_def(db) {
if db.function_data(func).is_unsafe() {
- unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
+ unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
}
}
}
@@ -68,7 +72,7 @@ fn walk_unsafe(
let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path.mod_path());
if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id))) = value_or_partial {
if db.static_data(id).mutable {
- unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
+ unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
}
}
}
@@ -78,21 +82,21 @@ fn walk_unsafe(
.map(|(func, _)| db.function_data(func).is_unsafe())
.unwrap_or(false)
{
- unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
+ unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
}
}
Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
if let TyKind::Raw(..) = &infer[*expr].kind(Interner) {
- unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
+ unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
}
}
Expr::Unsafe { body: child } => {
- return walk_unsafe(unsafe_exprs, db, infer, def, body, *child, true);
+ return walk_unsafe(db, infer, def, body, *child, true, unsafe_expr_cb);
}
_ => {}
}
expr.walk_child_exprs(|child| {
- walk_unsafe(unsafe_exprs, db, infer, def, body, child, inside_unsafe_block);
+ walk_unsafe(db, infer, def, body, child, inside_unsafe_block, unsafe_expr_cb);
});
}