From 3c038606a32329d3e4ce21e308e8a49635a6d44f Mon Sep 17 00:00:00 2001 From: Khyber Sen Date: Fri, 9 Jun 2023 01:58:05 -0700 Subject: [PATCH 1/3] (`c2rust-analyze`) Add the simple dataflow constraints for `CastKind::Misc` (still incomplete). --- c2rust-analyze/src/dataflow/type_check.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/c2rust-analyze/src/dataflow/type_check.rs b/c2rust-analyze/src/dataflow/type_check.rs index 5472bb9b96..29d7290a8f 100644 --- a/c2rust-analyze/src/dataflow/type_check.rs +++ b/c2rust-analyze/src/dataflow/type_check.rs @@ -141,6 +141,7 @@ impl<'tcx> TypeChecker<'tcx, '_> { CastKind::Misc => { match is_transmutable_ptr_cast(from_ty, to_ty) { Some(true) => { + self.do_assign_pointer_ids(to_lty.label, from_lty.label); // TODO add other dataflow constraints }, Some(false) => ::log::error!("TODO: unsupported ptr-to-ptr cast between pointee types not yet supported as safely transmutable: `{from_ty:?} as {to_ty:?}`"), From b20cea742881dee4c5b4dfe3003345c7db161250 Mon Sep 17 00:00:00 2001 From: Khyber Sen Date: Tue, 23 May 2023 00:52:02 -0700 Subject: [PATCH 2/3] (`c2rust-analyze`) Add complete dataflow constraints for `CastKind::Pointer` (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. --- c2rust-analyze/src/dataflow/type_check.rs | 27 +++++++++- c2rust-analyze/tests/analyze/string_casts.rs | 54 ++++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/c2rust-analyze/src/dataflow/type_check.rs b/c2rust-analyze/src/dataflow/type_check.rs index 29d7290a8f..2626890269 100644 --- a/c2rust-analyze/src/dataflow/type_check.rs +++ b/c2rust-analyze/src/dataflow/type_check.rs @@ -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. @@ -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) { diff --git a/c2rust-analyze/tests/analyze/string_casts.rs b/c2rust-analyze/tests/analyze/string_casts.rs index ea0c837a59..d33a1acf79 100644 --- a/c2rust-analyze/tests/analyze/string_casts.rs +++ b/c2rust-analyze/tests/analyze/string_casts.rs @@ -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(); +} From 19ce2bd1b345e8399c514616e8cadf8cbcf348bc Mon Sep 17 00:00:00 2001 From: Khyber Sen Date: Sun, 11 Jun 2023 22:33:26 -0700 Subject: [PATCH 3/3] (`c2rust-analyze`) Fix `cast_fn_item_to_fn_ptr` test to correctly create a `PointerCast::ReifyFnPointer`. --- c2rust-analyze/tests/analyze/string_casts.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/c2rust-analyze/tests/analyze/string_casts.rs b/c2rust-analyze/tests/analyze/string_casts.rs index d33a1acf79..9aa7c9bde8 100644 --- a/c2rust-analyze/tests/analyze/string_casts.rs +++ b/c2rust-analyze/tests/analyze/string_casts.rs @@ -35,9 +35,10 @@ pub fn cast_from_literal_explicit() { } /// [`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) { +pub fn cast_fn_item_to_fn_ptr() { + fn f(x: u8) -> i8 { + x as i8 + } f as fn(u8) -> i8; }