Skip to content

Commit 0f65864

Browse files
authored
Remove duplicated lamda/function pointer rules (#373)
`stable_sort` rules had 2 version of rules: one that takes a lambda and one that takes a function pointer. This PR removes the duplication by adding a new trait in libcc2rs: Callable. Callable is implemented by `Fn` (closures, safe function items, safe function pointers) and `unsafe fn` pointers. Unsafe functoin items reach the `Callable` trait to an explicit cast to `unsafe fn` pointers because they don't implement `Fn`.
1 parent 8e84d83 commit 0f65864

15 files changed

Lines changed: 112 additions & 99 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1826,6 +1826,20 @@ void Converter::ConvertFunctionToFunctionPointer(
18261826
computed_expr_type_ = ComputedExprType::FreshPointer;
18271827
}
18281828

1829+
std::string Converter::ConvertFnPtrCallee(clang::Expr *arg) {
1830+
PushExprKind push(*this, ExprKind::Callee);
1831+
Buffer buf(*this);
1832+
Convert(arg);
1833+
return std::move(buf).str();
1834+
}
1835+
1836+
std::string Converter::ConvertFnPtrPlaceholder(clang::Expr *arg) {
1837+
auto proto =
1838+
arg->getType()->getPointeeType()->getAs<clang::FunctionProtoType>();
1839+
return std::format("({} as {} {})", ConvertFnPtrCallee(arg), keyword_unsafe_,
1840+
ConvertFunctionPointerType(proto));
1841+
}
1842+
18291843
Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
18301844
using Kind = CallArg::Kind;
18311845

@@ -4617,22 +4631,20 @@ void Converter::PlaceholderCtx::dump() const {
46174631
<< ", declared_in_rule_as_rust_ptr: "
46184632
<< declared_in_rule_as_rust_ptr
46194633
<< ", access: " << static_cast<int>(access)
4620-
<< ", param_type: " << param_type
4634+
<< ", arg_idx: " << arg_idx
46214635
<< ", materialize_idx: " << materialize_idx << '\n';
46224636
}
46234637

46244638
std::string Converter::ConvertPlaceholder(clang::Expr *expr, clang::Expr *arg,
46254639
const PlaceholderCtx &ph_ctx) {
46264640
if (arg->getType()->isFunctionPointerType()) {
4627-
PushExprKind push(*this, ExprKind::Callee);
4628-
Buffer buf(*this);
4629-
Convert(arg);
4630-
return std::move(buf).str();
4641+
return ConvertFnPtrPlaceholder(arg);
46314642
}
46324643

46334644
if (ph_ctx.declared_in_rule_as_rust_ptr && arg->getType()->isArrayType()) {
4634-
return std::format("({} as {})", ConvertFreshPointer(arg),
4635-
ph_ctx.param_type);
4645+
return std::format(
4646+
"({} as {})", ConvertFreshPointer(arg),
4647+
Mapper::GetParamType(GetCalleeOrExpr(expr), ph_ctx.arg_idx));
46364648
}
46374649

46384650
if (ph_ctx.needs_materialization()) {
@@ -4647,8 +4659,9 @@ std::string Converter::ConvertPlaceholder(clang::Expr *expr, clang::Expr *arg,
46474659
}
46484660

46494661
if (ph_ctx.needs_pointer_receiver()) {
4650-
return std::format("({} as {})", ConvertFreshObject(arg),
4651-
ph_ctx.param_type);
4662+
return std::format(
4663+
"({} as {})", ConvertFreshObject(arg),
4664+
Mapper::GetParamType(GetCalleeOrExpr(expr), ph_ctx.arg_idx));
46524665
}
46534666

46544667
if (ph_ctx.needs_object_receiver()) {
@@ -4727,7 +4740,7 @@ std::string Converter::ConvertIRFragment(
47274740
bool is_receiver = HasReceiver(expr) && arg_idx == 0;
47284741

47294742
PlaceholderCtx ph_ctx{
4730-
.param_type = Mapper::GetParamType(GetCalleeOrExpr(expr), arg_idx),
4743+
.arg_idx = arg_idx,
47314744
.implicit_convert_to = GetParamImplicitConvertTarget(expr, arg_idx),
47324745
.materialize_ctx = ctx,
47334746
.materialize_idx =

‎cpp2rust/converter/converter.h‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
221221
};
222222

223223
struct PlaceholderCtx {
224-
std::string param_type;
224+
unsigned arg_idx;
225225
std::optional<clang::QualType> implicit_convert_to;
226226
TempMaterializationCtx *materialize_ctx;
227227
int materialize_idx; // <0 = no idx, >=0 idx valid
@@ -309,6 +309,9 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
309309
virtual void
310310
ConvertFunctionToFunctionPointer(const clang::FunctionDecl *fn_decl);
311311

312+
std::string ConvertFnPtrCallee(clang::Expr *arg);
313+
virtual std::string ConvertFnPtrPlaceholder(clang::Expr *arg);
314+
312315
// Option<fn> implements Copy
313316
virtual bool FunctionPointerImplementsCopy() const { return true; }
314317

‎cpp2rust/converter/mapper.cpp‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -682,10 +682,9 @@ std::string InstantiateTemplate(const clang::Expr *expr, unsigned n) {
682682
if (!rule) {
683683
return text;
684684
}
685-
for (auto &ty : subs) {
686-
if (ty) {
687-
ty = mapTypeStringRecursive(*ty);
688-
}
685+
auto &ty = subs.at(n - 1);
686+
if (ty) {
687+
ty = mapTypeStringRecursive(*ty);
689688
}
690689
return instantiateTgt(subs, text);
691690
}

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,10 @@ void ConverterRefCount::ConvertFunctionToFunctionPointer(
12871287
computed_expr_type_ = ComputedExprType::FreshPointer;
12881288
}
12891289

1290+
std::string ConverterRefCount::ConvertFnPtrPlaceholder(clang::Expr *arg) {
1291+
return ConvertFnPtrCallee(arg);
1292+
}
1293+
12901294
void ConverterRefCount::ConvertEqualsNullPtr(clang::Expr *expr) {
12911295
StrCat('(');
12921296
Convert(expr);

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ class ConverterRefCount final : public Converter {
103103
void
104104
ConvertFunctionToFunctionPointer(const clang::FunctionDecl *fn_decl) override;
105105

106+
std::string ConvertFnPtrPlaceholder(clang::Expr *arg) override;
107+
106108
// FnPtr does not implement Copy
107109
bool FunctionPointerImplementsCopy() const override { return false; }
108110

‎libcc2rs/src/callable.rs‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
macro_rules! callable {
5+
($name:ident; $($a:ident: $A:ident),*) => {
6+
pub trait $name<$($A,)* R> {
7+
fn call(&self, $($a: $A),*) -> R;
8+
}
9+
10+
impl<F, $($A,)* R> $name<$($A,)* R> for F
11+
where
12+
F: Fn($($A),*) -> R,
13+
{
14+
#[inline]
15+
fn call(&self, $($a: $A),*) -> R {
16+
self($($a),*)
17+
}
18+
}
19+
20+
impl<$($A,)* R> $name<$($A,)* R> for unsafe fn($($A),*) -> R {
21+
#[inline]
22+
fn call(&self, $($a: $A),*) -> R {
23+
unsafe { self($($a),*) }
24+
}
25+
}
26+
};
27+
}
28+
29+
callable!(Callable0;);
30+
callable!(Callable1; a1: A1);
31+
callable!(Callable2; a1: A1, a2: A2);
32+
callable!(Callable3; a1: A1, a2: A2, a3: A3);

‎libcc2rs/src/lib.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ pub use libc_shims::*;
2121
mod fn_ptr;
2222
pub use fn_ptr::FnPtr;
2323

24+
mod callable;
25+
pub use callable::*;
26+
2427
mod inc;
2528
pub use inc::*;
2629

‎rules/algorithm/src.cpp‎

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
struct T2 {
1111
friend bool operator<(T2 a, T2 b) { return false; }
12+
bool operator()(const T2 &, const T2 &) const;
1213
};
1314

1415
struct T1 {
@@ -91,14 +92,7 @@ template <class T1, class T2> T1 f3(T1 first, T1 last, const T2 &value) {
9192
return std::find(first, last, value);
9293
}
9394

94-
// TODO
95-
auto lambda = [](const T2 &a, const T2 &b) { return false; };
96-
void f6(T1 first, T1 last, decltype(lambda) comp) {
97-
return std::stable_sort(first, last, comp);
98-
}
99-
100-
template <typename T1, typename T2>
101-
void f7(T1 first, T1 last, bool (*comp)(const T2 &, const T2 &)) {
95+
void f6(T1 first, T1 last, T2 comp) {
10296
return std::stable_sort(first, last, comp);
10397
}
10498

@@ -126,14 +120,7 @@ std::ostream_iterator<char> f13(std::string::iterator a0,
126120
return std::copy(a0, a1, a2);
127121
}
128122

129-
// TODO
130-
auto lambda_nref = [](T2 a, T2 b) { return false; };
131-
void f14(T1 *first, T1 *last, decltype(lambda_nref) comp) {
132-
return std::stable_sort(first, last, comp);
133-
}
134-
135-
template <typename T1, typename T2>
136-
void f15(T1 *first, T1 *last, bool (*comp)(T2, T2)) {
123+
void f14(T1 *first, T1 *last, T2 comp) {
137124
return std::stable_sort(first, last, comp);
138125
}
139126

‎rules/algorithm/tgt_refcount.rs‎

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,9 @@ fn f3<T1: PartialEq + Clone + ByteRepr>(a0: Ptr<T1>, a1: Ptr<T1>, a2: T1) -> Ptr
3838

3939
fn f6<T1: Ord + Clone, T2>(a0: Ptr<T1>, a1: Ptr<T1>, a2: T2)
4040
where
41-
T2: FnMut(Ptr<T1>, Ptr<T1>) -> bool,
41+
T2: Callable2<Ptr<T1>, Ptr<T1>, bool>,
4242
{
43-
a0.sort_with_cmp(a1.get_offset(), a2)
44-
}
45-
46-
fn f7<T1: Ord + Clone, T2>(a0: Ptr<T1>, a1: Ptr<T1>, a2: T2)
47-
where
48-
T2: FnMut(Ptr<T1>, Ptr<T1>) -> bool,
49-
{
50-
a0.sort_with_cmp(a1.get_offset(), a2)
43+
a0.sort_with_cmp(a1.get_offset(), |x, y| a2.call(x, y))
5144
}
5245

5346
fn f8<T1: PartialOrd + Clone + ByteRepr>(a0: Ptr<T1>, a1: Ptr<T1>) -> Ptr<T1> {
@@ -109,17 +102,9 @@ fn f13(a0: Ptr<u8>, a1: Ptr<u8>, a2: &mut ::std::fs::File) -> ::std::fs::File {
109102

110103
fn f14<T1: Ord + Clone + ByteRepr, T2>(a0: Ptr<T1>, a1: Ptr<T1>, a2: T2)
111104
where
112-
T2: Fn(T1, T1) -> bool,
113-
{
114-
let fun = |x: Ptr<T1>, y: Ptr<T1>| a2((x.read()).clone(), (y.read()).clone());
115-
a0.sort_with_cmp(a1.get_offset(), fun)
116-
}
117-
118-
fn f15<T1: Ord + Clone + ByteRepr, T2>(a0: Ptr<T1>, a1: Ptr<T1>, a2: T2)
119-
where
120-
T2: Fn(T1, T1) -> bool,
105+
T2: Callable2<T1, T1, bool>,
121106
{
122-
let fun = |x: Ptr<T1>, y: Ptr<T1>| a2((x.read()).clone(), (y.read()).clone());
107+
let fun = |x: Ptr<T1>, y: Ptr<T1>| a2.call((x.read()).clone(), (y.read()).clone());
123108
a0.sort_with_cmp(a1.get_offset(), fun)
124109
}
125110

‎rules/algorithm/tgt_unsafe.rs‎

Lines changed: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) 2022-present INESC-ID.
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

4+
use libcc2rs::*;
45
use std::io::{Seek, Write};
56

67
unsafe fn f1<T1: Ord>(a0: *mut T1, a1: *mut T1) {
@@ -27,31 +28,15 @@ unsafe fn f3<T1: PartialEq>(a0: *mut T1, a1: *mut T1, a2: T1) -> *mut T1 {
2728
it
2829
}
2930

30-
unsafe fn f6<T1: Ord, T2>(a0: *mut T1, a1: *mut T1, a2: &mut T2)
31+
unsafe fn f6<T1: Ord, T2>(a0: *mut T1, a1: *mut T1, a2: T2)
3132
where
32-
T2: FnMut(&T1, &T1) -> bool,
33+
T2: Callable2<*const T1, *const T1, bool>,
3334
{
3435
let len = a1.offset_from(a0) as usize;
3536
::std::slice::from_raw_parts_mut(a0, len).sort_by(|x, y| {
36-
if (a2)(x, y) {
37+
if a2.call(x as *const _, y as *const _) {
3738
std::cmp::Ordering::Less
38-
} else if (a2)(y, x) {
39-
std::cmp::Ordering::Greater
40-
} else {
41-
std::cmp::Ordering::Equal
42-
}
43-
})
44-
}
45-
46-
unsafe fn f7<T1: Ord, T2>(a0: *mut T1, a1: *mut T1, a2: &mut T2)
47-
where
48-
T2: FnMut(&T1, &T1) -> bool,
49-
{
50-
let len = a1.offset_from(a0) as usize;
51-
::std::slice::from_raw_parts_mut(a0, len).sort_by(|x, y| {
52-
if (a2)(x, y) {
53-
std::cmp::Ordering::Less
54-
} else if (a2)(y, x) {
39+
} else if a2.call(y as *const _, x as *const _) {
5540
std::cmp::Ordering::Greater
5641
} else {
5742
std::cmp::Ordering::Equal
@@ -113,31 +98,15 @@ unsafe fn f13(
11398
a2.try_clone().unwrap()
11499
}
115100

116-
unsafe fn f14<T1: Ord + Copy, T2>(a0: *mut T1, a1: *mut T1, a2: &mut T2)
117-
where
118-
T2: FnMut(T1, T1) -> bool,
119-
{
120-
let len = a1.offset_from(a0) as usize;
121-
::std::slice::from_raw_parts_mut(a0, len).sort_by(|x, y| {
122-
if (a2)(*x, *y) {
123-
std::cmp::Ordering::Less
124-
} else if (a2)(*y, *x) {
125-
std::cmp::Ordering::Greater
126-
} else {
127-
std::cmp::Ordering::Equal
128-
}
129-
})
130-
}
131-
132-
unsafe fn f15<T1: Ord + Copy, T2>(a0: *mut T1, a1: *mut T1, a2: &mut T2)
101+
unsafe fn f14<T1: Ord + Copy, T2>(a0: *mut T1, a1: *mut T1, a2: T2)
133102
where
134-
T2: FnMut(T1, T1) -> bool,
103+
T2: Callable2<T1, T1, bool>,
135104
{
136105
let len = a1.offset_from(a0) as usize;
137106
::std::slice::from_raw_parts_mut(a0, len).sort_by(|x, y| {
138-
if (a2)(*x, *y) {
107+
if a2.call(*x, *y) {
139108
std::cmp::Ordering::Less
140-
} else if (a2)(*y, *x) {
109+
} else if a2.call(*y, *x) {
141110
std::cmp::Ordering::Greater
142111
} else {
143112
std::cmp::Ordering::Equal

0 commit comments

Comments
 (0)