Skip to content

Commit c94254d

Browse files
authored
Use reinterpret_cast to round-trip through void (#217)
1 parent 297f2bc commit c94254d

16 files changed

Lines changed: 84 additions & 52 deletions

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ std::string ConverterRefCount::BuildFnAdapter(
203203
closure += std::format("a{}", i);
204204
} else if (src_pty->isPointerType() && tgt_pty->isPointerType()) {
205205
if (tgt_pty->isVoidPointerType()) {
206-
closure += std::format("a{}.cast::<{}>().unwrap()", i,
206+
closure += std::format("a{}.reinterpret_cast::<{}>()", i,
207207
ConvertPointeeType(src_pty));
208208
} else if (src_pty->isVoidPointerType()) {
209209
closure += std::format("a{}.to_any()", i);
@@ -1301,7 +1301,7 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
13011301
expr->getType()->isPointerType()) {
13021302
Convert(expr->getSubExpr());
13031303
PushConversionKind push(*this, ConversionKind::Unboxed);
1304-
StrCat(std::format(".cast::<{}>().expect(\"ub:wrong type\")",
1304+
StrCat(std::format(".reinterpret_cast::<{}>()",
13051305
ConvertPointeeType(expr->getType())));
13061306
return false;
13071307
} else if (expr->getType()->isVoidPointerType() &&

libcc2rs/src/io.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,7 @@ pub unsafe fn cerr_unsafe() -> *mut std::fs::File {
8686

8787
pub fn fread_refcount(a0: AnyPtr, a1: usize, a2: usize, a3: Ptr<::std::fs::File>) -> usize {
8888
let total = a1.saturating_mul(a2);
89-
let mut dst = a0
90-
.cast::<u8>()
91-
.expect("fread: only supporting u8 pointers")
92-
.clone();
89+
let mut dst = a0.reinterpret_cast::<u8>();
9390

9491
let f = (*a3.upgrade().deref())
9592
.try_clone()
@@ -123,10 +120,7 @@ pub fn fread_refcount(a0: AnyPtr, a1: usize, a2: usize, a3: Ptr<::std::fs::File>
123120

124121
pub fn fwrite_refcount(a0: AnyPtr, a1: usize, a2: usize, a3: Ptr<::std::fs::File>) -> usize {
125122
let total = a1.saturating_mul(a2);
126-
let mut src = a0
127-
.cast::<u8>()
128-
.expect("fwrite: only supporting u8 pointers")
129-
.clone();
123+
let mut src = a0.reinterpret_cast::<u8>();
130124

131125
let f = (*a3.upgrade().deref())
132126
.try_clone()

libcc2rs/src/rc.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,11 +1100,14 @@ impl Default for AnyPtr {
11001100
}
11011101

11021102
impl AnyPtr {
1103-
pub fn cast<T: 'static>(&self) -> Option<Ptr<T>> {
1103+
pub fn reinterpret_cast<T: ByteRepr>(&self) -> Ptr<T> {
11041104
if self.ptr.is_null() {
1105-
return Some(Ptr::<T>::null());
1105+
return Ptr::<T>::null();
11061106
}
1107-
self.ptr.as_any().downcast_ref::<Ptr<T>>().cloned()
1107+
if let Some(p) = self.ptr.as_any().downcast_ref::<Ptr<T>>() {
1108+
return p.clone();
1109+
}
1110+
self.ptr.as_bytes().reinterpret_cast::<T>()
11081111
}
11091112
}
11101113

@@ -1265,27 +1268,23 @@ mod tests {
12651268
fn anyptr_null_cast() {
12661269
// void* nullptr
12671270
let any = Ptr::<()>::null().to_any();
1268-
let p: Option<Ptr<u32>> = any.cast::<u32>();
1269-
assert!(p.is_some());
1270-
assert!(p.unwrap().is_null());
1271+
let p = any.reinterpret_cast::<u32>();
1272+
assert!(p.is_null());
12711273

1272-
let p2: Option<Ptr<u8>> = any.cast::<u8>();
1273-
assert!(p2.is_some());
1274-
assert!(p2.unwrap().is_null());
1274+
let p2 = any.reinterpret_cast::<u8>();
1275+
assert!(p2.is_null());
12751276

12761277
// int* nullptr
12771278
let any2 = Ptr::<i32>::null().to_any();
1278-
let p3: Option<Ptr<f32>> = any2.cast::<f32>();
1279-
assert!(p3.is_some());
1280-
assert!(p3.unwrap().is_null());
1279+
let p3 = any2.reinterpret_cast::<f32>();
1280+
assert!(p3.is_null());
12811281
}
12821282

12831283
#[test]
12841284
fn to_any_without_clone() {
12851285
let p: Ptr<std::fs::File> = Ptr::null(); // std::fs::File is not Clone
12861286
let any = p.to_any();
1287-
let recovered = any.cast::<std::fs::File>();
1288-
assert!(recovered.is_some());
1289-
assert!(recovered.unwrap().is_null());
1287+
let recovered = any.reinterpret_cast::<std::fs::File>();
1288+
assert!(recovered.is_null());
12901289
}
12911290
}

libcc2rs/src/va_args.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,10 @@ impl<T> VaArgGet for *const T {
119119
}
120120
}
121121

122-
impl<T: 'static> VaArgGet for crate::rc::Ptr<T> {
122+
impl<T: 'static + crate::ByteRepr> VaArgGet for crate::rc::Ptr<T> {
123123
fn get(v: &VaArg) -> Self {
124124
match v {
125-
VaArg::Ptr(any) => any.cast::<T>().expect("VaArgGet: Ptr type mismatch"),
125+
VaArg::Ptr(any) => any.reinterpret_cast::<T>(),
126126
_ => panic!("VaArgGet: expected Ptr"),
127127
}
128128
}

tests/unit/out/refcount/fn_ptr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
99
pub fn my_foo_0(p: AnyPtr) -> i32 {
1010
let p: Value<AnyPtr> = Rc::new(RefCell::new(p));
11-
return ((*p.borrow()).cast::<i32>().expect("ub:wrong type").read());
11+
return ((*p.borrow()).reinterpret_cast::<i32>().read());
1212
}
1313
pub fn foo_1(fn_: FnPtr<fn(AnyPtr) -> i32>, pi: Ptr<i32>) -> i32 {
1414
let fn_: Value<FnPtr<fn(AnyPtr) -> i32>> = Rc::new(RefCell::new(fn_));

tests/unit/out/refcount/fn_ptr_cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ pub fn add_offset_4(base: Ptr<i32>, offset: i32) -> i32 {
8888
pub fn test_call_through_cast_5() {
8989
let gfn: Value<FnPtr<fn(AnyPtr, i32) -> i32>> = Rc::new(RefCell::new(
9090
FnPtr::<fn(Ptr<i32>, i32) -> i32>::new(add_offset_4).cast::<fn(AnyPtr, i32) -> i32>(Some(
91-
(|a0: AnyPtr, a1: i32| -> i32 { add_offset_4(a0.cast::<i32>().unwrap(), a1) })
91+
(|a0: AnyPtr, a1: i32| -> i32 { add_offset_4(a0.reinterpret_cast::<i32>(), a1) })
9292
as fn(AnyPtr, i32) -> i32,
9393
)),
9494
));

tests/unit/out/refcount/fn_ptr_stdlib_compare.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@ fn main_0() -> i32 {
4141
)
4242
.cast::<fn(Ptr<u8>, usize, usize, AnyPtr) -> usize>(Some(
4343
(|a0: Ptr<u8>, a1: usize, a2: usize, a3: AnyPtr| -> usize {
44-
libcc2rs::fread_refcount(a0.to_any(), a1, a2, a3.cast::<::std::fs::File>().unwrap())
44+
libcc2rs::fread_refcount(
45+
a0.to_any(),
46+
a1,
47+
a2,
48+
a3.reinterpret_cast::<::std::fs::File>(),
49+
)
4550
}) as fn(Ptr<u8>, usize, usize, AnyPtr) -> usize,
4651
)),
4752
));
@@ -56,7 +61,7 @@ fn main_0() -> i32 {
5661
FnPtr::<fn(Ptr<u8>, usize, usize, AnyPtr) -> usize>::new(my_alternative_fread_0)
5762
.cast::<fn(AnyPtr, usize, usize, Ptr<::std::fs::File>) -> usize>(Some(
5863
(|a0: AnyPtr, a1: usize, a2: usize, a3: Ptr<::std::fs::File>| -> usize {
59-
my_alternative_fread_0(a0.cast::<u8>().unwrap(), a1, a2, a3.to_any())
64+
my_alternative_fread_0(a0.reinterpret_cast::<u8>(), a1, a2, a3.to_any())
6065
}) as fn(AnyPtr, usize, usize, Ptr<::std::fs::File>) -> usize,
6166
)),
6267
));
@@ -195,7 +200,7 @@ fn main_0() -> i32 {
195200
a0.to_any(),
196201
a1,
197202
a2,
198-
a3.cast::<::std::fs::File>().unwrap(),
203+
a3.reinterpret_cast::<::std::fs::File>(),
199204
)
200205
}) as fn(Ptr<u8>, usize, usize, AnyPtr) -> usize,
201206
)),
@@ -211,7 +216,7 @@ fn main_0() -> i32 {
211216
FnPtr::<fn(Ptr<u8>, usize, usize, AnyPtr) -> usize>::new(my_alternative_fwrite_1)
212217
.cast::<fn(AnyPtr, usize, usize, Ptr<::std::fs::File>) -> usize>(Some(
213218
(|a0: AnyPtr, a1: usize, a2: usize, a3: Ptr<::std::fs::File>| -> usize {
214-
my_alternative_fwrite_1(a0.cast::<u8>().unwrap(), a1, a2, a3.to_any())
219+
my_alternative_fwrite_1(a0.reinterpret_cast::<u8>(), a1, a2, a3.to_any())
215220
}) as fn(AnyPtr, usize, usize, Ptr<::std::fs::File>) -> usize,
216221
)),
217222
));

tests/unit/out/refcount/fn_ptr_vtable.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ pub fn int_create_1(val: i32) -> AnyPtr {
6262
}
6363
pub fn int_get_2(p: AnyPtr) -> i32 {
6464
let p: Value<AnyPtr> = Rc::new(RefCell::new(p));
65-
return ((*p.borrow()).cast::<i32>().expect("ub:wrong type").read());
65+
return ((*p.borrow()).reinterpret_cast::<i32>().read());
6666
}
6767
pub fn int_destroy_3(p: AnyPtr) {
6868
let p: Value<AnyPtr> = Rc::new(RefCell::new(p));
69-
(*p.borrow()).cast::<i32>().expect("ub:wrong type").write(0);
69+
(*p.borrow()).reinterpret_cast::<i32>().write(0);
7070
}
7171
pub fn main() {
7272
std::process::exit(main_0());

tests/unit/out/refcount/ptr_to_incomplete_struct.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ fn main_0() -> i32 {
1313
let fp: Value<Ptr<::std::fs::File>> = Rc::new(RefCell::new((libcc2rs::cout()).clone()));
1414
let p: Value<AnyPtr> = Rc::new(RefCell::new((*fp.borrow()).clone().to_any()));
1515
let fp2: Value<Ptr<::std::fs::File>> = Rc::new(RefCell::new(
16-
((*p.borrow())
17-
.cast::<::std::fs::File>()
18-
.expect("ub:wrong type"))
19-
.clone(),
16+
((*p.borrow()).reinterpret_cast::<::std::fs::File>()).clone(),
2017
));
2118
assert!(
2219
((({

tests/unit/out/refcount/union_cross_arm_cast.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,7 @@ fn main_0() -> i32 {
157157
(*(*(((*(*c.borrow()).u.borrow()).a())
158158
.clone()
159159
.to_any()
160-
.cast::<shape_b>()
161-
.expect("ub:wrong type"))
160+
.reinterpret_cast::<shape_b>())
162161
.upgrade()
163162
.deref())
164163
.tail

0 commit comments

Comments
 (0)