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 ++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) (limited to 'crates/hir_def/src') 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) } + "#]], + ); +} -- cgit v1.2.3 From 0be21b05d6811936a22d491f2cea4c7fe244ce2f Mon Sep 17 00:00:00 2001 From: Francesco Zardi Date: Wed, 21 Oct 2020 21:53:05 +0200 Subject: Move safe intrinsic tests --- crates/hir_def/src/item_tree/tests.rs | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'crates/hir_def/src') diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs index 495c5a7e9..4b354c4c1 100644 --- a/crates/hir_def/src/item_tree/tests.rs +++ b/crates/hir_def/src/item_tree/tests.rs @@ -437,23 +437,3 @@ 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) } - "#]], - ); -} -- cgit v1.2.3 From aff04d81ba6a334c1ba20ea4e6e04ffc88221aee Mon Sep 17 00:00:00 2001 From: Francesco Zardi Date: Wed, 21 Oct 2020 21:53:37 +0200 Subject: Refactor is_intrinsic_fn_unsafe() and make it private --- crates/hir_def/src/item_tree/lower.rs | 81 ++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 39 deletions(-) (limited to 'crates/hir_def/src') diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 1a29081c5..ca7fb4a43 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -42,45 +42,6 @@ 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 { @@ -753,3 +714,45 @@ enum GenericsOwner<'a> { TypeAlias, Impl, } + +/// Returns `true` if the given intrinsic is unsafe to call, or false otherwise. +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 + ![ + known::abort, + known::min_align_of, + known::needs_drop, + known::caller_location, + known::size_of_val, + known::min_align_of_val, + known::add_with_overflow, + known::sub_with_overflow, + known::mul_with_overflow, + known::wrapping_add, + known::wrapping_sub, + known::wrapping_mul, + known::saturating_add, + known::saturating_sub, + known::rotate_left, + known::rotate_right, + known::ctpop, + known::ctlz, + known::cttz, + known::bswap, + known::bitreverse, + known::discriminant_value, + known::type_id, + known::likely, + known::unlikely, + known::ptr_guaranteed_eq, + known::ptr_guaranteed_ne, + known::minnumf32, + known::minnumf64, + known::maxnumf32, + known::rustc_peek, + known::maxnumf64, + known::type_name, + known::variant_count, + ] + .contains(&name) +} -- cgit v1.2.3