aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancesco Zardi <[email protected]>2020-10-21 08:06:05 +0100
committerFrancesco Zardi <[email protected]>2020-10-21 08:06:05 +0100
commita9d996a7c5f962b4ac914c86f5005eb22128f511 (patch)
treeb56e177229758fbaa269388a6b64ff53b933e25d
parent2c5bd9517e202a6e2b004664f291b85093c8e0a9 (diff)
Add whitelist of safe intrinsics
-rw-r--r--crates/hir_def/src/item_tree/lower.rs44
-rw-r--r--crates/hir_def/src/item_tree/tests.rs20
-rw-r--r--crates/hir_expand/src/name.rs36
3 files changed, 98 insertions, 2 deletions
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 3328639cf..1a29081c5 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -3,7 +3,7 @@
3use std::{collections::hash_map::Entry, mem, sync::Arc}; 3use std::{collections::hash_map::Entry, mem, sync::Arc};
4 4
5use arena::map::ArenaMap; 5use arena::map::ArenaMap;
6use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId}; 6use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId};
7use smallvec::SmallVec; 7use smallvec::SmallVec;
8use syntax::{ 8use syntax::{
9 ast::{self, ModuleItemOwner}, 9 ast::{self, ModuleItemOwner},
@@ -42,6 +42,45 @@ pub(super) struct Ctx {
42 forced_visibility: Option<RawVisibilityId>, 42 forced_visibility: Option<RawVisibilityId>,
43} 43}
44 44
45/// Returns `true` if the given intrinsic is unsafe to call or not.
46pub fn is_intrinsic_fn_unsafe(name: &Name) -> bool {
47 // Should be kept in sync with https://github.com/rust-lang/rust/blob/c6e4db620a7d2f569f11dcab627430921ea8aacf/compiler/rustc_typeck/src/check/intrinsic.rs#L68
48 *name != known::abort
49 && *name != known::min_align_of
50 && *name != known::needs_drop
51 && *name != known::caller_location
52 && *name != known::size_of_val
53 && *name != known::min_align_of_val
54 && *name != known::add_with_overflow
55 && *name != known::sub_with_overflow
56 && *name != known::mul_with_overflow
57 && *name != known::wrapping_add
58 && *name != known::wrapping_sub
59 && *name != known::wrapping_mul
60 && *name != known::saturating_add
61 && *name != known::saturating_sub
62 && *name != known::rotate_left
63 && *name != known::rotate_right
64 && *name != known::ctpop
65 && *name != known::ctlz
66 && *name != known::cttz
67 && *name != known::bswap
68 && *name != known::bitreverse
69 && *name != known::discriminant_value
70 && *name != known::type_id
71 && *name != known::likely
72 && *name != known::unlikely
73 && *name != known::ptr_guaranteed_eq
74 && *name != known::ptr_guaranteed_ne
75 && *name != known::minnumf32
76 && *name != known::minnumf64
77 && *name != known::maxnumf32
78 && *name != known::rustc_peek
79 && *name != known::maxnumf64
80 && *name != known::type_name
81 && *name != known::variant_count
82}
83
45impl Ctx { 84impl Ctx {
46 pub(super) fn new(db: &dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self { 85 pub(super) fn new(db: &dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self {
47 Self { 86 Self {
@@ -555,7 +594,8 @@ impl Ctx {
555 let id: ModItem = match item { 594 let id: ModItem = match item {
556 ast::ExternItem::Fn(ast) => { 595 ast::ExternItem::Fn(ast) => {
557 let func = self.lower_function(&ast)?; 596 let func = self.lower_function(&ast)?;
558 self.data().functions[func.index].is_unsafe = true; 597 self.data().functions[func.index].is_unsafe =
598 is_intrinsic_fn_unsafe(&self.data().functions[func.index].name);
559 func.into() 599 func.into()
560 } 600 }
561 ast::ExternItem::Static(ast) => { 601 ast::ExternItem::Static(ast) => {
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs
index 4b354c4c1..495c5a7e9 100644
--- a/crates/hir_def/src/item_tree/tests.rs
+++ b/crates/hir_def/src/item_tree/tests.rs
@@ -437,3 +437,23 @@ fn assoc_item_macros() {
437 "#]], 437 "#]],
438 ); 438 );
439} 439}
440
441#[test]
442fn safe_intrinsic() {
443 check(
444 r"
445 #![feature(core_intrinsics)]
446
447 fn reverse(input: u32) -> u32 {
448 std::intrinsics::bitreverse(input)
449 }
450 ",
451 expect![[r#"
452 inner attrs: Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("feature"))] }, input: Some(TokenTree(SUBTREE () 0
453 IDENT core_intrinsics 1)) }]) }
454
455 top-level items:
456 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) }
457 "#]],
458 );
459}
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index 63f828707..0d5b56681 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -208,6 +208,42 @@ pub mod known {
208 PartialOrd, 208 PartialOrd,
209 Eq, 209 Eq,
210 PartialEq, 210 PartialEq,
211 // Safe primitives
212 abort,
213 size_of,
214 min_align_of,
215 needs_drop,
216 caller_location,
217 size_of_val,
218 min_align_of_val,
219 add_with_overflow,
220 sub_with_overflow,
221 mul_with_overflow,
222 wrapping_add,
223 wrapping_sub,
224 wrapping_mul,
225 saturating_add,
226 saturating_sub,
227 rotate_left,
228 rotate_right,
229 ctpop,
230 ctlz,
231 cttz,
232 bswap,
233 bitreverse,
234 discriminant_value,
235 type_id,
236 likely,
237 unlikely,
238 ptr_guaranteed_eq,
239 ptr_guaranteed_ne,
240 minnumf32,
241 minnumf64,
242 maxnumf32,
243 rustc_peek,
244 maxnumf64,
245 type_name,
246 variant_count,
211 ); 247 );
212 248
213 // self/Self cannot be used as an identifier 249 // self/Self cannot be used as an identifier