Use HIR unsafety information for unsafe syntax highlightng

This commit is contained in:
Lukas Wirth 2025-03-03 14:45:20 +01:00
parent 071eda7d91
commit 9fc0ffe008
37 changed files with 550 additions and 540 deletions

View file

@ -9,5 +9,8 @@ pub use crate::diagnostics::{
expr::{
record_literal_missing_fields, record_pattern_missing_fields, BodyValidationDiagnostic,
},
unsafe_check::{missing_unsafe, unsafe_expressions, InsideUnsafeBlock, UnsafetyReason},
unsafe_check::{
missing_unsafe, unsafe_operations, unsafe_operations_for_body, InsideUnsafeBlock,
UnsafetyReason,
},
};

View file

@ -95,7 +95,26 @@ enum UnsafeDiagnostic {
DeprecatedSafe2024 { node: ExprId, inside_unsafe_block: InsideUnsafeBlock },
}
pub fn unsafe_expressions(
pub fn unsafe_operations_for_body(
db: &dyn HirDatabase,
infer: &InferenceResult,
def: DefWithBodyId,
body: &Body,
callback: &mut dyn FnMut(ExprOrPatId),
) {
let mut visitor_callback = |diag| {
if let UnsafeDiagnostic::UnsafeOperation { node, .. } = diag {
callback(node);
}
};
let mut visitor = UnsafeVisitor::new(db, infer, body, def, &mut visitor_callback);
visitor.walk_expr(body.body_expr);
for &param in &body.params {
visitor.walk_pat(param);
}
}
pub fn unsafe_operations(
db: &dyn HirDatabase,
infer: &InferenceResult,
def: DefWithBodyId,
@ -281,13 +300,6 @@ impl<'a> UnsafeVisitor<'a> {
self.on_unsafe_op(current.into(), UnsafetyReason::RawPtrDeref);
}
}
Expr::Unsafe { .. } => {
let old_inside_unsafe_block =
mem::replace(&mut self.inside_unsafe_block, InsideUnsafeBlock::Yes);
self.body.walk_child_exprs_without_pats(current, |child| self.walk_expr(child));
self.inside_unsafe_block = old_inside_unsafe_block;
return;
}
&Expr::Assignment { target, value: _ } => {
let old_inside_assignment = mem::replace(&mut self.inside_assignment, true);
self.walk_pats_top(std::iter::once(target), current);
@ -306,6 +318,20 @@ impl<'a> UnsafeVisitor<'a> {
}
}
}
Expr::Unsafe { statements, .. } => {
let old_inside_unsafe_block =
mem::replace(&mut self.inside_unsafe_block, InsideUnsafeBlock::Yes);
self.walk_pats_top(
statements.iter().filter_map(|statement| match statement {
&Statement::Let { pat, .. } => Some(pat),
_ => None,
}),
current,
);
self.body.walk_child_exprs_without_pats(current, |child| self.walk_expr(child));
self.inside_unsafe_block = old_inside_unsafe_block;
return;
}
Expr::Block { statements, .. } | Expr::Async { statements, .. } => {
self.walk_pats_top(
statements.iter().filter_map(|statement| match statement {