@@ -6,6 +6,7 @@ use std::sync::Arc;
66use hir_def:: {
77 body:: Body ,
88 expr:: { Expr , ExprId , UnaryOp } ,
9+ resolver:: { resolver_for_expr, ResolveValueResult , ValueNs } ,
910 DefWithBodyId ,
1011} ;
1112use 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