mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 06:11:35 +00:00
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](https://github.com/rust-analyzer/rust-analyzer/issues/5996#issuecomment-709234802). Co-authored-by: Francesco Zardi <frazar@users.noreply.github.com>
This commit is contained in:
commit
9eb6cbb80b
3 changed files with 99 additions and 2 deletions
|
@ -3,7 +3,7 @@
|
||||||
use std::{collections::hash_map::Entry, mem, sync::Arc};
|
use std::{collections::hash_map::Entry, mem, sync::Arc};
|
||||||
|
|
||||||
use arena::map::ArenaMap;
|
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 smallvec::SmallVec;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, ModuleItemOwner},
|
ast::{self, ModuleItemOwner},
|
||||||
|
@ -555,7 +555,8 @@ impl Ctx {
|
||||||
let id: ModItem = match item {
|
let id: ModItem = match item {
|
||||||
ast::ExternItem::Fn(ast) => {
|
ast::ExternItem::Fn(ast) => {
|
||||||
let func = self.lower_function(&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()
|
func.into()
|
||||||
}
|
}
|
||||||
ast::ExternItem::Static(ast) => {
|
ast::ExternItem::Static(ast) => {
|
||||||
|
@ -713,3 +714,45 @@ enum GenericsOwner<'a> {
|
||||||
TypeAlias,
|
TypeAlias,
|
||||||
Impl,
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -208,6 +208,42 @@ pub mod known {
|
||||||
PartialOrd,
|
PartialOrd,
|
||||||
Eq,
|
Eq,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
|
// Safe intrinsics
|
||||||
|
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
|
// self/Self cannot be used as an identifier
|
||||||
|
|
|
@ -199,6 +199,24 @@ fn main() {
|
||||||
let x = STATIC_MUT.a;
|
let x = STATIC_MUT.a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_missing_unsafe_diagnostic_with_safe_intrinsic() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
extern "rust-intrinsic" {
|
||||||
|
pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
|
||||||
|
pub fn floorf32(x: f32) -> f32; // Unsafe intrinsic
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = bitreverse(12);
|
||||||
|
let _ = floorf32(12.0);
|
||||||
|
//^^^^^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue