Skip to content

Commit

Permalink
(c2rust-analyze) Add complete dataflow constraints for `CastKind::P…
Browse files Browse the repository at this point in the history
…ointer` (previously incomplete).

More tests have also been added to `string_casts.rs`
exercising as many of the `PointerCast`s as possible,
but many of these crash later on, so they're disabled.
  • Loading branch information
kkysen committed Jun 9, 2023
1 parent 3c03860 commit b20cea7
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 2 deletions.
27 changes: 25 additions & 2 deletions c2rust-analyze/src/dataflow/type_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::{SubstsRef, Ty, TyKind};
use std::iter;

/// Visitor that walks over the MIR, computing types of rvalues/operands/places and generating
/// constraints as a side effect.
Expand Down Expand Up @@ -135,8 +136,30 @@ impl<'tcx> TypeChecker<'tcx, '_> {
PointerCast::ArrayToPointer => {}
PointerCast::Unsize => {}
}
self.do_assign_pointer_ids(to_lty.label, from_lty.label)
// TODO add other dataflow constraints

// We would normally do `self.do_assign`,
// but we can't do a normal `self.do_equivalence_nested` (inside `self.do_assign`),
// so we do the `self.do_assign_pointer_ids` from `self.do_assign`,
// and then do the body of `self.do_equivalence_nested`,
// but after the extra outer layers are stripped.

self.do_assign_pointer_ids(to_lty.label, from_lty.label);

// Each of these ptr casts needs at least the outer layer stripped (e.x. `&`, `*mut`, `fn`),
// but then after that, these ptr casts below
// needs more layers stripped to reach the types that are equivalent.
let strip_from = |lty: LTy<'tcx>| match ptr_cast {
PointerCast::ArrayToPointer => lty.args[0],
PointerCast::Unsize => lty.args[0],
_ => lty,
};
let strip_to = |lty: LTy<'tcx>| match ptr_cast {
PointerCast::Unsize => lty.args[0],
_ => lty,
};
for (&from_lty, &to_lty) in iter::zip(from_lty.args, to_lty.args) {
self.do_unify(strip_from(from_lty), strip_to(to_lty));
}
}
CastKind::Misc => {
match is_transmutable_ptr_cast(from_ty, to_ty) {
Expand Down
54 changes: 54 additions & 0 deletions c2rust-analyze/tests/analyze/string_casts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,57 @@ pub fn cast_from_literal() {
pub fn cast_from_literal_explicit() {
std::ptr::addr_of!(*b"\0") as *const u8 as *const core::ffi::c_char;
}

/// [`PointerCast::ReifyFnPointer`]
/// Can't figure out how to create a [`PointerCast::ReifyFnPointer`].
#[cfg(any())]
pub fn cast_fn_item_to_fn_ptr(f: impl Fn(u8) -> i8) {
f as fn(u8) -> i8;
}

/// [`PointerCast::UnsafeFnPointer`]
///
/// ```shell
/// thread 'rustc' panicked at 'not yet implemented', c2rust-analyze/src/labeled_ty.rs:372:17
/// ```
#[cfg(any())]
pub fn cast_fn_ptr_to_unsafe_fn_ptr(f: fn(u8) -> i8) {
f as unsafe fn(u8) -> i8;
}

/// [`PointerCast::ClosureFnPointer`]
/// Unhandled very early on.
#[cfg(any())]
pub fn cast_closure_to_fn_ptr() {
(|b: u8| b as i8) as fn(u8) -> i8;
}

/// [`PointerCast::MutToConstPointer`]
///
/// ```shell
/// thread 'rustc' panicked at 'not yet implemented', c2rust-analyze/src/labeled_ty.rs:372:17
/// ```
#[cfg(any())]
pub fn cast_mut_to_const_ptr(p: *mut i32) {
p as *const i32;
}

/// Meant to be [`PointerCast::ArrayToPointer`], but is [`CastKind::Misc`].
pub fn cast_array_ptr_to_ptr(p: *const [i32; 1]) {
p as *const i32;
}

/// [`PointerCast::Unsize`]
///
/// ```shell
/// thread 'rustc' panicked at 'expected to find only one Assign statement, but got multiple', c2rust-analyze/src/rewrite/expr/hir_op.rs:126:21
/// ```
#[cfg(any())]
pub fn cast_unsize_direct(a: &[i32; 1]) {
a as &[i32];
}

/// [`PointerCast::Unsize`]
pub fn cast_unsize_indirect(a: &[i32; 1]) {
let _ = a.as_ptr();
}

0 comments on commit b20cea7

Please sign in to comment.