Skip to content

Commit f089690

Browse files
committed
Account for static mut in missing unsafe diagnostic
1 parent f1d5072 commit f089690

File tree

1 file changed

+35
-3
lines changed

1 file changed

+35
-3
lines changed

crates/ra_hir_ty/src/diagnostics/unsafe_check.rs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::sync::Arc;
66
use hir_def::{
77
body::Body,
88
expr::{Expr, ExprId, UnaryOp},
9+
resolver::{resolver_for_expr, ResolveValueResult, ValueNs},
910
DefWithBodyId,
1011
};
1112
use hir_expand::diagnostics::DiagnosticSink;
@@ -70,7 +71,7 @@ pub fn unsafe_expressions(
7071
) -> Vec<UnsafeExpr> {
7172
let mut unsafe_exprs = vec![];
7273
let body = db.body(def);
73-
walk_unsafe(&mut unsafe_exprs, db, infer, &body, body.body_expr, false);
74+
walk_unsafe(&mut unsafe_exprs, db, infer, def, &body, body.body_expr, false);
7475

7576
unsafe_exprs
7677
}
@@ -79,6 +80,7 @@ fn walk_unsafe(
7980
unsafe_exprs: &mut Vec<UnsafeExpr>,
8081
db: &dyn HirDatabase,
8182
infer: &InferenceResult,
83+
def: DefWithBodyId,
8284
body: &Body,
8385
current: ExprId,
8486
inside_unsafe_block: bool,
@@ -97,6 +99,15 @@ fn walk_unsafe(
9799
}
98100
}
99101
}
102+
Expr::Path(path) => {
103+
let resolver = resolver_for_expr(db.upcast(), def, current);
104+
let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path.mod_path());
105+
if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id))) = value_or_partial {
106+
if db.static_data(id).mutable {
107+
unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
108+
}
109+
}
110+
}
100111
Expr::MethodCall { .. } => {
101112
if infer
102113
.method_resolution(current)
@@ -112,13 +123,13 @@ fn walk_unsafe(
112123
}
113124
}
114125
Expr::Unsafe { body: child } => {
115-
return walk_unsafe(unsafe_exprs, db, infer, body, *child, true);
126+
return walk_unsafe(unsafe_exprs, db, infer, def, body, *child, true);
116127
}
117128
_ => {}
118129
}
119130

120131
expr.walk_child_exprs(|child| {
121-
walk_unsafe(unsafe_exprs, db, infer, body, child, inside_unsafe_block);
132+
walk_unsafe(unsafe_exprs, db, infer, def, body, child, inside_unsafe_block);
122133
});
123134
}
124135

@@ -167,6 +178,27 @@ fn main() {
167178
HasUnsafe.unsafe_fn();
168179
}
169180
}
181+
"#,
182+
);
183+
}
184+
185+
#[test]
186+
fn missing_unsafe_diagnostic_with_static_mut() {
187+
check_diagnostics(
188+
r#"
189+
struct Ty {
190+
a: u8,
191+
}
192+
193+
static mut static_mut: Ty = Ty { a: 0 };
194+
195+
fn main() {
196+
let x = static_mut.a;
197+
//^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
198+
unsafe {
199+
let x = static_mut.a;
200+
}
201+
}
170202
"#,
171203
);
172204
}

0 commit comments

Comments
 (0)