use crate::def_ids::intrinsic_api;
use crate::def_ids::nomir_api;
use crate::def_ids::other_api;
use crate::def_ids::type_ids;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::Ty;
fn any_def(callee: Option<DefId>, defs: &[DefId]) -> bool {
callee.is_some_and(|c| defs.contains(&c))
}
pub fn is_ownership_reconstruction(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::box_from_raw(),
nomir_api::cstring_from_raw(),
other_api::arc_from_raw(),
other_api::rc_from_raw(),
other_api::box_from_raw_in(),
other_api::arc_from_raw_in(),
other_api::rc_from_raw_in(),
nomir_api::cstring_from_vec_with_nul_unchecked(),
],
)
}
pub fn is_manually_drop_drop(callee: Option<DefId>) -> bool {
callee.is_some_and(|c| other_api::manually_drop() == Some(c))
}
pub fn is_std_drop(callee: Option<DefId>) -> bool {
callee.is_some_and(|c| other_api::drop() == Some(c))
}
pub fn is_drop_in_place(callee: Option<DefId>) -> bool {
callee.is_some_and(|c| other_api::drop_in_place() == Some(c))
}
pub fn is_as_ptr(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::slice_as_ptr(),
other_api::slice_as_mut_ptr(),
other_api::str_as_ptr(),
other_api::str_as_mut_ptr(),
other_api::vec_as_ptr(),
other_api::vec_as_mut_ptr(),
other_api::cstr_as_ptr(),
other_api::nonnull_as_ptr(),
other_api::const_ptr_slice_as_ptr(),
other_api::mut_ptr_slice_as_mut_ptr(),
other_api::nonnull_slice_as_mut_ptr(),
other_api::box_as_ptr(),
other_api::box_as_mut_ptr(),
other_api::maybe_uninit_as_ptr(),
other_api::maybe_uninit_as_mut_ptr(),
other_api::arc_as_ptr(),
other_api::rc_as_ptr(),
other_api::const_ptr_cast(),
other_api::const_ptr_cast_mut(),
other_api::const_ptr_cast_array(),
other_api::mut_ptr_cast(),
other_api::mut_ptr_cast_const(),
other_api::mut_ptr_cast_array(),
other_api::nonnull_cast(),
other_api::box_into_raw(),
other_api::cstring_into_raw(),
other_api::arc_into_raw(),
other_api::rc_into_raw(),
],
)
}
pub(crate) fn is_raw_ptr_cast(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::const_ptr_cast(),
other_api::const_ptr_cast_mut(),
other_api::const_ptr_cast_array(),
other_api::mut_ptr_cast(),
other_api::mut_ptr_cast_const(),
other_api::mut_ptr_cast_array(),
],
)
}
pub fn is_as_ptr_valid(callee: Option<DefId>) -> bool {
is_as_ptr(callee) && !is_raw_ptr_cast(callee)
}
pub fn is_str_as_bytes(callee: Option<DefId>) -> bool {
other_api::matches_any(callee, &[other_api::str_as_bytes()])
}
pub(crate) fn is_element_ptr_add(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::const_ptr_add(),
other_api::const_ptr_wrapping_add(),
other_api::const_ptr_offset(),
other_api::const_ptr_wrapping_offset(),
other_api::mut_ptr_add(),
other_api::mut_ptr_wrapping_add(),
other_api::mut_ptr_offset(),
other_api::mut_ptr_wrapping_offset(),
other_api::nonnull_add(),
other_api::nonnull_offset(),
],
)
}
pub(crate) fn is_element_ptr_sub(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::const_ptr_sub(),
other_api::const_ptr_wrapping_sub(),
other_api::mut_ptr_sub(),
other_api::mut_ptr_wrapping_sub(),
other_api::nonnull_sub(),
],
)
}
pub(crate) fn is_byte_ptr_add(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::const_ptr_byte_add(),
other_api::const_ptr_wrapping_byte_add(),
other_api::const_ptr_byte_offset(),
other_api::const_ptr_wrapping_byte_offset(),
other_api::mut_ptr_byte_add(),
other_api::mut_ptr_wrapping_byte_add(),
other_api::mut_ptr_byte_offset(),
other_api::mut_ptr_wrapping_byte_offset(),
other_api::nonnull_byte_add(),
other_api::nonnull_byte_offset(),
],
)
}
pub(crate) fn is_byte_ptr_sub(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::const_ptr_byte_sub(),
other_api::const_ptr_wrapping_byte_sub(),
other_api::mut_ptr_byte_sub(),
other_api::mut_ptr_wrapping_byte_sub(),
other_api::nonnull_byte_sub(),
],
)
}
pub fn is_pointer_add(callee: Option<DefId>) -> bool {
is_element_ptr_add(callee) || is_byte_ptr_add(callee)
}
pub fn is_pointer_sub(callee: Option<DefId>) -> bool {
is_element_ptr_sub(callee) || is_byte_ptr_sub(callee)
}
pub fn is_intrinsic_copy(callee: Option<DefId>) -> bool {
intrinsic_api::is_copy(callee) || intrinsic_api::is_copy_nonoverlapping(callee)
}
pub fn is_intrinsic_ptr_offset_from(callee: Option<DefId>) -> bool {
intrinsic_api::is_ptr_offset_from(callee) || intrinsic_api::is_ptr_offset_from_unsigned(callee)
}
pub fn is_intrinsic_branch_hint(callee: Option<DefId>) -> bool {
intrinsic_api::is_unlikely(callee) || intrinsic_api::is_likely(callee)
}
pub fn is_intrinsic_with_overflow(callee: Option<DefId>) -> bool {
intrinsic_api::is_add_with_overflow(callee)
|| intrinsic_api::is_sub_with_overflow(callee)
|| intrinsic_api::is_mul_with_overflow(callee)
}
pub fn is_intrinsic_nonzero_preserving(callee: Option<DefId>) -> bool {
intrinsic_api::is_bswap(callee)
|| intrinsic_api::is_ctpop(callee)
|| intrinsic_api::is_bitreverse(callee)
|| intrinsic_api::is_rotate_left(callee)
|| intrinsic_api::is_rotate_right(callee)
}
pub fn is_intrinsic_pure_opaque(callee: Option<DefId>) -> bool {
intrinsic_api::is_float_to_int_unchecked(callee)
|| intrinsic_api::is_vtable_size(callee)
|| intrinsic_api::is_vtable_align(callee)
|| intrinsic_api::is_size_of_val(callee)
}
pub fn is_layout_constant(callee: Option<DefId>) -> bool {
intrinsic_api::is_size_of(callee)
|| intrinsic_api::is_align_of(callee)
|| other_api::matches_any(
callee,
&[other_api::mem_size_of(), other_api::mem_align_of()],
)
}
pub fn is_align_offset(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::ptr_align_offset(),
other_api::nonnull_align_offset(),
other_api::const_ptr_align_offset(),
other_api::mut_ptr_align_offset(),
],
)
}
pub fn is_ptr_write(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::ptr_write(),
other_api::ptr_write_unaligned(),
other_api::ptr_write_volatile(),
other_api::ptr_write_bytes(),
],
)
}
pub fn is_ptr_copy(callee: Option<DefId>) -> bool {
is_intrinsic_copy(callee)
|| other_api::matches_any(
callee,
&[other_api::ptr_copy(), other_api::ptr_copy_nonoverlapping()],
)
}
pub fn is_ptr_read(callee: Option<DefId>) -> bool {
is_intrinsic_copy(callee)
|| other_api::matches_any(
callee,
&[
other_api::ptr_read(),
other_api::ptr_read_unaligned(),
other_api::ptr_read_volatile(),
other_api::copy_to(),
other_api::copy_to_nonoverlapping(),
other_api::copy_from(),
other_api::copy_from_nonoverlapping(),
other_api::assume_init_read(),
],
)
}
pub fn is_maybe_uninit_write(callee: Option<DefId>) -> bool {
other_api::matches_any(callee, &[other_api::maybe_uninit_write()])
}
pub fn is_maybe_uninit_uninit(callee: Option<DefId>) -> bool {
other_api::matches_any(callee, &[other_api::maybe_uninit_uninit()])
}
pub fn is_maybe_uninit_assume_init(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::maybe_uninit_assume_init(),
other_api::assume_init_read(),
other_api::maybe_uninit_assume_init_ref(),
other_api::maybe_uninit_assume_init_mut(),
],
)
}
pub fn is_mem_copy_or_write(callee: Option<DefId>) -> bool {
is_intrinsic_copy(callee)
|| other_api::matches_any(
callee,
&[
other_api::copy_from_nonoverlapping(),
other_api::copy_to_nonoverlapping(),
other_api::ptr_write(),
other_api::ptr_write_bytes(),
],
)
}
pub fn is_from_raw_parts(callee: Option<DefId>) -> bool {
any_def(callee, other_api::from_raw_parts_fns())
}
pub fn is_with_metadata_of(callee: Option<DefId>) -> bool {
any_def(callee, other_api::with_metadata_of_fns())
}
pub fn is_from_raw_parts_mut(callee: Option<DefId>) -> bool {
any_def(callee, other_api::from_raw_parts_mut_fns())
}
pub fn is_cstr_from_ptr(callee: Option<DefId>) -> bool {
other_api::matches_any(callee, &[other_api::cstr_from_ptr()])
}
pub fn is_cstr_unchecked_constructor(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::cstr_from_bytes_with_nul_unchecked(),
nomir_api::cstring_from_vec_with_nul_unchecked(),
],
)
}
pub fn is_vec_push_or_reserve(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::vec_push(),
other_api::vec_reserve(),
other_api::vec_reserve_exact(),
],
)
}
pub fn is_vec_alloc_constructor(callee: Option<DefId>) -> bool {
other_api::matches_any(callee, &[other_api::vec_from_elem()])
}
pub fn is_vec_from_box(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::slice_into_vec(),
#[cfg(rapx_ge_99)]
other_api::box_assume_init_into_vec_unsafe(),
],
)
}
pub fn is_exchange_malloc(callee: Option<DefId>) -> bool {
callee.is_some_and(|c| other_api::exchange_malloc() == Some(c))
}
pub fn is_vec_with_capacity(callee: Option<DefId>) -> bool {
any_def(callee, other_api::with_capacity_fns())
}
pub fn is_box_alloc_ctor(callee: Option<DefId>) -> bool {
any_def(callee, other_api::box_alloc_ctors())
}
pub fn is_into_boxed_slice(callee: Option<DefId>) -> bool {
other_api::matches_any(callee, &[other_api::vec_into_boxed_slice()])
}
pub fn is_ownership_transfer(callee: Option<DefId>) -> bool {
let Some(callee) = callee else { return false };
is_ownership_reconstruction(Some(callee))
&& !other_api::contains(&[nomir_api::cstring_from_vec_with_nul_unchecked()], callee)
}
pub fn is_vec_ownership_transfer(callee: Option<DefId>) -> bool {
any_def(callee, other_api::vec_ownership_transfer_fns())
}
pub(crate) fn is_nonnull_checked_new(callee: Option<DefId>) -> bool {
other_api::matches_any(callee, &[other_api::nonnull_new()])
}
pub(crate) fn is_nonnull_new_unchecked(callee: Option<DefId>) -> bool {
other_api::matches_any(callee, &[other_api::nonnull_new_unchecked()])
}
pub fn is_nonnull_as_ref_as_mut(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[other_api::nonnull_as_ref(), other_api::nonnull_as_mut()],
)
}
pub fn is_nonnull_as_mut(callee: Option<DefId>) -> bool {
other_api::matches_any(callee, &[other_api::nonnull_as_mut()])
}
pub fn is_vec_invalidating_method(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::vec_push(),
other_api::vec_reserve(),
other_api::vec_reserve_exact(),
other_api::vec_shrink_to_fit(),
other_api::vec_shrink_to(),
other_api::vec_insert(),
other_api::vec_remove(),
other_api::vec_clear(),
other_api::vec_truncate(),
other_api::vec_set_len(),
],
)
}
pub fn is_ownership_return(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::box_into_raw(),
other_api::cstring_into_raw(),
other_api::arc_into_raw(),
other_api::rc_into_raw(),
],
)
}
pub fn is_benign_origin_use(callee: Option<DefId>) -> bool {
other_api::matches_any(
callee,
&[
other_api::const_ptr_is_null(),
other_api::const_ptr_addr(),
other_api::const_ptr_cast(),
other_api::const_ptr_cast_mut(),
other_api::const_ptr_slice_is_empty(),
other_api::const_ptr_slice_len(),
other_api::const_ptr_slice_as_ptr(),
other_api::mut_ptr_is_null(),
other_api::mut_ptr_addr(),
other_api::mut_ptr_cast(),
other_api::mut_ptr_cast_const(),
other_api::mut_ptr_slice_is_empty(),
other_api::mut_ptr_slice_len(),
other_api::mut_ptr_slice_as_mut_ptr(),
other_api::nonnull_addr(),
other_api::nonnull_cast(),
other_api::nonnull_as_ptr(),
other_api::nonnull_slice_is_empty(),
other_api::nonnull_slice_len(),
other_api::nonnull_slice_as_mut_ptr(),
other_api::slice_len(),
other_api::slice_is_empty(),
other_api::slice_as_ptr(),
other_api::slice_as_mut_ptr(),
other_api::str_len(),
other_api::str_is_empty(),
other_api::str_as_ptr(),
other_api::str_as_mut_ptr(),
other_api::vec_len(),
other_api::vec_is_empty(),
other_api::vec_as_ptr(),
other_api::vec_as_mut_ptr(),
other_api::string_len(),
other_api::string_is_empty(),
other_api::cstr_as_ptr(),
other_api::cstr_is_empty(),
],
)
}
pub fn is_std_vec(def_id: DefId) -> bool {
type_ids::vec_types().contains(&def_id)
}
pub fn is_std_box(def_id: DefId) -> bool {
type_ids::box_types().contains(&def_id)
}
pub fn is_std_cstring(def_id: DefId) -> bool {
type_ids::cstring_types().contains(&def_id)
}
pub fn is_std_nonnull(def_id: DefId) -> bool {
type_ids::nonnull_types().contains(&def_id)
}
pub fn is_maybe_uninit_type(def_id: DefId) -> bool {
type_ids::maybe_uninit_types().contains(&def_id)
}
pub fn is_maybe_uninit_ty(ty: Ty<'_>) -> bool {
use rustc_middle::ty::TyKind;
let mut t = ty;
loop {
match t.kind() {
TyKind::Slice(e) | TyKind::Array(e, _) => t = *e,
TyKind::RawPtr(e, _) | TyKind::Ref(_, e, _) => t = *e,
TyKind::Adt(adt, _) => return is_maybe_uninit_type(adt.did()),
_ => return false,
}
}
}
pub fn is_std_iter_or_itermut(def_id: DefId) -> bool {
type_ids::iter_types().contains(&def_id)
}
pub fn is_std_ordering(def_id: DefId) -> bool {
type_ids::ordering_types().contains(&def_id)
}
pub fn is_integer_wrapping_sub_method(callee: Option<DefId>) -> bool {
any_def(callee, other_api::integer_wrapping_sub_fns())
}
pub fn is_checked_next_pow2(callee: Option<DefId>) -> bool {
any_def(callee, other_api::checked_next_pow2_fns())
}
pub fn is_layout_align(callee: Option<DefId>) -> bool {
any_def(callee, other_api::layout_align_fns())
}
pub fn is_split_at(callee: Option<DefId>) -> bool {
any_def(callee, other_api::split_at_fns())
}
pub fn is_align_to_local(callee: Option<DefId>) -> bool {
any_def(callee, other_api::align_to_local_fns())
}
pub fn is_iter_position(callee: Option<DefId>) -> bool {
any_def(callee, other_api::iter_position_fns())
}
pub fn is_strlen(callee: Option<DefId>) -> bool {
any_def(callee, other_api::strlen_fns())
}
pub fn is_slice_get_unchecked(callee: Option<DefId>) -> bool {
any_def(callee, other_api::slice_get_unchecked_fns())
}
pub fn is_index_method(callee: Option<DefId>) -> bool {
any_def(callee, other_api::index_fns())
}
pub fn is_eq_call(callee: Option<DefId>) -> bool {
any_def(callee, other_api::eq_fns())
}
pub fn is_sliceindex_get_unchecked(callee: Option<DefId>) -> bool {
any_def(callee, other_api::sliceindex_get_unchecked_fns())
}
pub fn is_range_next(callee: Option<DefId>) -> bool {
any_def(callee, other_api::range_next_fns())
}
pub fn is_iter_next(callee: Option<DefId>) -> bool {
any_def(callee, other_api::iter_next_fns())
}
pub fn is_iter_len(callee: Option<DefId>) -> bool {
any_def(callee, other_api::iter_len_fns())
}
pub fn is_iter_is_empty(callee: Option<DefId>) -> bool {
any_def(callee, other_api::iter_is_empty_fns())
}
pub fn is_branch(callee: Option<DefId>) -> bool {
any_def(callee, other_api::branch_fns())
}
pub fn is_gcd(callee: Option<DefId>) -> bool {
any_def(callee, other_api::gcd_fns())
}
pub fn is_index_range(def_id: DefId) -> bool {
type_ids::index_range_types().contains(&def_id)
}
pub fn is_slice_range(callee: Option<DefId>) -> bool {
any_def(callee, other_api::slice_range_fns())
}
pub fn is_mem_replace(callee: Option<DefId>) -> bool {
other_api::matches_any(callee, &[other_api::replace()])
}