Unnamed repository; edit this file 'description' to name the repository.
fix: do not emit unsafe diagnositcs for safe statics in extern blocks
roife 2024-10-20
parent 9f1e450 · commit 002f6ad
-rw-r--r--crates/hir-def/src/data.rs4
-rw-r--r--crates/hir-def/src/item_tree.rs3
-rw-r--r--crates/hir-def/src/item_tree/lower.rs5
-rw-r--r--crates/hir-def/src/item_tree/pretty.rs16
-rw-r--r--crates/hir-ty/src/diagnostics/unsafe_check.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_unsafe.rs35
6 files changed, 62 insertions, 3 deletions
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index f2c49813fa..263fad51d7 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -571,6 +571,8 @@ pub struct StaticData {
pub visibility: RawVisibility,
pub mutable: bool,
pub is_extern: bool,
+ pub has_safe_kw: bool,
+ pub has_unsafe_kw: bool,
}
impl StaticData {
@@ -585,6 +587,8 @@ impl StaticData {
visibility: item_tree[statik.visibility].clone(),
mutable: statik.mutable,
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
+ has_safe_kw: statik.has_safe_kw,
+ has_unsafe_kw: statik.has_unsafe_kw,
})
}
}
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 4bee7eeb9e..7cb833fdce 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -823,7 +823,10 @@ pub struct Const {
pub struct Static {
pub name: Name,
pub visibility: RawVisibilityId,
+ // TODO: use bitflags when we have more flags
pub mutable: bool,
+ pub has_safe_kw: bool,
+ pub has_unsafe_kw: bool,
pub type_ref: Interned<TypeRef>,
pub ast_id: FileAstId<ast::Static>,
}
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index 1d8d236d97..431a7f66f4 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -487,8 +487,11 @@ impl<'a> Ctx<'a> {
let type_ref = self.lower_type_ref_opt(static_.ty());
let visibility = self.lower_visibility(static_);
let mutable = static_.mut_token().is_some();
+ let has_safe_kw = static_.safe_token().is_some();
+ let has_unsafe_kw = static_.unsafe_token().is_some();
let ast_id = self.source_ast_id_map.ast_id(static_);
- let res = Static { name, visibility, mutable, type_ref, ast_id };
+ let res =
+ Static { name, visibility, mutable, type_ref, ast_id, has_safe_kw, has_unsafe_kw };
Some(id(self.data().statics.alloc(res)))
}
diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs
index 5ab4718a36..9dce28b2e4 100644
--- a/crates/hir-def/src/item_tree/pretty.rs
+++ b/crates/hir-def/src/item_tree/pretty.rs
@@ -382,9 +382,23 @@ impl Printer<'_> {
wln!(self, " = _;");
}
ModItem::Static(it) => {
- let Static { name, visibility, mutable, type_ref, ast_id } = &self.tree[it];
+ let Static {
+ name,
+ visibility,
+ mutable,
+ type_ref,
+ ast_id,
+ has_safe_kw,
+ has_unsafe_kw,
+ } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
+ if *has_safe_kw {
+ w!(self, "safe ");
+ }
+ if *has_unsafe_kw {
+ w!(self, "unsafe ");
+ }
w!(self, "static ");
if *mutable {
w!(self, "mut ");
diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs
index ff45c725c7..bcfc37c867 100644
--- a/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -89,7 +89,7 @@ fn walk_unsafe(
let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path);
if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
let static_data = db.static_data(id);
- if static_data.mutable || static_data.is_extern {
+ if static_data.mutable || (static_data.is_extern && !static_data.has_safe_kw) {
unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
}
}
diff --git a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
index a53dd31286..cc0f4bfccc 100644
--- a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
@@ -595,4 +595,39 @@ unsafe fn foo(p: *mut i32) {
"#,
)
}
+
+ #[test]
+ fn no_unsafe_diagnostic_with_safe_kw() {
+ check_diagnostics(
+ r#"
+unsafe extern {
+ pub safe fn f();
+
+ pub unsafe fn g();
+
+ pub fn h();
+
+ pub safe static S1: i32;
+
+ pub unsafe static S2: i32;
+
+ pub static S3: i32;
+}
+
+fn main() {
+ f();
+ g();
+ //^^^💡 error: this operation is unsafe and requires an unsafe function or block
+ h();
+ //^^^💡 error: this operation is unsafe and requires an unsafe function or block
+
+ let _ = S1;
+ let _ = S2;
+ //^^💡 error: this operation is unsafe and requires an unsafe function or block
+ let _ = S3;
+ //^^💡 error: this operation is unsafe and requires an unsafe function or block
+}
+"#,
+ );
+ }
}