mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 04:23:25 +00:00
Merge #5679
5679: Account for static mut in missing unsafe diagnostic r=jonas-schievink a=Nashenas88 Accessing or modifying a static mut is an unsafe operation. The "missing unsafe" diagnostic now tracks this. Co-authored-by: Paul Daniel Faria <Nashenas88@users.noreply.github.com>
This commit is contained in:
commit
7a02cc8845
1 changed files with 35 additions and 3 deletions
|
@ -6,6 +6,7 @@ use std::sync::Arc;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
body::Body,
|
body::Body,
|
||||||
expr::{Expr, ExprId, UnaryOp},
|
expr::{Expr, ExprId, UnaryOp},
|
||||||
|
resolver::{resolver_for_expr, ResolveValueResult, ValueNs},
|
||||||
DefWithBodyId,
|
DefWithBodyId,
|
||||||
};
|
};
|
||||||
use hir_expand::diagnostics::DiagnosticSink;
|
use hir_expand::diagnostics::DiagnosticSink;
|
||||||
|
@ -70,7 +71,7 @@ pub fn unsafe_expressions(
|
||||||
) -> Vec<UnsafeExpr> {
|
) -> Vec<UnsafeExpr> {
|
||||||
let mut unsafe_exprs = vec![];
|
let mut unsafe_exprs = vec![];
|
||||||
let body = db.body(def);
|
let body = db.body(def);
|
||||||
walk_unsafe(&mut unsafe_exprs, db, infer, &body, body.body_expr, false);
|
walk_unsafe(&mut unsafe_exprs, db, infer, def, &body, body.body_expr, false);
|
||||||
|
|
||||||
unsafe_exprs
|
unsafe_exprs
|
||||||
}
|
}
|
||||||
|
@ -79,6 +80,7 @@ fn walk_unsafe(
|
||||||
unsafe_exprs: &mut Vec<UnsafeExpr>,
|
unsafe_exprs: &mut Vec<UnsafeExpr>,
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
infer: &InferenceResult,
|
infer: &InferenceResult,
|
||||||
|
def: DefWithBodyId,
|
||||||
body: &Body,
|
body: &Body,
|
||||||
current: ExprId,
|
current: ExprId,
|
||||||
inside_unsafe_block: bool,
|
inside_unsafe_block: bool,
|
||||||
|
@ -97,6 +99,15 @@ fn walk_unsafe(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expr::Path(path) => {
|
||||||
|
let resolver = resolver_for_expr(db.upcast(), def, current);
|
||||||
|
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 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Expr::MethodCall { .. } => {
|
Expr::MethodCall { .. } => {
|
||||||
if infer
|
if infer
|
||||||
.method_resolution(current)
|
.method_resolution(current)
|
||||||
|
@ -112,13 +123,13 @@ fn walk_unsafe(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Unsafe { body: child } => {
|
Expr::Unsafe { body: child } => {
|
||||||
return walk_unsafe(unsafe_exprs, db, infer, body, *child, true);
|
return walk_unsafe(unsafe_exprs, db, infer, def, body, *child, true);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
expr.walk_child_exprs(|child| {
|
expr.walk_child_exprs(|child| {
|
||||||
walk_unsafe(unsafe_exprs, db, infer, body, child, inside_unsafe_block);
|
walk_unsafe(unsafe_exprs, db, infer, def, body, child, inside_unsafe_block);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,6 +178,27 @@ fn main() {
|
||||||
HasUnsafe.unsafe_fn();
|
HasUnsafe.unsafe_fn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn missing_unsafe_diagnostic_with_static_mut() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
struct Ty {
|
||||||
|
a: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
static mut static_mut: Ty = Ty { a: 0 };
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = static_mut.a;
|
||||||
|
//^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
|
||||||
|
unsafe {
|
||||||
|
let x = static_mut.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue