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.rs | 50 |
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); }); } |