Skip to content

Commit 002f6ad

Browse files
committed
fix: do not emit unsafe diagnositcs for safe statics in extern blocks
1 parent 9f1e450 commit 002f6ad

File tree

6 files changed

+62
-3
lines changed

6 files changed

+62
-3
lines changed

crates/hir-def/src/data.rs

+4
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,8 @@ pub struct StaticData {
571571
pub visibility: RawVisibility,
572572
pub mutable: bool,
573573
pub is_extern: bool,
574+
pub has_safe_kw: bool,
575+
pub has_unsafe_kw: bool,
574576
}
575577

576578
impl StaticData {
@@ -585,6 +587,8 @@ impl StaticData {
585587
visibility: item_tree[statik.visibility].clone(),
586588
mutable: statik.mutable,
587589
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
590+
has_safe_kw: statik.has_safe_kw,
591+
has_unsafe_kw: statik.has_unsafe_kw,
588592
})
589593
}
590594
}

crates/hir-def/src/item_tree.rs

+3
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,10 @@ pub struct Const {
823823
pub struct Static {
824824
pub name: Name,
825825
pub visibility: RawVisibilityId,
826+
// TODO: use bitflags when we have more flags
826827
pub mutable: bool,
828+
pub has_safe_kw: bool,
829+
pub has_unsafe_kw: bool,
827830
pub type_ref: Interned<TypeRef>,
828831
pub ast_id: FileAstId<ast::Static>,
829832
}

crates/hir-def/src/item_tree/lower.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,11 @@ impl<'a> Ctx<'a> {
487487
let type_ref = self.lower_type_ref_opt(static_.ty());
488488
let visibility = self.lower_visibility(static_);
489489
let mutable = static_.mut_token().is_some();
490+
let has_safe_kw = static_.safe_token().is_some();
491+
let has_unsafe_kw = static_.unsafe_token().is_some();
490492
let ast_id = self.source_ast_id_map.ast_id(static_);
491-
let res = Static { name, visibility, mutable, type_ref, ast_id };
493+
let res =
494+
Static { name, visibility, mutable, type_ref, ast_id, has_safe_kw, has_unsafe_kw };
492495
Some(id(self.data().statics.alloc(res)))
493496
}
494497

crates/hir-def/src/item_tree/pretty.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,23 @@ impl Printer<'_> {
382382
wln!(self, " = _;");
383383
}
384384
ModItem::Static(it) => {
385-
let Static { name, visibility, mutable, type_ref, ast_id } = &self.tree[it];
385+
let Static {
386+
name,
387+
visibility,
388+
mutable,
389+
type_ref,
390+
ast_id,
391+
has_safe_kw,
392+
has_unsafe_kw,
393+
} = &self.tree[it];
386394
self.print_ast_id(ast_id.erase());
387395
self.print_visibility(*visibility);
396+
if *has_safe_kw {
397+
w!(self, "safe ");
398+
}
399+
if *has_unsafe_kw {
400+
w!(self, "unsafe ");
401+
}
388402
w!(self, "static ");
389403
if *mutable {
390404
w!(self, "mut ");

crates/hir-ty/src/diagnostics/unsafe_check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ fn walk_unsafe(
8989
let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path);
9090
if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
9191
let static_data = db.static_data(id);
92-
if static_data.mutable || static_data.is_extern {
92+
if static_data.mutable || (static_data.is_extern && !static_data.has_safe_kw) {
9393
unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
9494
}
9595
}

crates/ide-diagnostics/src/handlers/missing_unsafe.rs

+35
Original file line numberDiff line numberDiff line change
@@ -595,4 +595,39 @@ unsafe fn foo(p: *mut i32) {
595595
"#,
596596
)
597597
}
598+
599+
#[test]
600+
fn no_unsafe_diagnostic_with_safe_kw() {
601+
check_diagnostics(
602+
r#"
603+
unsafe extern {
604+
pub safe fn f();
605+
606+
pub unsafe fn g();
607+
608+
pub fn h();
609+
610+
pub safe static S1: i32;
611+
612+
pub unsafe static S2: i32;
613+
614+
pub static S3: i32;
615+
}
616+
617+
fn main() {
618+
f();
619+
g();
620+
//^^^💡 error: this operation is unsafe and requires an unsafe function or block
621+
h();
622+
//^^^💡 error: this operation is unsafe and requires an unsafe function or block
623+
624+
let _ = S1;
625+
let _ = S2;
626+
//^^💡 error: this operation is unsafe and requires an unsafe function or block
627+
let _ = S3;
628+
//^^💡 error: this operation is unsafe and requires an unsafe function or block
629+
}
630+
"#,
631+
);
632+
}
598633
}

0 commit comments

Comments
 (0)