diff options
author | Francesco Zardi <[email protected]> | 2020-10-21 08:06:05 +0100 |
---|---|---|
committer | Francesco Zardi <[email protected]> | 2020-10-21 08:06:05 +0100 |
commit | a9d996a7c5f962b4ac914c86f5005eb22128f511 (patch) | |
tree | b56e177229758fbaa269388a6b64ff53b933e25d | |
parent | 2c5bd9517e202a6e2b004664f291b85093c8e0a9 (diff) |
Add whitelist of safe intrinsics
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 44 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/tests.rs | 20 | ||||
-rw-r--r-- | crates/hir_expand/src/name.rs | 36 |
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 @@ | |||
3 | use std::{collections::hash_map::Entry, mem, sync::Arc}; | 3 | use std::{collections::hash_map::Entry, mem, sync::Arc}; |
4 | 4 | ||
5 | use arena::map::ArenaMap; | 5 | use arena::map::ArenaMap; |
6 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId}; | 6 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId}; |
7 | use smallvec::SmallVec; | 7 | use smallvec::SmallVec; |
8 | use syntax::{ | 8 | use 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. | ||
46 | pub 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 | |||
45 | impl Ctx { | 84 | impl 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] | ||
442 | fn 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 |