about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-08-07 12:26:23 +0000
committerGitHub <noreply@github.com>2020-08-07 12:26:23 +0000
commit7a02cc8845ba4e9e3ec414283c60333143831733 (patch)
tree614076ad3ce5cf6c35cccc0828c72e11e53fea50
parent911ef38b24efc3e273f7395578c10e05ceb0cd7b (diff)
parentf089690a21357ca6d396bce98bf598f0954199b5 (diff)
downloadrust-7a02cc8845ba4e9e3ec414283c60333143831733.tar.gz
rust-7a02cc8845ba4e9e3ec414283c60333143831733.zip
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>
-rw-r--r--crates/ra_hir_ty/src/diagnostics/unsafe_check.rs38
1 files changed, 35 insertions, 3 deletions
diff --git a/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs b/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs
index 5cc76bdce41..61ffbf5d151 100644
--- a/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs
@@ -6,6 +6,7 @@ use std::sync::Arc;
 use hir_def::{
     body::Body,
     expr::{Expr, ExprId, UnaryOp},
+    resolver::{resolver_for_expr, ResolveValueResult, ValueNs},
     DefWithBodyId,
 };
 use hir_expand::diagnostics::DiagnosticSink;
@@ -70,7 +71,7 @@ pub fn unsafe_expressions(
 ) -> Vec<UnsafeExpr> {
     let mut unsafe_exprs = vec![];
     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
 }
@@ -79,6 +80,7 @@ fn walk_unsafe(
     unsafe_exprs: &mut Vec<UnsafeExpr>,
     db: &dyn HirDatabase,
     infer: &InferenceResult,
+    def: DefWithBodyId,
     body: &Body,
     current: ExprId,
     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 { .. } => {
             if infer
                 .method_resolution(current)
@@ -112,13 +123,13 @@ fn walk_unsafe(
             }
         }
         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| {
-        walk_unsafe(unsafe_exprs, db, infer, body, child, inside_unsafe_block);
+        walk_unsafe(unsafe_exprs, db, infer, def, body, child, inside_unsafe_block);
     });
 }
 
@@ -170,4 +181,25 @@ fn main() {
 "#,
         );
     }
+
+    #[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;
+    }
+}
+"#,
+        );
+    }
 }