From a9d996a7c5f962b4ac914c86f5005eb22128f511 Mon Sep 17 00:00:00 2001 From: Francesco Zardi Date: Wed, 21 Oct 2020 09:06:05 +0200 Subject: Add whitelist of safe intrinsics --- crates/hir_def/src/item_tree/lower.rs | 44 +++++++++++++++++++++++++++++++++-- crates/hir_def/src/item_tree/tests.rs | 20 ++++++++++++++++ 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 @@ 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, } +/// 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 @@ impl Ctx { 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) => { 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() { "#]], ); } + +#[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::(0) } + "#]], + ); +} 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 { 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 -- cgit v1.2.3