mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
fix: do not emit unsafe diagnositcs for safe statics in extern blocks
This commit is contained in:
parent
9f1e450c4f
commit
002f6ad6f1
6 changed files with 62 additions and 3 deletions
|
@ -571,6 +571,8 @@ pub struct StaticData {
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
pub mutable: bool,
|
pub mutable: bool,
|
||||||
pub is_extern: bool,
|
pub is_extern: bool,
|
||||||
|
pub has_safe_kw: bool,
|
||||||
|
pub has_unsafe_kw: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StaticData {
|
impl StaticData {
|
||||||
|
@ -585,6 +587,8 @@ impl StaticData {
|
||||||
visibility: item_tree[statik.visibility].clone(),
|
visibility: item_tree[statik.visibility].clone(),
|
||||||
mutable: statik.mutable,
|
mutable: statik.mutable,
|
||||||
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
|
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
|
||||||
|
has_safe_kw: statik.has_safe_kw,
|
||||||
|
has_unsafe_kw: statik.has_unsafe_kw,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -823,7 +823,10 @@ pub struct Const {
|
||||||
pub struct Static {
|
pub struct Static {
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
pub visibility: RawVisibilityId,
|
pub visibility: RawVisibilityId,
|
||||||
|
// TODO: use bitflags when we have more flags
|
||||||
pub mutable: bool,
|
pub mutable: bool,
|
||||||
|
pub has_safe_kw: bool,
|
||||||
|
pub has_unsafe_kw: bool,
|
||||||
pub type_ref: Interned<TypeRef>,
|
pub type_ref: Interned<TypeRef>,
|
||||||
pub ast_id: FileAstId<ast::Static>,
|
pub ast_id: FileAstId<ast::Static>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -487,8 +487,11 @@ impl<'a> Ctx<'a> {
|
||||||
let type_ref = self.lower_type_ref_opt(static_.ty());
|
let type_ref = self.lower_type_ref_opt(static_.ty());
|
||||||
let visibility = self.lower_visibility(static_);
|
let visibility = self.lower_visibility(static_);
|
||||||
let mutable = static_.mut_token().is_some();
|
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 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)))
|
Some(id(self.data().statics.alloc(res)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -382,9 +382,23 @@ impl Printer<'_> {
|
||||||
wln!(self, " = _;");
|
wln!(self, " = _;");
|
||||||
}
|
}
|
||||||
ModItem::Static(it) => {
|
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_ast_id(ast_id.erase());
|
||||||
self.print_visibility(*visibility);
|
self.print_visibility(*visibility);
|
||||||
|
if *has_safe_kw {
|
||||||
|
w!(self, "safe ");
|
||||||
|
}
|
||||||
|
if *has_unsafe_kw {
|
||||||
|
w!(self, "unsafe ");
|
||||||
|
}
|
||||||
w!(self, "static ");
|
w!(self, "static ");
|
||||||
if *mutable {
|
if *mutable {
|
||||||
w!(self, "mut ");
|
w!(self, "mut ");
|
||||||
|
|
|
@ -89,7 +89,7 @@ fn walk_unsafe(
|
||||||
let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path);
|
let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path);
|
||||||
if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
|
if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
|
||||||
let static_data = db.static_data(id);
|
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 });
|
unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue