Skip to content

Commit 9eb6cbb

Browse files
bors[bot]frazar
andauthored
Merge #6307
6307: Add whitelist of safe intrinsics r=frazar a=frazar This PR should fix #5996, where intrinsic operations where all marked as unsafe. I'm rather new to this codebase, so I might be doing something *very* wrong. Please forgive me! In particular, I'm not sure how to "check that we are in extern `rust-intrinsics`" as mentioned [in this comment](#5996 (comment)). Co-authored-by: Francesco Zardi <[email protected]>
2 parents cc63f15 + aff04d8 commit 9eb6cbb

File tree

3 files changed

+99
-2
lines changed

3 files changed

+99
-2
lines changed

crates/hir_def/src/item_tree/lower.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::{collections::hash_map::Entry, mem, sync::Arc};
44

55
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};
77
use smallvec::SmallVec;
88
use syntax::{
99
ast::{self, ModuleItemOwner},
@@ -555,7 +555,8 @@ impl Ctx {
555555
let id: ModItem = match item {
556556
ast::ExternItem::Fn(ast) => {
557557
let func = self.lower_function(&ast)?;
558-
self.data().functions[func.index].is_unsafe = true;
558+
self.data().functions[func.index].is_unsafe =
559+
is_intrinsic_fn_unsafe(&self.data().functions[func.index].name);
559560
func.into()
560561
}
561562
ast::ExternItem::Static(ast) => {
@@ -713,3 +714,45 @@ enum GenericsOwner<'a> {
713714
TypeAlias,
714715
Impl,
715716
}
717+
718+
/// Returns `true` if the given intrinsic is unsafe to call, or false otherwise.
719+
fn is_intrinsic_fn_unsafe(name: &Name) -> bool {
720+
// Should be kept in sync with https://github.com/rust-lang/rust/blob/c6e4db620a7d2f569f11dcab627430921ea8aacf/compiler/rustc_typeck/src/check/intrinsic.rs#L68
721+
![
722+
known::abort,
723+
known::min_align_of,
724+
known::needs_drop,
725+
known::caller_location,
726+
known::size_of_val,
727+
known::min_align_of_val,
728+
known::add_with_overflow,
729+
known::sub_with_overflow,
730+
known::mul_with_overflow,
731+
known::wrapping_add,
732+
known::wrapping_sub,
733+
known::wrapping_mul,
734+
known::saturating_add,
735+
known::saturating_sub,
736+
known::rotate_left,
737+
known::rotate_right,
738+
known::ctpop,
739+
known::ctlz,
740+
known::cttz,
741+
known::bswap,
742+
known::bitreverse,
743+
known::discriminant_value,
744+
known::type_id,
745+
known::likely,
746+
known::unlikely,
747+
known::ptr_guaranteed_eq,
748+
known::ptr_guaranteed_ne,
749+
known::minnumf32,
750+
known::minnumf64,
751+
known::maxnumf32,
752+
known::rustc_peek,
753+
known::maxnumf64,
754+
known::type_name,
755+
known::variant_count,
756+
]
757+
.contains(&name)
758+
}

crates/hir_expand/src/name.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,42 @@ pub mod known {
208208
PartialOrd,
209209
Eq,
210210
PartialEq,
211+
// Safe intrinsics
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,
211247
);
212248

213249
// self/Self cannot be used as an identifier

crates/hir_ty/src/diagnostics/unsafe_check.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,24 @@ fn main() {
199199
let x = STATIC_MUT.a;
200200
}
201201
}
202+
"#,
203+
);
204+
}
205+
206+
#[test]
207+
fn no_missing_unsafe_diagnostic_with_safe_intrinsic() {
208+
check_diagnostics(
209+
r#"
210+
extern "rust-intrinsic" {
211+
pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
212+
pub fn floorf32(x: f32) -> f32; // Unsafe intrinsic
213+
}
214+
215+
fn main() {
216+
let _ = bitreverse(12);
217+
let _ = floorf32(12.0);
218+
//^^^^^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
219+
}
202220
"#,
203221
);
204222
}

0 commit comments

Comments
 (0)