mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
feat: initial support for safe_kw in extern blocks
This commit is contained in:
parent
687b72c36a
commit
9f1e450c4f
12 changed files with 264 additions and 9 deletions
|
@ -148,6 +148,10 @@ impl FunctionData {
|
|||
self.flags.contains(FnFlags::HAS_UNSAFE_KW)
|
||||
}
|
||||
|
||||
pub fn is_safe(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_SAFE_KW)
|
||||
}
|
||||
|
||||
pub fn is_varargs(&self) -> bool {
|
||||
self.flags.contains(FnFlags::IS_VARARGS)
|
||||
}
|
||||
|
|
|
@ -754,6 +754,7 @@ bitflags::bitflags! {
|
|||
const HAS_ASYNC_KW = 1 << 4;
|
||||
const HAS_UNSAFE_KW = 1 << 5;
|
||||
const IS_VARARGS = 1 << 6;
|
||||
const HAS_SAFE_KW = 1 << 7;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -440,6 +440,9 @@ impl<'a> Ctx<'a> {
|
|||
if func.unsafe_token().is_some() {
|
||||
flags |= FnFlags::HAS_UNSAFE_KW;
|
||||
}
|
||||
if func.safe_token().is_some() {
|
||||
flags |= FnFlags::HAS_SAFE_KW;
|
||||
}
|
||||
if has_var_args {
|
||||
flags |= FnFlags::IS_VARARGS;
|
||||
}
|
||||
|
|
|
@ -278,6 +278,9 @@ impl Printer<'_> {
|
|||
if flags.contains(FnFlags::HAS_UNSAFE_KW) {
|
||||
w!(self, "unsafe ");
|
||||
}
|
||||
if flags.contains(FnFlags::HAS_SAFE_KW) {
|
||||
w!(self, "safe ");
|
||||
}
|
||||
if let Some(abi) = abi {
|
||||
w!(self, "extern \"{}\" ", abi);
|
||||
}
|
||||
|
|
|
@ -257,10 +257,12 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
|
|||
return true;
|
||||
}
|
||||
|
||||
match func.lookup(db.upcast()).container {
|
||||
let loc = func.lookup(db.upcast());
|
||||
match loc.container {
|
||||
hir_def::ItemContainerId::ExternBlockId(block) => {
|
||||
// Function in an `extern` block are always unsafe to call, except when it has
|
||||
// `"rust-intrinsic"` ABI there are a few exceptions.
|
||||
// Function in an `extern` block are always unsafe to call, except when
|
||||
// it is marked as `safe` or it has `"rust-intrinsic"` ABI there are a
|
||||
// few exceptions.
|
||||
let id = block.lookup(db.upcast()).id;
|
||||
|
||||
let is_intrinsic =
|
||||
|
@ -270,8 +272,8 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
|
|||
// Intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
|
||||
!data.attrs.by_key(&sym::rustc_safe_intrinsic).exists()
|
||||
} else {
|
||||
// Extern items are always unsafe
|
||||
true
|
||||
// Extern items without `safe` modifier are always unsafe
|
||||
!db.function_data(func).is_safe()
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
|
|
|
@ -554,7 +554,7 @@ fn main() {
|
|||
r#"
|
||||
//- /ed2021.rs crate:ed2021 edition:2021
|
||||
#[rustc_deprecated_safe_2024]
|
||||
unsafe fn safe() -> u8 {
|
||||
unsafe fn safe_fn() -> u8 {
|
||||
0
|
||||
}
|
||||
//- /ed2024.rs crate:ed2024 edition:2024
|
||||
|
@ -564,7 +564,7 @@ unsafe fn not_safe() -> u8 {
|
|||
}
|
||||
//- /main.rs crate:main deps:ed2021,ed2024
|
||||
fn main() {
|
||||
ed2021::safe();
|
||||
ed2021::safe_fn();
|
||||
ed2024::not_safe();
|
||||
//^^^^^^^^^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block
|
||||
}
|
||||
|
|
|
@ -135,6 +135,11 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
|
|||
has_mods = true;
|
||||
}
|
||||
|
||||
if p.at(T![safe]) {
|
||||
p.eat(T![safe]);
|
||||
has_mods = true;
|
||||
}
|
||||
|
||||
if p.at(T![extern]) {
|
||||
has_extern = true;
|
||||
has_mods = true;
|
||||
|
@ -189,6 +194,7 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
|
|||
T![fn] => fn_(p, m),
|
||||
|
||||
T![const] if p.nth(1) != T!['{'] => consts::konst(p, m),
|
||||
T![static] if matches!(p.nth(1), IDENT | T![_] | T![mut]) => consts::static_(p, m),
|
||||
|
||||
T![trait] => traits::trait_(p, m),
|
||||
T![impl] => traits::impl_(p, m),
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,208 @@
|
|||
SOURCE_FILE
|
||||
EXTERN_BLOCK
|
||||
UNSAFE_KW "unsafe"
|
||||
WHITESPACE " "
|
||||
ABI
|
||||
EXTERN_KW "extern"
|
||||
WHITESPACE " "
|
||||
EXTERN_ITEM_LIST
|
||||
L_CURLY "{"
|
||||
WHITESPACE "\n "
|
||||
FN
|
||||
COMMENT "// sqrt (from libm) may be called with any `f64`"
|
||||
WHITESPACE "\n "
|
||||
VISIBILITY
|
||||
PUB_KW "pub"
|
||||
WHITESPACE " "
|
||||
SAFE_KW "safe"
|
||||
WHITESPACE " "
|
||||
FN_KW "fn"
|
||||
WHITESPACE " "
|
||||
NAME
|
||||
IDENT "sqrt"
|
||||
PARAM_LIST
|
||||
L_PAREN "("
|
||||
PARAM
|
||||
IDENT_PAT
|
||||
NAME
|
||||
IDENT "x"
|
||||
COLON ":"
|
||||
WHITESPACE " "
|
||||
PATH_TYPE
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "f64"
|
||||
R_PAREN ")"
|
||||
WHITESPACE " "
|
||||
RET_TYPE
|
||||
THIN_ARROW "->"
|
||||
WHITESPACE " "
|
||||
PATH_TYPE
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "f64"
|
||||
SEMICOLON ";"
|
||||
WHITESPACE "\n\n "
|
||||
FN
|
||||
COMMENT "// strlen (from libc) requires a valid pointer,"
|
||||
WHITESPACE "\n "
|
||||
COMMENT "// so we mark it as being an unsafe fn"
|
||||
WHITESPACE "\n "
|
||||
VISIBILITY
|
||||
PUB_KW "pub"
|
||||
WHITESPACE " "
|
||||
UNSAFE_KW "unsafe"
|
||||
WHITESPACE " "
|
||||
FN_KW "fn"
|
||||
WHITESPACE " "
|
||||
NAME
|
||||
IDENT "strlen"
|
||||
PARAM_LIST
|
||||
L_PAREN "("
|
||||
PARAM
|
||||
IDENT_PAT
|
||||
NAME
|
||||
IDENT "p"
|
||||
COLON ":"
|
||||
WHITESPACE " "
|
||||
PTR_TYPE
|
||||
STAR "*"
|
||||
CONST_KW "const"
|
||||
WHITESPACE " "
|
||||
PATH_TYPE
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "c_char"
|
||||
R_PAREN ")"
|
||||
WHITESPACE " "
|
||||
RET_TYPE
|
||||
THIN_ARROW "->"
|
||||
WHITESPACE " "
|
||||
PATH_TYPE
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "usize"
|
||||
SEMICOLON ";"
|
||||
WHITESPACE "\n\n "
|
||||
FN
|
||||
COMMENT "// this function doesn't say safe or unsafe, so it defaults to unsafe"
|
||||
WHITESPACE "\n "
|
||||
VISIBILITY
|
||||
PUB_KW "pub"
|
||||
WHITESPACE " "
|
||||
FN_KW "fn"
|
||||
WHITESPACE " "
|
||||
NAME
|
||||
IDENT "free"
|
||||
PARAM_LIST
|
||||
L_PAREN "("
|
||||
PARAM
|
||||
IDENT_PAT
|
||||
NAME
|
||||
IDENT "p"
|
||||
COLON ":"
|
||||
WHITESPACE " "
|
||||
PTR_TYPE
|
||||
STAR "*"
|
||||
MUT_KW "mut"
|
||||
WHITESPACE " "
|
||||
PATH_TYPE
|
||||
PATH
|
||||
PATH
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "core"
|
||||
COLON2 "::"
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "ffi"
|
||||
COLON2 "::"
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "c_void"
|
||||
R_PAREN ")"
|
||||
SEMICOLON ";"
|
||||
WHITESPACE "\n\n "
|
||||
STATIC
|
||||
VISIBILITY
|
||||
PUB_KW "pub"
|
||||
WHITESPACE " "
|
||||
SAFE_KW "safe"
|
||||
WHITESPACE " "
|
||||
STATIC_KW "static"
|
||||
WHITESPACE " "
|
||||
MUT_KW "mut"
|
||||
WHITESPACE " "
|
||||
NAME
|
||||
IDENT "COUNTER"
|
||||
COLON ":"
|
||||
WHITESPACE " "
|
||||
PATH_TYPE
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "i32"
|
||||
SEMICOLON ";"
|
||||
WHITESPACE "\n\n "
|
||||
STATIC
|
||||
VISIBILITY
|
||||
PUB_KW "pub"
|
||||
WHITESPACE " "
|
||||
UNSAFE_KW "unsafe"
|
||||
WHITESPACE " "
|
||||
STATIC_KW "static"
|
||||
WHITESPACE " "
|
||||
NAME
|
||||
IDENT "IMPORTANT_BYTES"
|
||||
COLON ":"
|
||||
WHITESPACE " "
|
||||
ARRAY_TYPE
|
||||
L_BRACK "["
|
||||
PATH_TYPE
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "u8"
|
||||
SEMICOLON ";"
|
||||
WHITESPACE " "
|
||||
CONST_ARG
|
||||
LITERAL
|
||||
INT_NUMBER "256"
|
||||
R_BRACK "]"
|
||||
SEMICOLON ";"
|
||||
WHITESPACE "\n\n "
|
||||
STATIC
|
||||
VISIBILITY
|
||||
PUB_KW "pub"
|
||||
WHITESPACE " "
|
||||
SAFE_KW "safe"
|
||||
WHITESPACE " "
|
||||
STATIC_KW "static"
|
||||
WHITESPACE " "
|
||||
NAME
|
||||
IDENT "LINES"
|
||||
COLON ":"
|
||||
WHITESPACE " "
|
||||
PATH_TYPE
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "SyncUnsafeCell"
|
||||
GENERIC_ARG_LIST
|
||||
L_ANGLE "<"
|
||||
TYPE_ARG
|
||||
PATH_TYPE
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "i32"
|
||||
R_ANGLE ">"
|
||||
SEMICOLON ";"
|
||||
WHITESPACE "\n"
|
||||
R_CURLY "}"
|
||||
WHITESPACE "\n"
|
|
@ -0,0 +1,17 @@
|
|||
unsafe extern {
|
||||
// sqrt (from libm) may be called with any `f64`
|
||||
pub safe fn sqrt(x: f64) -> f64;
|
||||
|
||||
// strlen (from libc) requires a valid pointer,
|
||||
// so we mark it as being an unsafe fn
|
||||
pub unsafe fn strlen(p: *const c_char) -> usize;
|
||||
|
||||
// this function doesn't say safe or unsafe, so it defaults to unsafe
|
||||
pub fn free(p: *mut core::ffi::c_void);
|
||||
|
||||
pub safe static mut COUNTER: i32;
|
||||
|
||||
pub unsafe static IMPORTANT_BYTES: [u8; 256];
|
||||
|
||||
pub safe static LINES: SyncUnsafeCell<i32>;
|
||||
}
|
|
@ -190,7 +190,7 @@ UseTreeList =
|
|||
|
||||
Fn =
|
||||
Attr* Visibility?
|
||||
'default'? 'const'? 'async'? 'gen'? 'unsafe'? Abi?
|
||||
'default'? 'const'? 'async'? 'gen'? 'unsafe'? 'safe'? Abi?
|
||||
'fn' Name GenericParamList? ParamList RetType? WhereClause?
|
||||
(body:BlockExpr | ';')
|
||||
|
||||
|
@ -284,6 +284,7 @@ Const =
|
|||
|
||||
Static =
|
||||
Attr* Visibility?
|
||||
'unsafe'? 'safe'?
|
||||
'static' 'mut'? Name ':' Type
|
||||
('=' body:Expr)? ';'
|
||||
|
||||
|
|
|
@ -668,6 +668,8 @@ impl Fn {
|
|||
#[inline]
|
||||
pub fn gen_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![gen]) }
|
||||
#[inline]
|
||||
pub fn safe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![safe]) }
|
||||
#[inline]
|
||||
pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
|
||||
}
|
||||
|
||||
|
@ -1761,7 +1763,11 @@ impl Static {
|
|||
#[inline]
|
||||
pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
|
||||
#[inline]
|
||||
pub fn safe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![safe]) }
|
||||
#[inline]
|
||||
pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
|
||||
#[inline]
|
||||
pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
|
Loading…
Reference in a new issue