@@ -6,6 +6,7 @@ use std::sync::Arc;
6
6
use hir_def:: {
7
7
body:: Body ,
8
8
expr:: { Expr , ExprId , UnaryOp } ,
9
+ resolver:: { resolver_for_expr, ResolveValueResult , ValueNs } ,
9
10
DefWithBodyId ,
10
11
} ;
11
12
use hir_expand:: diagnostics:: DiagnosticSink ;
@@ -70,7 +71,7 @@ pub fn unsafe_expressions(
70
71
) -> Vec < UnsafeExpr > {
71
72
let mut unsafe_exprs = vec ! [ ] ;
72
73
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 ) ;
74
75
75
76
unsafe_exprs
76
77
}
@@ -79,6 +80,7 @@ fn walk_unsafe(
79
80
unsafe_exprs : & mut Vec < UnsafeExpr > ,
80
81
db : & dyn HirDatabase ,
81
82
infer : & InferenceResult ,
83
+ def : DefWithBodyId ,
82
84
body : & Body ,
83
85
current : ExprId ,
84
86
inside_unsafe_block : bool ,
@@ -97,6 +99,15 @@ fn walk_unsafe(
97
99
}
98
100
}
99
101
}
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
+ }
100
111
Expr :: MethodCall { .. } => {
101
112
if infer
102
113
. method_resolution ( current)
@@ -112,13 +123,13 @@ fn walk_unsafe(
112
123
}
113
124
}
114
125
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 ) ;
116
127
}
117
128
_ => { }
118
129
}
119
130
120
131
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) ;
122
133
} ) ;
123
134
}
124
135
@@ -167,6 +178,27 @@ fn main() {
167
178
HasUnsafe.unsafe_fn();
168
179
}
169
180
}
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
+ }
170
202
"# ,
171
203
) ;
172
204
}
0 commit comments