Add whitelist of safe intrinsics
This commit is contained in:
parent
2c5bd9517e
commit
a9d996a7c5
@ -3,7 +3,7 @@
|
||||
use std::{collections::hash_map::Entry, mem, sync::Arc};
|
||||
|
||||
use arena::map::ArenaMap;
|
||||
use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId};
|
||||
use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId};
|
||||
use smallvec::SmallVec;
|
||||
use syntax::{
|
||||
ast::{self, ModuleItemOwner},
|
||||
@ -42,6 +42,45 @@ pub(super) struct Ctx {
|
||||
forced_visibility: Option<RawVisibilityId>,
|
||||
}
|
||||
|
||||
/// Returns `true` if the given intrinsic is unsafe to call or not.
|
||||
pub fn is_intrinsic_fn_unsafe(name: &Name) -> bool {
|
||||
// Should be kept in sync with https://github.com/rust-lang/rust/blob/c6e4db620a7d2f569f11dcab627430921ea8aacf/compiler/rustc_typeck/src/check/intrinsic.rs#L68
|
||||
*name != known::abort
|
||||
&& *name != known::min_align_of
|
||||
&& *name != known::needs_drop
|
||||
&& *name != known::caller_location
|
||||
&& *name != known::size_of_val
|
||||
&& *name != known::min_align_of_val
|
||||
&& *name != known::add_with_overflow
|
||||
&& *name != known::sub_with_overflow
|
||||
&& *name != known::mul_with_overflow
|
||||
&& *name != known::wrapping_add
|
||||
&& *name != known::wrapping_sub
|
||||
&& *name != known::wrapping_mul
|
||||
&& *name != known::saturating_add
|
||||
&& *name != known::saturating_sub
|
||||
&& *name != known::rotate_left
|
||||
&& *name != known::rotate_right
|
||||
&& *name != known::ctpop
|
||||
&& *name != known::ctlz
|
||||
&& *name != known::cttz
|
||||
&& *name != known::bswap
|
||||
&& *name != known::bitreverse
|
||||
&& *name != known::discriminant_value
|
||||
&& *name != known::type_id
|
||||
&& *name != known::likely
|
||||
&& *name != known::unlikely
|
||||
&& *name != known::ptr_guaranteed_eq
|
||||
&& *name != known::ptr_guaranteed_ne
|
||||
&& *name != known::minnumf32
|
||||
&& *name != known::minnumf64
|
||||
&& *name != known::maxnumf32
|
||||
&& *name != known::rustc_peek
|
||||
&& *name != known::maxnumf64
|
||||
&& *name != known::type_name
|
||||
&& *name != known::variant_count
|
||||
}
|
||||
|
||||
impl Ctx {
|
||||
pub(super) fn new(db: &dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self {
|
||||
Self {
|
||||
@ -555,7 +594,8 @@ fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
|
||||
let id: ModItem = match item {
|
||||
ast::ExternItem::Fn(ast) => {
|
||||
let func = self.lower_function(&ast)?;
|
||||
self.data().functions[func.index].is_unsafe = true;
|
||||
self.data().functions[func.index].is_unsafe =
|
||||
is_intrinsic_fn_unsafe(&self.data().functions[func.index].name);
|
||||
func.into()
|
||||
}
|
||||
ast::ExternItem::Static(ast) => {
|
||||
|
@ -437,3 +437,23 @@ impl S {
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn safe_intrinsic() {
|
||||
check(
|
||||
r"
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
fn reverse(input: u32) -> u32 {
|
||||
std::intrinsics::bitreverse(input)
|
||||
}
|
||||
",
|
||||
expect![[r#"
|
||||
inner attrs: Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("feature"))] }, input: Some(TokenTree(SUBTREE () 0
|
||||
IDENT core_intrinsics 1)) }]) }
|
||||
|
||||
top-level items:
|
||||
Function { name: Name(Text("reverse")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, has_body: true, is_unsafe: false, params: [Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("u32"))] }, generic_args: [None] })], is_varargs: false, ret_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("u32"))] }, generic_args: [None] }), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(0) }
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -208,6 +208,42 @@ macro_rules! known_names {
|
||||
PartialOrd,
|
||||
Eq,
|
||||
PartialEq,
|
||||
// Safe primitives
|
||||
abort,
|
||||
size_of,
|
||||
min_align_of,
|
||||
needs_drop,
|
||||
caller_location,
|
||||
size_of_val,
|
||||
min_align_of_val,
|
||||
add_with_overflow,
|
||||
sub_with_overflow,
|
||||
mul_with_overflow,
|
||||
wrapping_add,
|
||||
wrapping_sub,
|
||||
wrapping_mul,
|
||||
saturating_add,
|
||||
saturating_sub,
|
||||
rotate_left,
|
||||
rotate_right,
|
||||
ctpop,
|
||||
ctlz,
|
||||
cttz,
|
||||
bswap,
|
||||
bitreverse,
|
||||
discriminant_value,
|
||||
type_id,
|
||||
likely,
|
||||
unlikely,
|
||||
ptr_guaranteed_eq,
|
||||
ptr_guaranteed_ne,
|
||||
minnumf32,
|
||||
minnumf64,
|
||||
maxnumf32,
|
||||
rustc_peek,
|
||||
maxnumf64,
|
||||
type_name,
|
||||
variant_count,
|
||||
);
|
||||
|
||||
// self/Self cannot be used as an identifier
|
||||
|
Loading…
Reference in New Issue
Block a user