From 84ac34ff89cf1cafcd85c29d2f48cc04a0dc97d4 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 9 Oct 2026 09:32:07 +0100 Subject: [PATCH 1/6] Update tests --- tests/unit/lambda_as_template_argument.cpp | 1 - tests/unit/lambda_generic.cpp | 1 - tests/unit/lambda_generic_to_fn_ptr.cpp | 1 - tests/unit/lambda_self_recursive.cpp | 1 - .../refcount/lambda_as_template_argument.rs | 108 ++++++++++++++++++ .../out/refcount/lambda_capture_copy_ctor.rs | 14 +-- .../out/refcount/lambda_capture_implicit.rs | 6 +- .../refcount/lambda_capture_library_types.rs | 8 +- tests/unit/out/refcount/lambda_capture_ref.rs | 12 +- .../out/refcount/lambda_capture_star_this.rs | 6 +- .../unit/out/refcount/lambda_capture_this.rs | 6 +- .../unit/out/refcount/lambda_capture_value.rs | 16 +-- tests/unit/out/refcount/lambda_generic.rs | 104 +++++++++++++++++ .../out/refcount/lambda_generic_to_fn_ptr.rs | 44 +++++++ .../out/refcount/lambda_move_only_capture.rs | 6 +- tests/unit/out/refcount/lambda_mutable.rs | 4 +- tests/unit/out/refcount/lambda_nested.rs | 8 +- .../out/refcount/lambda_self_recursive.rs | 104 +++++++++++++++++ tests/unit/out/refcount/unboxed_locals.rs | 2 +- .../out/unsafe/lambda_as_template_argument.rs | 102 +++++++++++++++++ .../out/unsafe/lambda_capture_copy_ctor.rs | 14 +-- .../out/unsafe/lambda_capture_implicit.rs | 6 +- .../unsafe/lambda_capture_library_types.rs | 8 +- tests/unit/out/unsafe/lambda_capture_ref.rs | 12 +- .../out/unsafe/lambda_capture_star_this.rs | 6 +- tests/unit/out/unsafe/lambda_capture_this.rs | 6 +- tests/unit/out/unsafe/lambda_capture_value.rs | 16 +-- tests/unit/out/unsafe/lambda_generic.rs | 87 ++++++++++++++ .../out/unsafe/lambda_generic_to_fn_ptr.rs | 54 +++++++++ .../out/unsafe/lambda_move_only_capture.rs | 6 +- tests/unit/out/unsafe/lambda_mutable.rs | 4 +- tests/unit/out/unsafe/lambda_nested.rs | 8 +- .../unit/out/unsafe/lambda_self_recursive.rs | 99 ++++++++++++++++ tests/unit/out/unsafe/unboxed_locals.rs | 2 +- 34 files changed, 790 insertions(+), 92 deletions(-) create mode 100644 tests/unit/out/refcount/lambda_as_template_argument.rs create mode 100644 tests/unit/out/refcount/lambda_generic.rs create mode 100644 tests/unit/out/refcount/lambda_generic_to_fn_ptr.rs create mode 100644 tests/unit/out/refcount/lambda_self_recursive.rs create mode 100644 tests/unit/out/unsafe/lambda_as_template_argument.rs create mode 100644 tests/unit/out/unsafe/lambda_generic.rs create mode 100644 tests/unit/out/unsafe/lambda_generic_to_fn_ptr.rs create mode 100644 tests/unit/out/unsafe/lambda_self_recursive.rs diff --git a/tests/unit/lambda_as_template_argument.cpp b/tests/unit/lambda_as_template_argument.cpp index 0385de50b..824ef3191 100644 --- a/tests/unit/lambda_as_template_argument.cpp +++ b/tests/unit/lambda_as_template_argument.cpp @@ -1,4 +1,3 @@ -// translation-fail #include template int apply_int(F fn, int x) { return fn(x); } diff --git a/tests/unit/lambda_generic.cpp b/tests/unit/lambda_generic.cpp index 11030e47c..f3997633d 100644 --- a/tests/unit/lambda_generic.cpp +++ b/tests/unit/lambda_generic.cpp @@ -1,4 +1,3 @@ -// translation-fail #include int main() { diff --git a/tests/unit/lambda_generic_to_fn_ptr.cpp b/tests/unit/lambda_generic_to_fn_ptr.cpp index 21d8670f5..3bf5d77b6 100644 --- a/tests/unit/lambda_generic_to_fn_ptr.cpp +++ b/tests/unit/lambda_generic_to_fn_ptr.cpp @@ -1,4 +1,3 @@ -// translation-fail #include int main() { diff --git a/tests/unit/lambda_self_recursive.cpp b/tests/unit/lambda_self_recursive.cpp index 0c85c5a56..f05b0c654 100644 --- a/tests/unit/lambda_self_recursive.cpp +++ b/tests/unit/lambda_self_recursive.cpp @@ -1,5 +1,4 @@ // ADDITIONAL_COMPILE_FLAGS: -std=c++23 -// translation-fail #include int main() { diff --git a/tests/unit/out/refcount/lambda_as_template_argument.rs b/tests/unit/out/refcount/lambda_as_template_argument.rs new file mode 100644 index 000000000..85abc59f1 --- /dev/null +++ b/tests/unit/out/refcount/lambda_as_template_argument.rs @@ -0,0 +1,108 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn apply_int_0(fn_: FnPtr i32>, mut x: i32) -> i32 { + let fn_: Value i32>> = Rc::new(RefCell::new(fn_)); + return ({ (*fn_.borrow()).call(x) }); +} +pub fn apply_int_1(fn_: FnPtr, mut x: i32) -> i32 { + let fn_: Value> = Rc::new(RefCell::new(fn_)); + return ({ (*fn_.borrow()).spec:: i32>().call(x) }); +} +pub fn apply_int_2(fn_: FnPtr, mut x: i32) -> i32 { + let fn_: Value> = Rc::new(RefCell::new(fn_)); + return ({ (*fn_.borrow()).spec:: i32>().call(x) }); +} +pub fn apply_int_3(fn_: FnPtr, mut x: i32) -> i32 { + let fn_: Value> = Rc::new(RefCell::new(fn_)); + return ({ (*fn_.borrow()).spec:: i32>().call(x) }); +} +pub fn apply_double_4(fn_: FnPtr, mut x: f64) -> f64 { + let fn_: Value> = Rc::new(RefCell::new(fn_)); + return ({ (*fn_.borrow()).spec:: f64>().call(x) }); +} +pub fn apply_double_5(fn_: FnPtr, mut x: f64) -> f64 { + let fn_: Value> = Rc::new(RefCell::new(fn_)); + return ({ (*fn_.borrow()).spec:: f64>().call(x) }); +} +pub fn apply_twice_6(fn_: FnPtr i32>, mut x: i32) -> i32 { + let fn_: Value i32>> = Rc::new(RefCell::new(fn_)); + return ({ + let _x: i32 = ({ (*fn_.borrow()).call(x) }); + (*fn_.borrow()).call(_x) + }) + .clone(); +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let factor: Value = Rc::new(RefCell::new(3)); + let scale: Value i32>> = Rc::new(RefCell::new(lambda!( + { + let factor: Value = Rc::new(RefCell::new((*factor.borrow()))); + }, + |x: i32| -> i32 { + return (x * (*factor.borrow())); + }, + ))); + assert!((({ apply_twice_6((*scale.borrow()).copy_from(), 4,) }) == 36)); + assert!( + (({ + apply_int_0( + FnPtr:: i32>::new(|x: i32| -> i32 { + { + return -x; + } + }), + 9, + ) + }) == -9_i32) + ); + let generic_scale: Value> = Rc::new(RefCell::new(lambda!( + Generic, + { + let factor: Value = Rc::new(RefCell::new((*factor.borrow()))); + }, + |x: i32| -> i32 { + return (x * (*factor.borrow())); + }, + |x: f64| -> f64 { + return (x * ((*factor.borrow()) as f64)); + }, + ))); + assert!((({ apply_int_1((*generic_scale.borrow()).copy_from(), 4,) }) == 12)); + assert!((({ apply_double_4((*generic_scale.borrow()).copy_from(), 1.5_f64,) }) == 4.5_f64)); + assert!( + (({ + apply_int_2( + lambda!(Generic, {}, |x: i32| -> i32 { + return -x; + },), + 9, + ) + }) == -9_i32) + ); + let offset: Value> = Rc::new(RefCell::new(lambda!( + Generic, + { + let factor: Value = Rc::new(RefCell::new((*factor.borrow()))); + }, + |x: i32| -> i32 { + return (x + (*factor.borrow())); + }, + |x: f64| -> f64 { + return (x + ((*factor.borrow()) as f64)); + }, + ))); + assert!((({ apply_int_3((*offset.borrow()).copy_from(), 4,) }) == 7)); + assert!((({ apply_double_5((*offset.borrow()).copy_from(), 1.5_f64,) }) == 4.5_f64)); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/lambda_capture_copy_ctor.rs b/tests/unit/out/refcount/lambda_capture_copy_ctor.rs index 1dcd24481..8ea3112f1 100644 --- a/tests/unit/out/refcount/lambda_capture_copy_ctor.rs +++ b/tests/unit/out/refcount/lambda_capture_copy_ctor.rs @@ -88,7 +88,7 @@ fn main_0() -> i32 { }, || -> i32 { return (({ (*c.borrow()).copies } * 10) + { (*c.borrow()).moves }); - } + }, ))); assert!((({ (*f.borrow()).call() }) == 10)); let g: Value i32>> = Rc::new(RefCell::new((*f.borrow()).copy_from())); @@ -105,7 +105,7 @@ fn main_0() -> i32 { }, || -> Counted { return Counted::copy_from({ c.as_pointer() }); - } + }, ) .call() }) @@ -127,7 +127,7 @@ fn main_0() -> i32 { return ({ (*arr.borrow())[(0) as usize].copies } + { (*arr.borrow())[(1) as usize].copies }); - } + }, ))); assert!((({ (*a.borrow()).call() }) == 2)); let a2: Value i32>> = Rc::new(RefCell::new((*a.borrow()).copy_from())); @@ -139,7 +139,7 @@ fn main_0() -> i32 { { let d: Value = Rc::new(RefCell::new(Dropped::new())); }, - || {} + || {}, ))); let _dtor_m = ScopedDestructor::new(&m, |__p| __p.with(|__f| __f.destroy())); let m2: Value> = Rc::new(RefCell::new((*m.borrow()).move_from())); @@ -151,7 +151,7 @@ fn main_0() -> i32 { { let d: Value = Rc::new(RefCell::new(Dropped::new())); }, - || {} + || {}, ))); let _dtor_k = ScopedDestructor::new(&k, |__p| __p.with(|__f| __f.destroy())); let k2: Value> = Rc::new(RefCell::new((*k.borrow()).copy_from())); @@ -163,7 +163,7 @@ fn main_0() -> i32 { { let d: Value = Rc::new(RefCell::new(Dropped::new())); }, - || {} + || {}, ))); let _dtor_inner = ScopedDestructor::new(&inner, |__p| __p.with(|__f| __f.destroy())); let outer: Value> = Rc::new(RefCell::new(lambda!( @@ -171,7 +171,7 @@ fn main_0() -> i32 { let inner: Value> = Rc::new(RefCell::new((*inner.borrow()).copy_from())); }, - || {} + || {}, ))); let _dtor_outer = ScopedDestructor::new(&outer, |__p| __p.with(|__f| __f.destroy())); } diff --git a/tests/unit/out/refcount/lambda_capture_implicit.rs b/tests/unit/out/refcount/lambda_capture_implicit.rs index 4f287e427..b2e834aa5 100644 --- a/tests/unit/out/refcount/lambda_capture_implicit.rs +++ b/tests/unit/out/refcount/lambda_capture_implicit.rs @@ -22,7 +22,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return ((((*a.borrow()) + (*b.borrow())) + (*c.borrow())) + x); - } + }, ))); assert!((({ (*by_value.borrow()).call(10,) }) == 16)); (*a.borrow_mut()) = 100; @@ -35,7 +35,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return ((((a.read()) + (b.read())) + (c.read())) + x); - } + }, ))); assert!((({ (*by_ref.borrow()).call(10,) }) == 115)); (*b.borrow_mut()) = 200; @@ -52,7 +52,7 @@ fn main_0() -> i32 { c.with_mut(|__v| *__v = *__v + __rhs) }; return (((*a.borrow()) + (*b.borrow())) + (c.read())); - } + }, ))); assert!((({ (*mixed.borrow()).call(1,) }) == ((100 + 200) + 4))); assert!(((*c.borrow()) == 4)); diff --git a/tests/unit/out/refcount/lambda_capture_library_types.rs b/tests/unit/out/refcount/lambda_capture_library_types.rs index be1be47d0..79ea3b25a 100644 --- a/tests/unit/out/refcount/lambda_capture_library_types.rs +++ b/tests/unit/out/refcount/lambda_capture_library_types.rs @@ -18,7 +18,7 @@ fn main_0() -> i32 { }, || -> i32 { return ((*v.borrow()).len() as i32); - } + }, ))); let g: Value i32>> = Rc::new(RefCell::new((*f.borrow()).copy_from())); let h: Value i32>> = Rc::new(RefCell::new((*f.borrow()).move_from())); @@ -36,7 +36,7 @@ fn main_0() -> i32 { } else { 0 }; - } + }, ))); let q: Value i32>> = Rc::new(RefCell::new((*p.borrow()).move_from())); assert!((({ (*q.borrow()).call() }) == 5)); @@ -48,7 +48,7 @@ fn main_0() -> i32 { }, || -> i32 { return (*n.borrow_mut()).prefix_inc(); - } + }, ))); let outer: Value i32>> = Rc::new(RefCell::new(lambda!( { @@ -57,7 +57,7 @@ fn main_0() -> i32 { }, || -> i32 { return ({ (*inner.borrow()).call() }).clone(); - } + }, ))); assert!((({ (*outer.borrow()).call() }) == 1)); let outer2: Value i32>> = Rc::new(RefCell::new((*outer.borrow()).copy_from())); diff --git a/tests/unit/out/refcount/lambda_capture_ref.rs b/tests/unit/out/refcount/lambda_capture_ref.rs index 265efb0fa..4dbf1ff65 100644 --- a/tests/unit/out/refcount/lambda_capture_ref.rs +++ b/tests/unit/out/refcount/lambda_capture_ref.rs @@ -26,7 +26,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x + (base.read())); - } + }, ))); assert!((({ (*add_base.borrow()).call(5,) }) == 15)); (*base.borrow_mut()) = 100; @@ -38,7 +38,7 @@ fn main_0() -> i32 { }, || -> i32 { return (s.with(|__s| __s.x) + s.with(|__s| __s.y)); - } + }, ))); assert!((({ (*sum.borrow()).call() }) == 3)); (*s.borrow_mut()).x = 50; @@ -50,7 +50,7 @@ fn main_0() -> i32 { }, || { counter.with_mut(|__v| __v.postfix_inc()); - } + }, ))); ({ (*bump.borrow()).call() }); ({ (*bump.borrow()).call() }); @@ -64,7 +64,7 @@ fn main_0() -> i32 { let mut t: u16 = (elem!((arr), j).read()); elem!((arr), j).write({ (elem!((arr), i).read()) }); elem!((arr), i).write(t); - } + }, ))); ({ (*swap.borrow()).call(0_usize, 3_usize) }); assert!((((*arr.borrow())[(0) as usize] as i32) == 0)); @@ -79,7 +79,7 @@ fn main_0() -> i32 { let __rhs = { x }; t.with_mut(|__v| *__v = *__v + __rhs) }; - } + }, ))); ({ (*add.borrow()).call(2) }); ({ (*add.borrow()).call(3) }); @@ -90,7 +90,7 @@ fn main_0() -> i32 { }, |v: i32| { y.write({ v }); - } + }, ))); ({ (*set_y.borrow()).call(9) }); assert!(({ (*s.borrow()).y } == 9)); diff --git a/tests/unit/out/refcount/lambda_capture_star_this.rs b/tests/unit/out/refcount/lambda_capture_star_this.rs index 53bf2be9d..58a6959fd 100644 --- a/tests/unit/out/refcount/lambda_capture_star_this.rs +++ b/tests/unit/out/refcount/lambda_capture_star_this.rs @@ -46,7 +46,7 @@ impl SImpl for Ptr { field!(this_.as_pointer(), n).with_mut(|__v| *__v = *__v + 10) }; return this_.as_pointer().with(|__s| __s.n); - } + }, ))); let mut r: i32 = ({ (*f.borrow()).call() }).clone(); return ((r * 100) + (*self).with(|__s| __s.n)); @@ -58,7 +58,7 @@ impl SImpl for Ptr { }, || -> i32 { return ({ SImpl::twice(&this_.as_pointer()) }); - } + }, ))); field!((*self), n).write(99); return ({ (*f.borrow()).call() }).clone(); @@ -72,7 +72,7 @@ impl SImpl for Ptr { }, || -> i32 { return (this_.as_pointer().with(|__s| __s.n) + (*k.borrow())); - } + }, ))); field!((*self), n).write(0); return ({ (*f.borrow()).call() }).clone(); diff --git a/tests/unit/out/refcount/lambda_capture_this.rs b/tests/unit/out/refcount/lambda_capture_this.rs index 1d310cb29..1e601a364 100644 --- a/tests/unit/out/refcount/lambda_capture_this.rs +++ b/tests/unit/out/refcount/lambda_capture_this.rs @@ -54,7 +54,7 @@ impl SImpl for Ptr { let __rhs = k; field!((*this_.borrow()).clone(), n).with_mut(|__v| *__v = *__v + __rhs) }; - } + }, ))); ({ (*inc.borrow()).call(by) }); ({ (*inc.borrow()).call(by) }); @@ -66,7 +66,7 @@ impl SImpl for Ptr { }, |k: i32| { ({ SImpl::add(&(*this_.borrow()).clone(), k) }); - } + }, ))); ({ (*inc.borrow()).call(by) }); } @@ -77,7 +77,7 @@ impl SImpl for Ptr { }, || -> i32 { return ({ SImpl::scaled(&(*this_.borrow()).clone()) }); - } + }, ))); return ({ (*get.borrow()).call() }).clone(); } diff --git a/tests/unit/out/refcount/lambda_capture_value.rs b/tests/unit/out/refcount/lambda_capture_value.rs index a2d060a01..666f9a1b7 100644 --- a/tests/unit/out/refcount/lambda_capture_value.rs +++ b/tests/unit/out/refcount/lambda_capture_value.rs @@ -29,7 +29,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x * (*factor.borrow())); - } + }, ))); assert!((({ (*scale.borrow()).call(4,) }) == 12)); (*factor.borrow_mut()) = 100; @@ -42,7 +42,7 @@ fn main_0() -> i32 { }, || -> i32 { return ((*p.borrow()).read()); - } + }, ))); (*slot.borrow_mut()) = 8; assert!((({ (*read_ptr.borrow()).call() }) == 8)); @@ -53,7 +53,7 @@ fn main_0() -> i32 { }, || -> i32 { return ({ (*s.borrow()).x } + { (*s.borrow()).y }); - } + }, ))); (*s.borrow_mut()).x = 50; assert!((({ (*sum.borrow()).call() }) == 3)); @@ -64,7 +64,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x + (*y.borrow())); - } + }, ))); assert!((({ (*shifted.borrow()).call(5,) }) == 16)); let k: Value = Rc::new(RefCell::new(3)); @@ -74,7 +74,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x + 3); - } + }, ))); assert!((({ (*by_copy.borrow()).call(1,) }) == 4)); let by_copy_used: Value i32>> = Rc::new(RefCell::new(lambda!( @@ -83,7 +83,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x + ({ read_0(k.as_pointer()) })); - } + }, ))); assert!((({ (*by_copy_used.borrow()).call(1,) }) == 4)); let implicit_used: Value i32>> = Rc::new(RefCell::new(lambda!( @@ -92,7 +92,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x + ({ read_0(k.as_pointer()) })); - } + }, ))); assert!((({ (*implicit_used.borrow()).call(1,) }) == 4)); let by_ref: Value i32>> = Rc::new(RefCell::new(lambda!( @@ -101,7 +101,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x + 3); - } + }, ))); assert!((({ (*by_ref.borrow()).call(1,) }) == 4)); return 0; diff --git a/tests/unit/out/refcount/lambda_generic.rs b/tests/unit/out/refcount/lambda_generic.rs new file mode 100644 index 000000000..672c5b9c0 --- /dev/null +++ b/tests/unit/out/refcount/lambda_generic.rs @@ -0,0 +1,104 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let twice: Value> = Rc::new(RefCell::new(lambda!( + Generic, + {}, + |x: i32| -> i32 { + return (x + x); + }, + |x: f64| -> f64 { + return (x + x); + }, + ))); + assert!((({ (*twice.borrow()).spec:: i32>().call(4,) }) == 8)); + assert!((({ (*twice.borrow()).spec:: f64>().call(1.5_f64,) }) == 3_f64)); + let base: Value = Rc::new(RefCell::new(10)); + let add_base: Value> = Rc::new(RefCell::new(lambda!( + Generic, + { + let base: Value = Rc::new(RefCell::new((*base.borrow()))); + }, + |x: i32| -> i32 { + return (x + (*base.borrow())); + }, + |x: f64| -> f64 { + return (x + ((*base.borrow()) as f64)); + }, + ))); + assert!((({ (*add_base.borrow()).spec:: i32>().call(5,) }) == 15)); + assert!((({ (*add_base.borrow()).spec:: f64>().call(2.5_f64,) }) == 12.5_f64)); + let total: Value = Rc::new(RefCell::new(0)); + let accumulate: Value> = Rc::new(RefCell::new(lambda!( + Generic, + { + let total: Ptr = total.as_pointer(); + }, + |x: i32, y: i32| { + { + let __rhs = (x * y); + total.with_mut(|__v| *__v = *__v + __rhs) + }; + }, + |x: u32, y: u32| { + total.write({ (((total.read()) as u32).wrapping_add((x).wrapping_mul(y))) as i32 }); + }, + ))); + ({ (*accumulate.borrow()).spec::().call(2, 3) }); + ({ + (*accumulate.borrow()) + .spec::() + .call(4_u32, 5_u32) + }); + assert!(((*total.borrow()) == 26)); + let sub: Value> = Rc::new(RefCell::new(lambda!( + Generic, + {}, + |x: i32, y: i32| -> i32 { + return (x - y); + }, + |x: f64, y: f64| -> f64 { + return (x - y); + }, + ))); + assert!((({ (*sub.borrow()).spec:: i32>().call(9, 4,) }) == 5)); + assert!( + (({ + (*sub.borrow()) + .spec:: f64>() + .call(2.5_f64, 1_f64) + }) == 1.5_f64) + ); + let mixed: Value> = Rc::new(RefCell::new(lambda!( + Generic, + { + let base: Value = Rc::new(RefCell::new((*base.borrow()))); + }, + |x: i32, y: i32| -> i32 { + return ((x * y) + (*base.borrow())); + }, + |x: i32, y: f64| -> f64 { + return (((x as f64) * y) + ((*base.borrow()) as f64)); + }, + ))); + assert!((({ (*mixed.borrow()).spec:: i32>().call(2, 3,) }) == 16)); + assert!( + (({ + (*mixed.borrow()) + .spec:: f64>() + .call(2, 0.5_f64) + }) == 11_f64) + ); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/lambda_generic_to_fn_ptr.rs b/tests/unit/out/refcount/lambda_generic_to_fn_ptr.rs new file mode 100644 index 000000000..4ecc8b962 --- /dev/null +++ b/tests/unit/out/refcount/lambda_generic_to_fn_ptr.rs @@ -0,0 +1,44 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let negate: Value> = Rc::new(RefCell::new(lambda!( + Generic, + {}, + |x: i32| -> i32 { + return -x; + }, + |x: f64| -> f64 { + return -x; + }, + ))); + let mut fi: FnPtr i32> = (*negate.borrow()).clone().spec:: i32>(); + let mut fd: FnPtr f64> = (*negate.borrow()).clone().spec:: f64>(); + assert!((({ fi.call(3,) }) == -3_i32)); + assert!((({ fd.call(1.5_f64,) }) == -1.5_f64)); + let square: Value> = Rc::new(RefCell::new(lambda!( + Generic, + {}, + |x: i32| -> i32 { + return (x * x); + }, + |x: f64| -> f64 { + return (x * x); + }, + ))); + let mut si: FnPtr i32> = (*square.borrow()).clone().spec:: i32>(); + let mut sd: FnPtr f64> = (*square.borrow()).clone().spec:: f64>(); + assert!((({ si.call(3,) }) == 9)); + assert!((({ sd.call(1.5_f64,) }) == 2.25_f64)); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/lambda_move_only_capture.rs b/tests/unit/out/refcount/lambda_move_only_capture.rs index fe42942ae..a2115dd3f 100644 --- a/tests/unit/out/refcount/lambda_move_only_capture.rs +++ b/tests/unit/out/refcount/lambda_move_only_capture.rs @@ -38,7 +38,7 @@ fn main_0() -> i32 { }, || -> i32 { return ({ (*h.borrow()).p.clone() }.read()); - } + }, ))); let _dtor_f = ScopedDestructor::new(&f, |__p| __p.with(|__f| __f.destroy())); assert!(({ (*o.borrow()).p.clone() }).is_null()); @@ -58,7 +58,7 @@ fn main_0() -> i32 { total.with_mut(|__v| *__v = *__v + __rhs) }; { (*h.borrow()).p.clone() }.write(0); - } + }, ))); let _dtor_consume = ScopedDestructor::new(&consume, |__p| __p.with(|__f| __f.destroy())); ({ (*consume.borrow()).call() }); @@ -89,7 +89,7 @@ impl OwnerImpl for Ptr { }, || -> i32 { return ({ (*self_.borrow()).p.clone() }.read()); - } + }, ); } } diff --git a/tests/unit/out/refcount/lambda_mutable.rs b/tests/unit/out/refcount/lambda_mutable.rs index 8222bd58d..56284ef24 100644 --- a/tests/unit/out/refcount/lambda_mutable.rs +++ b/tests/unit/out/refcount/lambda_mutable.rs @@ -18,7 +18,7 @@ fn main_0() -> i32 { }, || -> i32 { return (*start.borrow_mut()).postfix_inc(); - } + }, ))); assert!((({ (*next.borrow()).call() }) == 5)); assert!((({ (*next.borrow()).call() }) == 6)); @@ -32,7 +32,7 @@ fn main_0() -> i32 { |x: i32| -> i32 { (*total.borrow_mut()) += x; return (*total.borrow()); - } + }, ))); assert!((({ (*accumulate.borrow()).call(1,) }) == 1)); assert!((({ (*accumulate.borrow()).call(2,) }) == 3)); diff --git a/tests/unit/out/refcount/lambda_nested.rs b/tests/unit/out/refcount/lambda_nested.rs index 819a1efa7..e097aec70 100644 --- a/tests/unit/out/refcount/lambda_nested.rs +++ b/tests/unit/out/refcount/lambda_nested.rs @@ -31,10 +31,10 @@ fn main_0() -> i32 { }, |z: i32| -> i32 { return (((x.read()) + (*y.borrow())) + z); - } + }, ))); return ({ (*inner.borrow()).call(1) }); - } + }, ))); assert!((({ (*outer.borrow()).call(20,) }) == 31)); (*x.borrow_mut()) = 100; @@ -61,10 +61,10 @@ impl SImpl for Ptr { }, |z: i32| -> i32 { return (((*this_.borrow()).clone().with(|__s| __s.v) + (*y.borrow())) + z); - } + }, ))); return ({ (*inner.borrow()).call(1) }); - } + }, ))); return ({ (*outer.borrow()).call(20) }); } diff --git a/tests/unit/out/refcount/lambda_self_recursive.rs b/tests/unit/out/refcount/lambda_self_recursive.rs new file mode 100644 index 000000000..6bb0cddda --- /dev/null +++ b/tests/unit/out/refcount/lambda_self_recursive.rs @@ -0,0 +1,104 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let fact: Value> = + Rc::new(RefCell::new(lambda!(Generic, {}, |self_: FnPtr< + Generic, + >, + n: i32| + -> i32 { + let self_: Value> = Rc::new(RefCell::new(self_)); + if (n <= 1) { + return 1; + } + return (n + * ({ + let _self_: FnPtr = (*self_.borrow()).clone(); + (*self_.borrow()) + .spec::, i32) -> i32>() + .call(_self_, (n - 1)) + })); + },))); + assert!( + (({ + let _self_: FnPtr = (*fact.borrow()).clone(); + (*fact.borrow()) + .spec::, i32) -> i32>() + .call(_self_, 5) + }) == 120) + ); + let calls: Value = Rc::new(RefCell::new(0)); + let fib: Value> = Rc::new(RefCell::new(lambda!( + Generic, + { + let calls: Ptr = calls.as_pointer(); + }, + |self_: Ptr>, n: i32| -> i32 { + calls.with_mut(|__v| __v.postfix_inc()); + if (n <= 2) { + return 1; + } + return (({ + let _self_: Ptr> = (self_).clone(); + let _n: i32 = (n - 1); + (*self_.upgrade().deref()) + .spec::>, i32) -> i32>() + .call(_self_, _n) + }) + ({ + let _self_: Ptr> = (self_).clone(); + let _n: i32 = (n - 2); + (*self_.upgrade().deref()) + .spec::>, i32) -> i32>() + .call(_self_, _n) + })); + }, + ))); + assert!( + (({ + let _self_: Ptr> = fib.as_pointer(); + (*fib.borrow()) + .spec::>, i32) -> i32>() + .call(_self_, 6) + }) == 8) + ); + assert!(((*calls.borrow()) == 15)); + let depth: Value = Rc::new(RefCell::new(0)); + let count_down: Value> = Rc::new(RefCell::new(lambda!( + Generic, + { + let depth: Ptr = depth.as_pointer(); + }, + |self_: Ptr>, n: i32| { + if (n == 0) { + return; + } + depth.with_mut(|__v| __v.postfix_inc()); + ({ + let _self_: Ptr> = (self_).clone(); + let _n: i32 = (n - 1); + (*self_.upgrade().deref()) + .spec::>, i32)>() + .call(_self_, _n) + }); + }, + ))); + ({ + let _self_: Ptr> = count_down.as_pointer(); + (*count_down.borrow()) + .spec::>, i32)>() + .call(_self_, 4) + }); + assert!(((*depth.borrow()) == 4)); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/unboxed_locals.rs b/tests/unit/out/refcount/unboxed_locals.rs index 2ad5f6dcc..59178cde6 100644 --- a/tests/unit/out/refcount/unboxed_locals.rs +++ b/tests/unit/out/refcount/unboxed_locals.rs @@ -85,7 +85,7 @@ fn main_0() -> i32 { }, || -> i32 { return (captured.read()); - } + }, ))); (*captured.borrow_mut()) = 8; assert!((({ (*get.borrow()).call() }) == 8)); diff --git a/tests/unit/out/unsafe/lambda_as_template_argument.rs b/tests/unit/out/unsafe/lambda_as_template_argument.rs new file mode 100644 index 000000000..0e433f74d --- /dev/null +++ b/tests/unit/out/unsafe/lambda_as_template_argument.rs @@ -0,0 +1,102 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn apply_int_0(mut fn_: FnPtr i32>, mut x: i32) -> i32 { + return (unsafe { fn_.call(x) }); +} +pub unsafe fn apply_int_1(mut fn_: FnPtr, mut x: i32) -> i32 { + return (unsafe { fn_.spec:: i32>().call(x) }); +} +pub unsafe fn apply_int_2(mut fn_: FnPtr, mut x: i32) -> i32 { + return (unsafe { fn_.spec:: i32>().call(x) }); +} +pub unsafe fn apply_int_3(mut fn_: FnPtr, mut x: i32) -> i32 { + return (unsafe { fn_.spec:: i32>().call(x) }); +} +pub unsafe fn apply_double_4(mut fn_: FnPtr, mut x: f64) -> f64 { + return (unsafe { fn_.spec:: f64>().call(x) }); +} +pub unsafe fn apply_double_5(mut fn_: FnPtr, mut x: f64) -> f64 { + return (unsafe { fn_.spec:: f64>().call(x) }); +} +pub unsafe fn apply_twice_6(mut fn_: FnPtr i32>, mut x: i32) -> i32 { + return (unsafe { + let _x: i32 = (unsafe { fn_.call(x) }); + fn_.call(_x) + }); +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut factor: i32 = 3; + let mut scale: FnPtr i32> = lambda_unsafe!( + { + let factor: i32 = factor; + }, + |x: i32| -> i32 { + return ((x) * (factor)); + }, + ); + assert!(((unsafe { apply_twice_6(scale.copy_from(), 4,) }) == (36))); + assert!( + ((unsafe { + apply_int_0( + FnPtr:: i32>::new(|x: i32| -> i32 { + unsafe { + return -x; + } + }), + 9, + ) + }) == (-9_i32)) + ); + let mut generic_scale: FnPtr = lambda_unsafe!( + Generic, + { + let factor: i32 = factor; + }, + |x: i32| -> i32 { + return ((x) * (factor)); + }, + |x: f64| -> f64 { + return ((x) * (factor as f64)); + }, + ); + assert!(((unsafe { apply_int_1(generic_scale.copy_from(), 4,) }) == (12))); + assert!(((unsafe { apply_double_4(generic_scale.copy_from(), 1.5_f64,) }) == (4.5_f64))); + assert!( + ((unsafe { + apply_int_2( + lambda_unsafe!(Generic, {}, |x: i32| -> i32 { + return -x; + },), + 9, + ) + }) == (-9_i32)) + ); + let mut offset: FnPtr = lambda_unsafe!( + Generic, + { + let factor: i32 = factor; + }, + |x: i32| -> i32 { + return ((x) + (factor)); + }, + |x: f64| -> f64 { + return ((x) + (factor as f64)); + }, + ); + assert!(((unsafe { apply_int_3(offset.copy_from(), 4,) }) == (7))); + assert!(((unsafe { apply_double_5(offset.copy_from(), 1.5_f64,) }) == (4.5_f64))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/lambda_capture_copy_ctor.rs b/tests/unit/out/unsafe/lambda_capture_copy_ctor.rs index c8a093317..33ad5686a 100644 --- a/tests/unit/out/unsafe/lambda_capture_copy_ctor.rs +++ b/tests/unit/out/unsafe/lambda_capture_copy_ctor.rs @@ -90,7 +90,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (((c.copies) * (10)) + (c.moves)); - } + }, ); assert!(((unsafe { f.call() }) == (10))); let mut g: FnPtr i32> = f.copy_from(); @@ -105,7 +105,7 @@ unsafe fn main_0() -> i32 { }, || -> Counted { return Counted::copy_from({ &c }); - } + }, ) .call() }) @@ -119,7 +119,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return ((arr[(0) as usize].copies) + (arr[(1) as usize].copies)); - } + }, ); assert!(((unsafe { a.call() }) == (2))); let mut a2: FnPtr i32> = a.copy_from(); @@ -131,7 +131,7 @@ unsafe fn main_0() -> i32 { { let d: Dropped = Dropped::new(); }, - || {} + || {}, ); let _dtor_m = ScopedDestructorUnsafe::new(&raw mut m, |__f| __f.destroy()); let mut m2: FnPtr = m.move_from(); @@ -143,7 +143,7 @@ unsafe fn main_0() -> i32 { { let d: Dropped = Dropped::new(); }, - || {} + || {}, ); let _dtor_k = ScopedDestructorUnsafe::new(&raw mut k, |__f| __f.destroy()); let mut k2: FnPtr = k.copy_from(); @@ -155,14 +155,14 @@ unsafe fn main_0() -> i32 { { let d: Dropped = Dropped::new(); }, - || {} + || {}, ); let _dtor_inner = ScopedDestructorUnsafe::new(&raw mut inner, |__f| __f.destroy()); let mut outer: FnPtr = lambda_unsafe!( { let inner: FnPtr = inner.copy_from(); }, - || {} + || {}, ); let _dtor_outer = ScopedDestructorUnsafe::new(&raw mut outer, |__f| __f.destroy()); } diff --git a/tests/unit/out/unsafe/lambda_capture_implicit.rs b/tests/unit/out/unsafe/lambda_capture_implicit.rs index b6c4ed0d8..f3303778d 100644 --- a/tests/unit/out/unsafe/lambda_capture_implicit.rs +++ b/tests/unit/out/unsafe/lambda_capture_implicit.rs @@ -24,7 +24,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((((a) + (b)) + (c)) + (x)); - } + }, ); assert!(((unsafe { by_value.call(10,) }) == (16))); a = 100; @@ -37,7 +37,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((((*a) + (*b)) + (*c)) + (x)); - } + }, ); assert!(((unsafe { by_ref.call(10,) }) == (115))); b = 200; @@ -51,7 +51,7 @@ unsafe fn main_0() -> i32 { |x: i32| -> i32 { (*c) += x; return (((a) + (b)) + (*c)); - } + }, ); assert!(((unsafe { mixed.call(1,) }) == (((100) + (200)) + (4)))); assert!(((c) == (4))); diff --git a/tests/unit/out/unsafe/lambda_capture_library_types.rs b/tests/unit/out/unsafe/lambda_capture_library_types.rs index ebdf8087c..e46730e86 100644 --- a/tests/unit/out/unsafe/lambda_capture_library_types.rs +++ b/tests/unit/out/unsafe/lambda_capture_library_types.rs @@ -20,7 +20,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (v.len() as i32); - } + }, ); let mut g: FnPtr i32> = f.copy_from(); let mut h: FnPtr i32> = f.move_from(); @@ -43,7 +43,7 @@ unsafe fn main_0() -> i32 { } else { 0 }; - } + }, ); let mut q: FnPtr i32> = p.move_from(); assert!(((unsafe { q.call() }) == (5))); @@ -55,7 +55,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return n.prefix_inc(); - } + }, ); let mut outer: FnPtr i32> = lambda_unsafe!( { @@ -63,7 +63,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (unsafe { inner.call() }); - } + }, ); assert!(((unsafe { outer.call() }) == (1))); let mut outer2: FnPtr i32> = outer.copy_from(); diff --git a/tests/unit/out/unsafe/lambda_capture_ref.rs b/tests/unit/out/unsafe/lambda_capture_ref.rs index 89e896634..cefa6eb20 100644 --- a/tests/unit/out/unsafe/lambda_capture_ref.rs +++ b/tests/unit/out/unsafe/lambda_capture_ref.rs @@ -26,7 +26,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) + (*base)); - } + }, ); assert!(((unsafe { add_base.call(5,) }) == (15))); base = 100; @@ -38,7 +38,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (((*s).x) + ((*s).y)); - } + }, ); assert!(((unsafe { sum.call() }) == (3))); s.x = 50; @@ -50,7 +50,7 @@ unsafe fn main_0() -> i32 { }, || { (*counter).postfix_inc(); - } + }, ); (unsafe { bump.call() }); (unsafe { bump.call() }); @@ -64,7 +64,7 @@ unsafe fn main_0() -> i32 { let mut t: u16 = (*arr)[(j)]; (*arr)[(j)] = (*arr)[(i)]; (*arr)[(i)] = t; - } + }, ); (unsafe { swap.call(0_usize, 3_usize) }); assert!(((arr[(0) as usize] as i32) == (0))); @@ -76,7 +76,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| { (*t) += x; - } + }, ); (unsafe { add.call(2) }); (unsafe { add.call(3) }); @@ -87,7 +87,7 @@ unsafe fn main_0() -> i32 { }, |v: i32| { (*y) = v; - } + }, ); (unsafe { set_y.call(9) }); assert!(((s.y) == (9))); diff --git a/tests/unit/out/unsafe/lambda_capture_star_this.rs b/tests/unit/out/unsafe/lambda_capture_star_this.rs index c31f5fc68..b8948c736 100644 --- a/tests/unit/out/unsafe/lambda_capture_star_this.rs +++ b/tests/unit/out/unsafe/lambda_capture_star_this.rs @@ -23,7 +23,7 @@ impl S { || -> i32 { (*(&raw mut this_)).n += 10; return (*(&raw mut this_)).n; - } + }, ); let mut r: i32 = (unsafe { f.call() }); return (((r) * (100)) + (self.n)); @@ -35,7 +35,7 @@ impl S { }, || -> i32 { return (unsafe { S::twice(&(*(&raw mut this_))) }); - } + }, ); self.n = 99; return (unsafe { f.call() }); @@ -48,7 +48,7 @@ impl S { }, || -> i32 { return (((*(&raw mut this_)).n) + (k)); - } + }, ); self.n = 0; return (unsafe { f.call() }); diff --git a/tests/unit/out/unsafe/lambda_capture_this.rs b/tests/unit/out/unsafe/lambda_capture_this.rs index d54d64ec0..0d81fda54 100644 --- a/tests/unit/out/unsafe/lambda_capture_this.rs +++ b/tests/unit/out/unsafe/lambda_capture_this.rs @@ -26,7 +26,7 @@ impl S { }, |k: i32| { (*this_).n += k; - } + }, ); (unsafe { inc.call(by) }); (unsafe { inc.call(by) }); @@ -38,7 +38,7 @@ impl S { }, |k: i32| { (unsafe { S::add(&mut (*this_), k) }); - } + }, ); (unsafe { inc.call(by) }); } @@ -49,7 +49,7 @@ impl S { }, || -> i32 { return (unsafe { S::scaled(&(*this_)) }); - } + }, ); return (unsafe { get.call() }); } diff --git a/tests/unit/out/unsafe/lambda_capture_value.rs b/tests/unit/out/unsafe/lambda_capture_value.rs index 2cd64b629..b34880798 100644 --- a/tests/unit/out/unsafe/lambda_capture_value.rs +++ b/tests/unit/out/unsafe/lambda_capture_value.rs @@ -29,7 +29,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) * (factor)); - } + }, ); assert!(((unsafe { scale.call(4,) }) == (12))); factor = 100; @@ -42,7 +42,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (*p); - } + }, ); slot = 8; assert!(((unsafe { read_ptr.call() }) == (8))); @@ -53,7 +53,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return ((s.x) + (s.y)); - } + }, ); s.x = 50; assert!(((unsafe { sum.call() }) == (3))); @@ -64,7 +64,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) + (y)); - } + }, ); assert!(((unsafe { shifted.call(5,) }) == (16))); let k: i32 = 3; @@ -74,7 +74,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) + (3)); - } + }, ); assert!(((unsafe { by_copy.call(1,) }) == (4))); let mut by_copy_used: FnPtr i32> = lambda_unsafe!( @@ -83,7 +83,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) + (unsafe { read_0(&k) })); - } + }, ); assert!(((unsafe { by_copy_used.call(1,) }) == (4))); let mut implicit_used: FnPtr i32> = lambda_unsafe!( @@ -92,7 +92,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) + (unsafe { read_0(&k) })); - } + }, ); assert!(((unsafe { implicit_used.call(1,) }) == (4))); let mut by_ref: FnPtr i32> = lambda_unsafe!( @@ -101,7 +101,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) + (3)); - } + }, ); assert!(((unsafe { by_ref.call(1,) }) == (4))); return 0; diff --git a/tests/unit/out/unsafe/lambda_generic.rs b/tests/unit/out/unsafe/lambda_generic.rs new file mode 100644 index 000000000..4f67eee83 --- /dev/null +++ b/tests/unit/out/unsafe/lambda_generic.rs @@ -0,0 +1,87 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut twice: FnPtr = lambda_unsafe!( + Generic, + {}, + |x: i32| -> i32 { + return ((x) + (x)); + }, + |x: f64| -> f64 { + return ((x) + (x)); + }, + ); + assert!(((unsafe { twice.spec:: i32>().call(4,) }) == (8))); + assert!(((unsafe { twice.spec:: f64>().call(1.5_f64,) }) == (3_f64))); + let mut base: i32 = 10; + let mut add_base: FnPtr = lambda_unsafe!( + Generic, + { + let base: i32 = base; + }, + |x: i32| -> i32 { + return ((x) + (base)); + }, + |x: f64| -> f64 { + return ((x) + (base as f64)); + }, + ); + assert!(((unsafe { add_base.spec:: i32>().call(5,) }) == (15))); + assert!(((unsafe { add_base.spec:: f64>().call(2.5_f64,) }) == (12.5_f64))); + let mut total: i32 = 0; + let mut accumulate: FnPtr = lambda_unsafe!( + Generic, + { + let total: *mut i32 = &mut total; + }, + |x: i32, y: i32| { + (*total) += ((x) * (y)); + }, + |x: u32, y: u32| { + (*total) = (((*total) as u32).wrapping_add((x).wrapping_mul(y))) as i32; + }, + ); + (unsafe { accumulate.spec::().call(2, 3) }); + (unsafe { accumulate.spec::().call(4_u32, 5_u32) }); + assert!(((total) == (26))); + let mut sub: FnPtr = lambda_unsafe!( + Generic, + {}, + |x: i32, y: i32| -> i32 { + return ((x) - (y)); + }, + |x: f64, y: f64| -> f64 { + return ((x) - (y)); + }, + ); + assert!(((unsafe { sub.spec:: i32>().call(9, 4,) }) == (5))); + assert!(((unsafe { sub.spec:: f64>().call(2.5_f64, 1_f64,) }) == (1.5_f64))); + let mut mixed: FnPtr = lambda_unsafe!( + Generic, + { + let base: i32 = base; + }, + |x: i32, y: i32| -> i32 { + return (((x) * (y)) + (base)); + }, + |x: i32, y: f64| -> f64 { + return (((x as f64) * (y)) + (base as f64)); + }, + ); + assert!(((unsafe { mixed.spec:: i32>().call(2, 3,) }) == (16))); + assert!(((unsafe { mixed.spec:: f64>().call(2, 0.5_f64,) }) == (11_f64))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/lambda_generic_to_fn_ptr.rs b/tests/unit/out/unsafe/lambda_generic_to_fn_ptr.rs new file mode 100644 index 000000000..5bfe3e66d --- /dev/null +++ b/tests/unit/out/unsafe/lambda_generic_to_fn_ptr.rs @@ -0,0 +1,54 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut negate: FnPtr = lambda_unsafe!( + Generic, + {}, + |x: i32| -> i32 { + return -x; + }, + |x: f64| -> f64 { + return -x; + }, + ); + let mut fi: Option i32> = Some(|x: i32| -> i32 { + return -x; + }); + let mut fd: Option f64> = Some(|x: f64| -> f64 { + return -x; + }); + assert!(((unsafe { (fi).unwrap()(3,) }) == (-3_i32))); + assert!(((unsafe { (fd).unwrap()(1.5_f64,) }) == (-1.5_f64))); + let mut square: FnPtr = lambda_unsafe!( + Generic, + {}, + |x: i32| -> i32 { + return ((x) * (x)); + }, + |x: f64| -> f64 { + return ((x) * (x)); + }, + ); + let mut si: Option i32> = Some(|x: i32| -> i32 { + return ((x) * (x)); + }); + let mut sd: Option f64> = Some(|x: f64| -> f64 { + return ((x) * (x)); + }); + assert!(((unsafe { (si).unwrap()(3,) }) == (9))); + assert!(((unsafe { (sd).unwrap()(1.5_f64,) }) == (2.25_f64))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/lambda_move_only_capture.rs b/tests/unit/out/unsafe/lambda_move_only_capture.rs index 1d16cf92b..ed0d87186 100644 --- a/tests/unit/out/unsafe/lambda_move_only_capture.rs +++ b/tests/unit/out/unsafe/lambda_move_only_capture.rs @@ -38,7 +38,7 @@ impl Owner { }, || -> i32 { return (*self_.p); - } + }, ); } } @@ -57,7 +57,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (*h.p); - } + }, ); let _dtor_f = ScopedDestructorUnsafe::new(&raw mut f, |__f| __f.destroy()); assert!((o.p).is_null()); @@ -74,7 +74,7 @@ unsafe fn main_0() -> i32 { || { (*total) += (*h.p); (*h.p) = 0; - } + }, ); let _dtor_consume = ScopedDestructorUnsafe::new(&raw mut consume, |__f| __f.destroy()); (unsafe { consume.call() }); diff --git a/tests/unit/out/unsafe/lambda_mutable.rs b/tests/unit/out/unsafe/lambda_mutable.rs index b0ea9c84c..615031c8c 100644 --- a/tests/unit/out/unsafe/lambda_mutable.rs +++ b/tests/unit/out/unsafe/lambda_mutable.rs @@ -20,7 +20,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return start.postfix_inc(); - } + }, ); assert!(((unsafe { next.call() }) == (5))); assert!(((unsafe { next.call() }) == (6))); @@ -34,7 +34,7 @@ unsafe fn main_0() -> i32 { |x: i32| -> i32 { total += x; return total; - } + }, ); assert!(((unsafe { accumulate.call(1,) }) == (1))); assert!(((unsafe { accumulate.call(2,) }) == (3))); diff --git a/tests/unit/out/unsafe/lambda_nested.rs b/tests/unit/out/unsafe/lambda_nested.rs index dc19d51db..1561f7541 100644 --- a/tests/unit/out/unsafe/lambda_nested.rs +++ b/tests/unit/out/unsafe/lambda_nested.rs @@ -25,10 +25,10 @@ impl S { }, |z: i32| -> i32 { return ((((*this_).v) + (y)) + (z)); - } + }, ); return (unsafe { inner.call(1) }); - } + }, ); return (unsafe { outer.call(20) }); } @@ -53,10 +53,10 @@ unsafe fn main_0() -> i32 { }, |z: i32| -> i32 { return (((*x) + (y)) + (z)); - } + }, ); return (unsafe { inner.call(1) }); - } + }, ); assert!(((unsafe { outer.call(20,) }) == (31))); x = 100; diff --git a/tests/unit/out/unsafe/lambda_self_recursive.rs b/tests/unit/out/unsafe/lambda_self_recursive.rs new file mode 100644 index 000000000..c78cb9591 --- /dev/null +++ b/tests/unit/out/unsafe/lambda_self_recursive.rs @@ -0,0 +1,99 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut fact: FnPtr = + lambda_unsafe!(Generic, {}, |self_: FnPtr, n: i32| -> i32 { + if ((n) <= (1)) { + return 1; + } + return ((n) + * (unsafe { + let _self_: FnPtr = self_.clone(); + self_ + .spec::, i32) -> i32>() + .call(_self_, ((n) - (1))) + })); + },); + assert!( + ((unsafe { + let _self_: FnPtr = fact.clone(); + fact.spec::, i32) -> i32>() + .call(_self_, 5) + }) == (120)) + ); + let mut calls: i32 = 0; + let mut fib: FnPtr = lambda_unsafe!( + Generic, + { + let calls: *mut i32 = &mut calls; + }, + |self_: *mut FnPtr, n: i32| -> i32 { + (*calls).postfix_inc(); + if ((n) <= (2)) { + return 1; + } + return ((unsafe { + let _self_: *mut FnPtr = self_; + let _n: i32 = ((n) - (1)); + (*self_) + .spec::, i32) -> i32>() + .call(_self_, _n) + }) + (unsafe { + let _self_: *mut FnPtr = self_; + let _n: i32 = ((n) - (2)); + (*self_) + .spec::, i32) -> i32>() + .call(_self_, _n) + })); + }, + ); + assert!( + ((unsafe { + let _self_: *mut FnPtr = &mut fib; + fib.spec::, i32) -> i32>() + .call(_self_, 6) + }) == (8)) + ); + assert!(((calls) == (15))); + let mut depth: i32 = 0; + let mut count_down: FnPtr = lambda_unsafe!( + Generic, + { + let depth: *mut i32 = &mut depth; + }, + |self_: *const FnPtr, n: i32| { + if ((n) == (0)) { + return; + } + (*depth).postfix_inc(); + (unsafe { + let _self_: *const FnPtr = self_; + let _n: i32 = ((n) - (1)); + (*self_) + .spec::, i32)>() + .call(_self_, _n) + }); + }, + ); + (unsafe { + let _self_: *const FnPtr = &count_down; + count_down + .spec::, i32)>() + .call(_self_, 4) + }); + assert!(((depth) == (4))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/unboxed_locals.rs b/tests/unit/out/unsafe/unboxed_locals.rs index 885ce0db3..427ab351e 100644 --- a/tests/unit/out/unsafe/unboxed_locals.rs +++ b/tests/unit/out/unsafe/unboxed_locals.rs @@ -84,7 +84,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (*captured); - } + }, ); captured = 8; assert!(((unsafe { get.call() }) == (8))); From 77a948323c671cea40daf84ce7ecd412d7a13c6c Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 9 Oct 2026 09:33:35 +0100 Subject: [PATCH 2/6] Add library support for generic lambdas --- libcc2rs-macros/src/lambda.rs | 162 +++++++++++++++++++++++++++------- libcc2rs/src/fn_ptr.rs | 98 ++++++++++++++++++++ libcc2rs/src/lib.rs | 2 +- 3 files changed, 231 insertions(+), 31 deletions(-) diff --git a/libcc2rs-macros/src/lambda.rs b/libcc2rs-macros/src/lambda.rs index e5664c4b0..782797482 100644 --- a/libcc2rs-macros/src/lambda.rs +++ b/libcc2rs-macros/src/lambda.rs @@ -9,17 +9,38 @@ use syn::parse::{Parse, ParseStream}; use syn::{Block, Error, ExprClosure, Pat, Result, Stmt, Token, parse_macro_input}; struct Lambda { + is_generic: bool, captures: Block, - closure: ExprClosure, + closures: Vec, } impl Parse for Lambda { fn parse(input: ParseStream) -> Result { + let is_generic = input.peek(syn::Ident); + if is_generic { + let marker: Ident = input.parse()?; + if marker != "Generic" { + return Err(Error::new(marker.span(), "expected `Generic`")); + } + input.parse::()?; + } let captures = input.parse()?; input.parse::()?; - let closure = input.parse()?; - input.parse::>()?; - Ok(Lambda { captures, closure }) + let mut closures = vec![input.parse()?]; + while input.parse::>()?.is_some() && !input.is_empty() { + closures.push(input.parse()?); + } + if !is_generic && closures.len() != 1 { + return Err(Error::new_spanned( + &closures[1], + "a non-generic lambda has one closure", + )); + } + Ok(Lambda { + is_generic, + captures, + closures, + }) } } @@ -137,28 +158,49 @@ fn expand_lambda(lambda: Lambda, is_unsafe: bool) -> Result = names.iter().map(|name| name.to_string()).collect(); + let mut calls = Vec::new(); + let mut sigs = Vec::new(); + let mut call_names = Vec::new(); + for (i, closure) in lambda.closures.iter().enumerate() { + let mut params = Vec::new(); + let mut param_types = Vec::new(); + for input in &closure.inputs { + let Pat::Type(pat) = input else { + return Err(Error::new_spanned(input, "expected a typed parameter")); + }; + params.push(pat); + param_types.push(&pat.ty); + } + let output = &closure.output; + let body = &closure.body; + let body = rewrite_captures(quote! { #body }, &captured, false)?; + let (receiver, body) = if is_unsafe { + (quote! { &mut self }, quote! { unsafe { #body } }) + } else { + (quote! { &self }, body) }; - params.push(pat); - param_types.push(&pat.ty); + let call_name = if lambda.is_generic { + Ident::new(&format!("call_{i}"), proc_macro2::Span::call_site()) + } else { + Ident::new("call", proc_macro2::Span::call_site()) + }; + calls.push(quote! { + #[allow(unused_unsafe, clippy::too_many_arguments)] + fn #call_name(#receiver #(, #params)*) #output { + #body + } + }); + sigs.push(quote! { fn(#(#param_types),*) #output }); + call_names.push((call_name, closure.inputs.len())); } - - let output = &lambda.closure.output; - let body = &lambda.closure.body; - let captured = names.iter().map(|name| name.to_string()).collect(); - let body = rewrite_captures(quote! { #body }, &captured, false)?; // The copy and move constructors of the lambda copy and move each // capture, and its destructor destroys them in reverse order, as chosen // from their types by the traits in libcc2rs::__capture. let reversed: Vec<_> = names.iter().rev().collect(); - let (receiver, body, destroy, constructor, copy_from, move_from) = if is_unsafe { + let (receiver, destroy, constructor, copy_from, move_from) = if is_unsafe { ( quote! { &mut self }, - quote! { unsafe { #body } }, quote! { use ::libcc2rs::__capture::{DestroyNoneUnsafe as _, DestroyWithDtorUnsafe as _}; unsafe { @@ -192,7 +234,6 @@ fn expand_lambda(lambda: Lambda, is_unsafe: bool) -> Result Result Self { #copy_from @@ -239,12 +277,76 @@ fn expand_lambda(lambda: Lambda, is_unsafe: bool) -> Result::#constructor( - __Lambda { #(#names: #inits,)* }, - __Lambda::call, - __Lambda::copy_from, - __Lambda::move_from, - __Lambda::destroy, + }; + let lambda_init = quote! { __Lambda { #(#names: #inits,)* } }; + + if !lambda.is_generic { + let sig = &sigs[0]; + return Ok(quote! {{ + #lambda_struct + ::libcc2rs::FnPtr::<#sig>::#constructor( + #lambda_init, + __Lambda::call, + __Lambda::copy_from, + __Lambda::move_from, + __Lambda::destroy, + ) + }}); + } + + let mut specs = Vec::new(); + for (sig, (call_name, arity)) in sigs.iter().zip(&call_names) { + let args: Vec = (0..*arity) + .map(|i| Ident::new(&format!("__a{i}"), proc_macro2::Span::call_site())) + .collect(); + let call = if is_unsafe { + quote! { + |__l: &mut ::std::rc::Rc<::std::cell::UnsafeCell<__Lambda>> #(, #args)*| { + unsafe { &mut *__l.get() }.#call_name(#(#args),*) + } + } + } else { + quote! { + |__l: &::std::rc::Rc<__Lambda> #(, #args)*| __l.#call_name(#(#args),*) + } + }; + specs.push(quote! { + ::std::rc::Rc::new(::libcc2rs::FnPtr::<#sig>::#constructor( + ::std::rc::Rc::clone(__l), + #call, + |__l| ::std::rc::Rc::clone(__l), + |__l| ::std::rc::Rc::clone(__l), + |_| {}, + )) as ::std::rc::Rc + }); + } + let (shared, copy_from, move_from, destroy) = if is_unsafe { + ( + quote! { ::std::rc::Rc::new(::std::cell::UnsafeCell::new(#lambda_init)) }, + quote! { |__l| ::std::rc::Rc::new(::std::cell::UnsafeCell::new( + unsafe { &mut *__l.get() }.copy_from() + )) }, + quote! { |__l| ::std::rc::Rc::new(::std::cell::UnsafeCell::new( + unsafe { &mut *__l.get() }.move_from() + )) }, + quote! { |__l| unsafe { &mut *__l.get() }.destroy() }, + ) + } else { + ( + quote! { ::std::rc::Rc::new(#lambda_init) }, + quote! { |__l| ::std::rc::Rc::new(__l.copy_from()) }, + quote! { |__l| ::std::rc::Rc::new(__l.move_from()) }, + quote! { |__l| __l.destroy() }, + ) + }; + Ok(quote! {{ + #lambda_struct + ::libcc2rs::FnPtr::<::libcc2rs::Generic>::from_generic_lambda( + #shared, + |__l| vec![#(#specs),*], + #copy_from, + #move_from, + #destroy, ) }}) } diff --git a/libcc2rs/src/fn_ptr.rs b/libcc2rs/src/fn_ptr.rs index d2a84d958..1ae6c222d 100644 --- a/libcc2rs/src/fn_ptr.rs +++ b/libcc2rs/src/fn_ptr.rs @@ -60,6 +60,10 @@ trait Adapted: Any { } fn destroy(&self) {} + + fn specializations(&self) -> &[Rc] { + panic!("ub: not a generic lambda"); + } } impl Adapted for T { @@ -373,6 +377,100 @@ macro_rules! impl_fn_ptr_call { } impl_fn_ptr_call!(); +#[derive(Clone, Copy)] +pub struct Generic; + +impl FnSig for Generic { + type Args = (); + type Ret = (); + fn fn_addr(&self) -> usize { + panic!("ub: a generic lambda has no single function address"); + } + fn call_direct(self, _args: ()) { + panic!("ub: calling a generic lambda without a signature"); + } +} + +struct GenericLambda { + captures: Captures, + specializations: Vec>, + make_specializations: fn(&Captures) -> Vec>, + copy_from: fn(&Captures) -> Captures, + move_from: fn(&Captures) -> Captures, + destroy: fn(&Captures), +} + +impl GenericLambda { + fn with_captures(&self, captures: Captures) -> Rc { + Rc::new(GenericLambda { + specializations: (self.make_specializations)(&captures), + captures, + make_specializations: self.make_specializations, + copy_from: self.copy_from, + move_from: self.move_from, + destroy: self.destroy, + }) + } +} + +impl Adapted for GenericLambda { + fn call_adapted(&self, _args: ArgList) -> ArgRepr { + panic!("ub: calling a generic lambda without a signature"); + } + + fn copy_from(&self) -> Option> { + Some(self.with_captures((self.copy_from)(&self.captures))) + } + + fn move_from(&self) -> Option> { + Some(self.with_captures((self.move_from)(&self.captures))) + } + + fn destroy(&self) { + (self.destroy)(&self.captures) + } + + fn specializations(&self) -> &[Rc] { + &self.specializations + } +} + +impl FnPtr { + pub fn from_generic_lambda( + captures: Captures, + make_specializations: fn(&Captures) -> Vec>, + copy_from: fn(&Captures) -> Captures, + move_from: fn(&Captures) -> Captures, + destroy: fn(&Captures), + ) -> Self { + let lambda: Rc = Rc::new(GenericLambda { + specializations: make_specializations(&captures), + captures, + make_specializations, + copy_from, + move_from, + destroy, + }); + FnPtr { + addr: Rc::as_ptr(&lambda) as *const () as usize, + current: None, + original: Some(lambda), + } + } + + pub fn spec(&self) -> FnPtr { + assert!(!self.is_null(), "ub: null fn pointer call"); + self.original + .as_ref() + .unwrap() + .specializations() + .iter() + .find_map(|spec| spec.downcast_ref::>()) + .expect("ub: calling through incompatible fn pointer type") + .clone() + } +} + impl Clone for FnPtr { fn clone(&self) -> Self { FnPtr { diff --git a/libcc2rs/src/lib.rs b/libcc2rs/src/lib.rs index b95481870..d7ae29fa1 100644 --- a/libcc2rs/src/lib.rs +++ b/libcc2rs/src/lib.rs @@ -35,7 +35,7 @@ mod fn_ptr_arg; pub use fn_ptr_arg::{ArgRepr, FnPtrArg, record_from_repr}; mod fn_ptr; -pub use fn_ptr::FnPtr; +pub use fn_ptr::{FnPtr, Generic}; mod capture; pub use capture::{Destructor, DestructorUnsafe, MoveCtor, MoveCtorUnsafe}; From 1e9cc14ae8b4143b208a535331d35d52eeff5721 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 9 Oct 2026 09:37:07 +0100 Subject: [PATCH 3/6] ADd converter support for lambda generic --- cpp2rust/converter/converter.cpp | 68 ++++++++++++++----- cpp2rust/converter/converter.h | 12 +++- cpp2rust/converter/converter_lib.cpp | 40 +++++++++++ cpp2rust/converter/converter_lib.h | 7 ++ .../converter/models/converter_refcount.cpp | 20 ++++-- .../converter/models/converter_refcount.h | 5 +- 6 files changed, 124 insertions(+), 28 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index fd404b357..11fbc4a2e 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -170,6 +170,10 @@ bool Converter::VisitBuiltinType(clang::BuiltinType *type) { bool Converter::VisitRecordType(clang::RecordType *type) { auto *decl = type->getDecl(); if (auto lambda = AsLambdaClass(clang::QualType(type, 0))) { + if (lambda->isGenericLambda()) { + StrCat("FnPtr"); + return false; + } auto proto = lambda->getLambdaCallOperator() ->getType() ->castAs(); @@ -1877,7 +1881,8 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) { expr->getCalleeDecl()); conversion && conversion->getParent()->isLambda()) { ConvertLambdaToFunctionPointer(clang::cast(expr) - ->getImplicitObjectArgument()); + ->getImplicitObjectArgument(), + conversion); return false; } @@ -1958,16 +1963,30 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) { return false; } -void Converter::ConvertLambdaToFunctionPointer(clang::Expr *lambda) { +void Converter::ConvertLambdaToFunctionPointer( + clang::Expr *lambda, const clang::CXXConversionDecl *conversion) { StrCat("Some"); PushParen paren(*this); - ConvertLambdaClosure(AsLambdaClass(lambda->getType())); + ConvertLambdaClosure(AsLambdaClass(lambda->getType()), + AsLambdaCallOperator(conversion)); computed_expr_type_ = ComputedExprType::FreshPointer; } -void Converter::EmitFnPtrCall(clang::Expr *callee) { - if (AsLambdaClass(callee->getType())) { - StrCat(ConvertRValue(callee), ".call"); +void Converter::ConvertLambdaCall(clang::CallExpr *expr, + const clang::CXXRecordDecl *lambda) { + StrCat(ConvertRValue(GetCallee(expr))); + if (lambda->isGenericLambda()) { + auto call_operator = expr->getDirectCallee(); + auto proto = call_operator->getType()->castAs(); + StrCat(std::format(".spec::<{}>()", ConvertFunctionPointerType(proto))); + } + StrCat(".call"); +} + +void Converter::EmitFnPtrCall(clang::CallExpr *expr) { + auto callee = GetCallee(expr); + if (auto lambda = AsLambdaClass(callee->getType())) { + ConvertLambdaCall(expr, lambda); return; } { @@ -2014,8 +2033,9 @@ Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) { auto callee = GetCallee(expr); unsigned arg_begin = 0; if (auto op_call = llvm::dyn_cast(expr)) { - if (clang::isa_and_nonnull( - op_call->getDirectCallee())) { + if (auto method = clang::dyn_cast_or_null( + op_call->getDirectCallee()); + method && !method->isExplicitObjectMemberFunction()) { arg_begin = 1; } } @@ -2221,7 +2241,7 @@ void Converter::EmitCall(CallInfo &&info) { EmitHoistedArgs(info); if (info.is_fn_ptr_call) { - EmitFnPtrCall(GetCallee(info.expr)); + EmitFnPtrCall(info.expr); } else if (info.is_libc_passthrough) { auto *direct_callee = info.expr->getDirectCallee(); assert(direct_callee); @@ -3926,12 +3946,15 @@ bool Converter::VisitConstantExpr(clang::ConstantExpr *expr) { bool Converter::VisitLambdaExpr(clang::LambdaExpr *expr) { auto decl = expr->getLambdaClass(); - if (decl->captures().empty()) { + if (decl->captures().empty() && !decl->isGenericLambda()) { ConvertCapturelessLambda(decl); return false; } StrCat(LambdaMacro()); PushParen paren(*this); + if (decl->isGenericLambda()) { + StrCat("Generic", token::kComma); + } { PushBrace captures(*this); auto init = expr->capture_init_begin(); @@ -3940,18 +3963,27 @@ bool Converter::VisitLambdaExpr(clang::LambdaExpr *expr) { } } StrCat(token::kComma); - ConvertLambdaClosure(decl); + std::unordered_set signatures; + ForEachLambdaCallOperator(decl, [&](clang::CXXMethodDecl *call_operator) { + auto proto = call_operator->getType()->castAs(); + if (!signatures.insert(ConvertFunctionPointerType(proto)).second) { + llvm::report_fatal_error("generic lambda with two specializations of " + "the same signature is not supported"); + } + ConvertLambdaClosure(decl, call_operator); + StrCat(token::kComma); + }); computed_expr_type_ = ComputedExprType::FreshValue; return false; } void Converter::ConvertCapturelessLambda(const clang::CXXRecordDecl *decl) { - auto proto = decl->getLambdaCallOperator() - ->getType() - ->castAs(); + assert(!decl->isGenericLambda()); + auto call_operator = decl->getLambdaCallOperator(); + auto proto = call_operator->getType()->castAs(); StrCat(std::format("FnPtr::<{}>::new", ConvertFunctionPointerType(proto))); PushParen paren(*this); - ConvertLambdaClosure(decl); + ConvertLambdaClosure(decl, call_operator); computed_expr_type_ = ComputedExprType::FreshValue; } @@ -3964,8 +3996,8 @@ void Converter::ConvertLambdaCapture(const clang::FieldDecl *field, StrCat(token::kSemiColon); } -void Converter::ConvertLambdaClosure(const clang::CXXRecordDecl *decl) { - auto call_operator = decl->getLambdaCallOperator(); +void Converter::ConvertLambdaClosure(const clang::CXXRecordDecl *decl, + clang::CXXMethodDecl *call_operator) { StrCat('|'); for (auto p : call_operator->parameters()) { StrCat(GetNamedDeclAsString(p), token::kColon, ToString(p->getType()), @@ -3975,7 +4007,7 @@ void Converter::ConvertLambdaClosure(const clang::CXXRecordDecl *decl) { ConvertFunctionReturnType(call_operator); PushBrace body(*this); std::optional unsafe_brace; - if (decl->captures().empty()) { + if (decl->captures().empty() && !decl->isGenericLambda()) { StrCat(keyword_unsafe_); unsafe_brace.emplace(*this); } diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index fc40844e9..179207599 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -329,9 +329,14 @@ class Converter : public clang::RecursiveASTVisitor { void ConvertGenericCallExpr(clang::CallExpr *expr); - virtual void EmitFnPtrCall(clang::Expr *callee); + virtual void EmitFnPtrCall(clang::CallExpr *expr); - virtual void ConvertLambdaToFunctionPointer(clang::Expr *lambda); + void ConvertLambdaCall(clang::CallExpr *expr, + const clang::CXXRecordDecl *lambda); + + virtual void + ConvertLambdaToFunctionPointer(clang::Expr *lambda, + const clang::CXXConversionDecl *conversion); virtual void ConvertFunctionToFunctionPointer(const clang::FunctionDecl *fn_decl); @@ -479,7 +484,8 @@ class Converter : public clang::RecursiveASTVisitor { virtual void ConvertLambdaCapture(const clang::FieldDecl *field, clang::Expr *init); - void ConvertLambdaClosure(const clang::CXXRecordDecl *decl); + void ConvertLambdaClosure(const clang::CXXRecordDecl *decl, + clang::CXXMethodDecl *call_operator); virtual bool VisitImplicitValueInitExpr(clang::ImplicitValueInitExpr *expr); virtual bool VisitCXXScalarValueInitExpr(clang::CXXScalarValueInitExpr *expr); diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index f33d1a809..5cfa8792c 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -1174,6 +1174,42 @@ AsLambdaOperatorCall(const clang::FunctionDecl *fn) { return method; } +void ForEachLambdaCallOperator( + const clang::CXXRecordDecl *decl, + llvm::function_ref fn) { + if (!decl->isGenericLambda()) { + fn(decl->getLambdaCallOperator()); + return; + } + for (auto spec : decl->getDependentLambdaCallOperator()->specializations()) { + fn(clang::cast(spec)); + } +} + +clang::CXXMethodDecl * +AsLambdaCallOperator(const clang::CXXConversionDecl *conversion) { + auto decl = conversion->getParent(); + if (!decl->isGenericLambda()) { + return decl->getLambdaCallOperator(); + } + auto args = conversion->getTemplateSpecializationArgs()->asArray(); + clang::CXXMethodDecl *found = nullptr; + ForEachLambdaCallOperator(decl, [&](clang::CXXMethodDecl *op) { + auto op_args = op->getTemplateSpecializationArgs()->asArray(); + if (llvm::equal(args, op_args, + [](const clang::TemplateArgument &a, + const clang::TemplateArgument &b) { + return a.structurallyEquals(b); + })) { + found = op; + } + }); + if (!found) { + llvm::report_fatal_error("no call operator matches the lambda conversion"); + } + return found; +} + const clang::LambdaCapture *AsLambdaCapture(const clang::FieldDecl *field) { auto decl = clang::dyn_cast(field->getParent()); if (!decl || !decl->isLambda()) { @@ -1689,6 +1725,10 @@ clang::Expr *GetCallee(clang::CallExpr *expr) { return op_call->getArg(0); } } + if (auto member_call = clang::dyn_cast(expr); + member_call && AsLambdaOperatorCall(member_call->getMethodDecl())) { + return member_call->getImplicitObjectArgument(); + } return expr->getCallee(); } diff --git a/cpp2rust/converter/converter_lib.h b/cpp2rust/converter/converter_lib.h index b3a8c68c7..3790a8c2b 100644 --- a/cpp2rust/converter/converter_lib.h +++ b/cpp2rust/converter/converter_lib.h @@ -214,6 +214,13 @@ const clang::CXXRecordDecl *AsLambdaClass(clang::QualType type); const clang::CXXMethodDecl *AsLambdaOperatorCall(const clang::FunctionDecl *fn); +void ForEachLambdaCallOperator( + const clang::CXXRecordDecl *decl, + llvm::function_ref fn); + +clang::CXXMethodDecl * +AsLambdaCallOperator(const clang::CXXConversionDecl *conversion); + const clang::LambdaCapture *AsLambdaCapture(const clang::FieldDecl *field); bool IsLambdaCopyOrMoveConstructor(const clang::CXXConstructorDecl *ctor); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 2658e835a..af1cbce35 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1311,7 +1311,8 @@ bool ConverterRefCount::VisitCallExpr(clang::CallExpr *expr) { expr->getCalleeDecl()); conversion && conversion->getParent()->isLambda()) { ConvertLambdaToFunctionPointer(clang::cast(expr) - ->getImplicitObjectArgument()); + ->getImplicitObjectArgument(), + conversion); return false; } @@ -1546,9 +1547,10 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) { return Converter::VisitImplicitCastExpr(expr); } -void ConverterRefCount::EmitFnPtrCall(clang::Expr *callee) { - if (AsLambdaClass(callee->getType())) { - StrCat(ConvertRValue(callee), ".call"); +void ConverterRefCount::EmitFnPtrCall(clang::CallExpr *expr) { + auto callee = GetCallee(expr); + if (auto lambda = AsLambdaClass(callee->getType())) { + ConvertLambdaCall(expr, lambda); return; } Convert(callee); @@ -1572,8 +1574,16 @@ void ConverterRefCount::ConvertLambdaCapture(const clang::FieldDecl *field, Converter::ConvertLambdaCapture(field, init); } -void ConverterRefCount::ConvertLambdaToFunctionPointer(clang::Expr *lambda) { +void ConverterRefCount::ConvertLambdaToFunctionPointer( + clang::Expr *lambda, const clang::CXXConversionDecl *conversion) { StrCat(ConvertFreshRValue(lambda)); + auto decl = AsLambdaClass(lambda->getType()); + if (decl->isGenericLambda()) { + auto proto = conversion->getConversionType() + ->getPointeeType() + ->castAs(); + StrCat(std::format(".spec::<{}>()", ConvertFunctionPointerType(proto))); + } } void ConverterRefCount::ConvertFunctionToFunctionPointer( diff --git a/cpp2rust/converter/models/converter_refcount.h b/cpp2rust/converter/models/converter_refcount.h index a181c1eae..e76995a74 100644 --- a/cpp2rust/converter/models/converter_refcount.h +++ b/cpp2rust/converter/models/converter_refcount.h @@ -113,7 +113,7 @@ class ConverterRefCount final : public Converter { void ConvertPrintf(clang::CallExpr *expr) override; - void EmitFnPtrCall(clang::Expr *callee) override; + void EmitFnPtrCall(clang::CallExpr *expr) override; bool VisitLambdaExpr(clang::LambdaExpr *expr) override; @@ -124,7 +124,8 @@ class ConverterRefCount final : public Converter { void ConvertLambdaCapture(const clang::FieldDecl *field, clang::Expr *init) override; - void ConvertLambdaToFunctionPointer(clang::Expr *lambda) override; + void ConvertLambdaToFunctionPointer( + clang::Expr *lambda, const clang::CXXConversionDecl *conversion) override; void ConvertFunctionToFunctionPointer(const clang::FunctionDecl *fn_decl) override; From 0889705dae56a766a9dfb19691076a64cc57a3cc Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 9 Oct 2026 09:50:31 +0100 Subject: [PATCH 4/6] Update tests --- tests/unit/lambda_as_template_argument.cpp | 1 + tests/unit/lambda_generic.cpp | 1 + tests/unit/lambda_generic_explicit_args.cpp | 2 +- tests/unit/lambda_generic_to_fn_ptr.cpp | 1 + .../refcount/lambda_as_template_argument.rs | 10 +- tests/unit/out/refcount/lambda_generic.rs | 24 ++-- .../refcount/lambda_generic_explicit_args.rs | 108 ++++++++++++++++++ .../out/refcount/lambda_generic_to_fn_ptr.rs | 8 +- .../out/refcount/lambda_self_recursive.rs | 14 +-- .../out/unsafe/lambda_as_template_argument.rs | 10 +- tests/unit/out/unsafe/lambda_generic.rs | 20 ++-- .../unsafe/lambda_generic_explicit_args.rs | 96 ++++++++++++++++ .../unit/out/unsafe/lambda_self_recursive.rs | 14 +-- 13 files changed, 260 insertions(+), 49 deletions(-) create mode 100644 tests/unit/out/refcount/lambda_generic_explicit_args.rs create mode 100644 tests/unit/out/unsafe/lambda_generic_explicit_args.rs diff --git a/tests/unit/lambda_as_template_argument.cpp b/tests/unit/lambda_as_template_argument.cpp index 824ef3191..9242ee4c9 100644 --- a/tests/unit/lambda_as_template_argument.cpp +++ b/tests/unit/lambda_as_template_argument.cpp @@ -1,3 +1,4 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++23 #include template int apply_int(F fn, int x) { return fn(x); } diff --git a/tests/unit/lambda_generic.cpp b/tests/unit/lambda_generic.cpp index f3997633d..389826471 100644 --- a/tests/unit/lambda_generic.cpp +++ b/tests/unit/lambda_generic.cpp @@ -1,3 +1,4 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++23 #include int main() { diff --git a/tests/unit/lambda_generic_explicit_args.cpp b/tests/unit/lambda_generic_explicit_args.cpp index 85717e5fc..00af09643 100644 --- a/tests/unit/lambda_generic_explicit_args.cpp +++ b/tests/unit/lambda_generic_explicit_args.cpp @@ -1,4 +1,4 @@ -// translation-fail +// ADDITIONAL_COMPILE_FLAGS: -std=c++23 #include struct Val { diff --git a/tests/unit/lambda_generic_to_fn_ptr.cpp b/tests/unit/lambda_generic_to_fn_ptr.cpp index 3bf5d77b6..c97373fe2 100644 --- a/tests/unit/lambda_generic_to_fn_ptr.cpp +++ b/tests/unit/lambda_generic_to_fn_ptr.cpp @@ -1,3 +1,4 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++23 #include int main() { diff --git a/tests/unit/out/refcount/lambda_as_template_argument.rs b/tests/unit/out/refcount/lambda_as_template_argument.rs index 85abc59f1..11bc926d8 100644 --- a/tests/unit/out/refcount/lambda_as_template_argument.rs +++ b/tests/unit/out/refcount/lambda_as_template_argument.rs @@ -12,23 +12,23 @@ pub fn apply_int_0(fn_: FnPtr i32>, mut x: i32) -> i32 { } pub fn apply_int_1(fn_: FnPtr, mut x: i32) -> i32 { let fn_: Value> = Rc::new(RefCell::new(fn_)); - return ({ (*fn_.borrow()).spec:: i32>().call(x) }); + return ({ (*fn_.borrow()).spec:: i32>(0).call(x) }); } pub fn apply_int_2(fn_: FnPtr, mut x: i32) -> i32 { let fn_: Value> = Rc::new(RefCell::new(fn_)); - return ({ (*fn_.borrow()).spec:: i32>().call(x) }); + return ({ (*fn_.borrow()).spec:: i32>(0).call(x) }); } pub fn apply_int_3(fn_: FnPtr, mut x: i32) -> i32 { let fn_: Value> = Rc::new(RefCell::new(fn_)); - return ({ (*fn_.borrow()).spec:: i32>().call(x) }); + return ({ (*fn_.borrow()).spec:: i32>(0).call(x) }); } pub fn apply_double_4(fn_: FnPtr, mut x: f64) -> f64 { let fn_: Value> = Rc::new(RefCell::new(fn_)); - return ({ (*fn_.borrow()).spec:: f64>().call(x) }); + return ({ (*fn_.borrow()).spec:: f64>(1).call(x) }); } pub fn apply_double_5(fn_: FnPtr, mut x: f64) -> f64 { let fn_: Value> = Rc::new(RefCell::new(fn_)); - return ({ (*fn_.borrow()).spec:: f64>().call(x) }); + return ({ (*fn_.borrow()).spec:: f64>(1).call(x) }); } pub fn apply_twice_6(fn_: FnPtr i32>, mut x: i32) -> i32 { let fn_: Value i32>> = Rc::new(RefCell::new(fn_)); diff --git a/tests/unit/out/refcount/lambda_generic.rs b/tests/unit/out/refcount/lambda_generic.rs index 672c5b9c0..790e0d597 100644 --- a/tests/unit/out/refcount/lambda_generic.rs +++ b/tests/unit/out/refcount/lambda_generic.rs @@ -21,8 +21,8 @@ fn main_0() -> i32 { return (x + x); }, ))); - assert!((({ (*twice.borrow()).spec:: i32>().call(4,) }) == 8)); - assert!((({ (*twice.borrow()).spec:: f64>().call(1.5_f64,) }) == 3_f64)); + assert!((({ (*twice.borrow()).spec:: i32>(0).call(4,) }) == 8)); + assert!((({ (*twice.borrow()).spec:: f64>(1).call(1.5_f64,) }) == 3_f64)); let base: Value = Rc::new(RefCell::new(10)); let add_base: Value> = Rc::new(RefCell::new(lambda!( Generic, @@ -36,8 +36,12 @@ fn main_0() -> i32 { return (x + ((*base.borrow()) as f64)); }, ))); - assert!((({ (*add_base.borrow()).spec:: i32>().call(5,) }) == 15)); - assert!((({ (*add_base.borrow()).spec:: f64>().call(2.5_f64,) }) == 12.5_f64)); + assert!((({ (*add_base.borrow()).spec:: i32>(0).call(5,) }) == 15)); + assert!( + (({ + (*add_base.borrow()).spec:: f64>(1).call(2.5_f64) + }) == 12.5_f64) + ); let total: Value = Rc::new(RefCell::new(0)); let accumulate: Value> = Rc::new(RefCell::new(lambda!( Generic, @@ -54,10 +58,10 @@ fn main_0() -> i32 { total.write({ (((total.read()) as u32).wrapping_add((x).wrapping_mul(y))) as i32 }); }, ))); - ({ (*accumulate.borrow()).spec::().call(2, 3) }); + ({ (*accumulate.borrow()).spec::(0).call(2, 3) }); ({ (*accumulate.borrow()) - .spec::() + .spec::(1) .call(4_u32, 5_u32) }); assert!(((*total.borrow()) == 26)); @@ -71,11 +75,11 @@ fn main_0() -> i32 { return (x - y); }, ))); - assert!((({ (*sub.borrow()).spec:: i32>().call(9, 4,) }) == 5)); + assert!((({ (*sub.borrow()).spec:: i32>(0).call(9, 4,) }) == 5)); assert!( (({ (*sub.borrow()) - .spec:: f64>() + .spec:: f64>(1) .call(2.5_f64, 1_f64) }) == 1.5_f64) ); @@ -91,11 +95,11 @@ fn main_0() -> i32 { return (((x as f64) * y) + ((*base.borrow()) as f64)); }, ))); - assert!((({ (*mixed.borrow()).spec:: i32>().call(2, 3,) }) == 16)); + assert!((({ (*mixed.borrow()).spec:: i32>(0).call(2, 3,) }) == 16)); assert!( (({ (*mixed.borrow()) - .spec:: f64>() + .spec:: f64>(1) .call(2, 0.5_f64) }) == 11_f64) ); diff --git a/tests/unit/out/refcount/lambda_generic_explicit_args.rs b/tests/unit/out/refcount/lambda_generic_explicit_args.rs new file mode 100644 index 000000000..7e296b791 --- /dev/null +++ b/tests/unit/out/refcount/lambda_generic_explicit_args.rs @@ -0,0 +1,108 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(4)] +pub struct Val { + #[offset(0)] + pub x: i32, +} +pub fn sum_0(mut a: Val, mut b: Val) -> i32 { + return (a.x + b.x); +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let total: Value = Rc::new(RefCell::new(0)); + let tally: Value> = Rc::new(RefCell::new(lambda!( + Generic, + { + let total: Ptr = total.as_pointer(); + }, + || { + total.write({ + (((total.read()) as usize).wrapping_add( + ((::std::mem::size_of::() as usize) + .wrapping_add((::std::mem::size_of::() as usize)) + as usize), + )) as i32 + }); + }, + || { + total.write({ + (((total.read()) as usize).wrapping_add( + ((::std::mem::size_of::() as usize) + .wrapping_add((::std::mem::size_of::() as usize)) + as usize), + )) as i32 + }); + }, + ))); + ({ (*tally.borrow()).spec::(0).call() }); + ({ (*tally.borrow()).spec::(1).call() }); + assert!(((*total.borrow()) == 7)); + let v: Value = Rc::new(RefCell::new(Val { x: 5 })); + let acc: Value = Rc::new(RefCell::new(0)); + let pick: Value> = Rc::new(RefCell::new(lambda!( + Generic, + { + let v: Ptr = v.as_pointer(); + let acc: Ptr = acc.as_pointer(); + }, + || { + { + let __rhs = ({ + let _a: Val = (*v.upgrade().deref()).clone(); + let _b: Val = (*v.upgrade().deref()).clone(); + sum_0(_a, _b) + }); + acc.with_mut(|__v| *__v = *__v + __rhs) + }; + }, + || { + { + let __rhs = ({ + let _a: Val = (*v.upgrade().deref()).clone(); + let _b: Val = (*v.upgrade().deref()).clone(); + sum_0(_a, _b) + }); + acc.with_mut(|__v| *__v = *__v + __rhs) + }; + }, + || { + { + let __rhs = ({ + let _a: Val = (*v.upgrade().deref()).clone(); + let _b: Val = (*v.upgrade().deref()).clone(); + sum_0(_a, _b) + }); + acc.with_mut(|__v| *__v = *__v + __rhs) + }; + }, + ))); + ({ (*pick.borrow()).spec::(0).call() }); + ({ (*pick.borrow()).spec::(1).call() }); + ({ (*pick.borrow()).spec::(2).call() }); + assert!(((*acc.borrow()) == 30)); + let cast_to: Value> = Rc::new(RefCell::new(lambda!( + Generic, + {}, + |x: i32| -> i32 { + return ((x as i32) / 2); + }, + |x: i32| -> f64 { + return ((x as f64) / 2_f64); + }, + ))); + assert!((({ (*cast_to.borrow()).spec:: i32>(0).call(5,) }) == 2)); + assert!((({ (*cast_to.borrow()).spec:: f64>(1).call(5,) }) == 2.5_f64)); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/lambda_generic_to_fn_ptr.rs b/tests/unit/out/refcount/lambda_generic_to_fn_ptr.rs index 4ecc8b962..ae43286d0 100644 --- a/tests/unit/out/refcount/lambda_generic_to_fn_ptr.rs +++ b/tests/unit/out/refcount/lambda_generic_to_fn_ptr.rs @@ -21,8 +21,8 @@ fn main_0() -> i32 { return -x; }, ))); - let mut fi: FnPtr i32> = (*negate.borrow()).clone().spec:: i32>(); - let mut fd: FnPtr f64> = (*negate.borrow()).clone().spec:: f64>(); + let mut fi: FnPtr i32> = (*negate.borrow()).clone().spec:: i32>(0); + let mut fd: FnPtr f64> = (*negate.borrow()).clone().spec:: f64>(1); assert!((({ fi.call(3,) }) == -3_i32)); assert!((({ fd.call(1.5_f64,) }) == -1.5_f64)); let square: Value> = Rc::new(RefCell::new(lambda!( @@ -35,8 +35,8 @@ fn main_0() -> i32 { return (x * x); }, ))); - let mut si: FnPtr i32> = (*square.borrow()).clone().spec:: i32>(); - let mut sd: FnPtr f64> = (*square.borrow()).clone().spec:: f64>(); + let mut si: FnPtr i32> = (*square.borrow()).clone().spec:: i32>(0); + let mut sd: FnPtr f64> = (*square.borrow()).clone().spec:: f64>(1); assert!((({ si.call(3,) }) == 9)); assert!((({ sd.call(1.5_f64,) }) == 2.25_f64)); return 0; diff --git a/tests/unit/out/refcount/lambda_self_recursive.rs b/tests/unit/out/refcount/lambda_self_recursive.rs index 6bb0cddda..02bee8896 100644 --- a/tests/unit/out/refcount/lambda_self_recursive.rs +++ b/tests/unit/out/refcount/lambda_self_recursive.rs @@ -25,7 +25,7 @@ fn main_0() -> i32 { * ({ let _self_: FnPtr = (*self_.borrow()).clone(); (*self_.borrow()) - .spec::, i32) -> i32>() + .spec::, i32) -> i32>(0) .call(_self_, (n - 1)) })); },))); @@ -33,7 +33,7 @@ fn main_0() -> i32 { (({ let _self_: FnPtr = (*fact.borrow()).clone(); (*fact.borrow()) - .spec::, i32) -> i32>() + .spec::, i32) -> i32>(0) .call(_self_, 5) }) == 120) ); @@ -52,13 +52,13 @@ fn main_0() -> i32 { let _self_: Ptr> = (self_).clone(); let _n: i32 = (n - 1); (*self_.upgrade().deref()) - .spec::>, i32) -> i32>() + .spec::>, i32) -> i32>(0) .call(_self_, _n) }) + ({ let _self_: Ptr> = (self_).clone(); let _n: i32 = (n - 2); (*self_.upgrade().deref()) - .spec::>, i32) -> i32>() + .spec::>, i32) -> i32>(0) .call(_self_, _n) })); }, @@ -67,7 +67,7 @@ fn main_0() -> i32 { (({ let _self_: Ptr> = fib.as_pointer(); (*fib.borrow()) - .spec::>, i32) -> i32>() + .spec::>, i32) -> i32>(0) .call(_self_, 6) }) == 8) ); @@ -87,7 +87,7 @@ fn main_0() -> i32 { let _self_: Ptr> = (self_).clone(); let _n: i32 = (n - 1); (*self_.upgrade().deref()) - .spec::>, i32)>() + .spec::>, i32)>(0) .call(_self_, _n) }); }, @@ -95,7 +95,7 @@ fn main_0() -> i32 { ({ let _self_: Ptr> = count_down.as_pointer(); (*count_down.borrow()) - .spec::>, i32)>() + .spec::>, i32)>(0) .call(_self_, 4) }); assert!(((*depth.borrow()) == 4)); diff --git a/tests/unit/out/unsafe/lambda_as_template_argument.rs b/tests/unit/out/unsafe/lambda_as_template_argument.rs index 0e433f74d..bee88302a 100644 --- a/tests/unit/out/unsafe/lambda_as_template_argument.rs +++ b/tests/unit/out/unsafe/lambda_as_template_argument.rs @@ -10,19 +10,19 @@ pub unsafe fn apply_int_0(mut fn_: FnPtr i32>, mut x: i32) -> i32 { return (unsafe { fn_.call(x) }); } pub unsafe fn apply_int_1(mut fn_: FnPtr, mut x: i32) -> i32 { - return (unsafe { fn_.spec:: i32>().call(x) }); + return (unsafe { fn_.spec:: i32>(0).call(x) }); } pub unsafe fn apply_int_2(mut fn_: FnPtr, mut x: i32) -> i32 { - return (unsafe { fn_.spec:: i32>().call(x) }); + return (unsafe { fn_.spec:: i32>(0).call(x) }); } pub unsafe fn apply_int_3(mut fn_: FnPtr, mut x: i32) -> i32 { - return (unsafe { fn_.spec:: i32>().call(x) }); + return (unsafe { fn_.spec:: i32>(0).call(x) }); } pub unsafe fn apply_double_4(mut fn_: FnPtr, mut x: f64) -> f64 { - return (unsafe { fn_.spec:: f64>().call(x) }); + return (unsafe { fn_.spec:: f64>(1).call(x) }); } pub unsafe fn apply_double_5(mut fn_: FnPtr, mut x: f64) -> f64 { - return (unsafe { fn_.spec:: f64>().call(x) }); + return (unsafe { fn_.spec:: f64>(1).call(x) }); } pub unsafe fn apply_twice_6(mut fn_: FnPtr i32>, mut x: i32) -> i32 { return (unsafe { diff --git a/tests/unit/out/unsafe/lambda_generic.rs b/tests/unit/out/unsafe/lambda_generic.rs index 4f67eee83..774b38cab 100644 --- a/tests/unit/out/unsafe/lambda_generic.rs +++ b/tests/unit/out/unsafe/lambda_generic.rs @@ -23,8 +23,8 @@ unsafe fn main_0() -> i32 { return ((x) + (x)); }, ); - assert!(((unsafe { twice.spec:: i32>().call(4,) }) == (8))); - assert!(((unsafe { twice.spec:: f64>().call(1.5_f64,) }) == (3_f64))); + assert!(((unsafe { twice.spec:: i32>(0).call(4,) }) == (8))); + assert!(((unsafe { twice.spec:: f64>(1).call(1.5_f64,) }) == (3_f64))); let mut base: i32 = 10; let mut add_base: FnPtr = lambda_unsafe!( Generic, @@ -38,8 +38,8 @@ unsafe fn main_0() -> i32 { return ((x) + (base as f64)); }, ); - assert!(((unsafe { add_base.spec:: i32>().call(5,) }) == (15))); - assert!(((unsafe { add_base.spec:: f64>().call(2.5_f64,) }) == (12.5_f64))); + assert!(((unsafe { add_base.spec:: i32>(0).call(5,) }) == (15))); + assert!(((unsafe { add_base.spec:: f64>(1).call(2.5_f64,) }) == (12.5_f64))); let mut total: i32 = 0; let mut accumulate: FnPtr = lambda_unsafe!( Generic, @@ -53,8 +53,8 @@ unsafe fn main_0() -> i32 { (*total) = (((*total) as u32).wrapping_add((x).wrapping_mul(y))) as i32; }, ); - (unsafe { accumulate.spec::().call(2, 3) }); - (unsafe { accumulate.spec::().call(4_u32, 5_u32) }); + (unsafe { accumulate.spec::(0).call(2, 3) }); + (unsafe { accumulate.spec::(1).call(4_u32, 5_u32) }); assert!(((total) == (26))); let mut sub: FnPtr = lambda_unsafe!( Generic, @@ -66,8 +66,8 @@ unsafe fn main_0() -> i32 { return ((x) - (y)); }, ); - assert!(((unsafe { sub.spec:: i32>().call(9, 4,) }) == (5))); - assert!(((unsafe { sub.spec:: f64>().call(2.5_f64, 1_f64,) }) == (1.5_f64))); + assert!(((unsafe { sub.spec:: i32>(0).call(9, 4,) }) == (5))); + assert!(((unsafe { sub.spec:: f64>(1).call(2.5_f64, 1_f64,) }) == (1.5_f64))); let mut mixed: FnPtr = lambda_unsafe!( Generic, { @@ -80,8 +80,8 @@ unsafe fn main_0() -> i32 { return (((x as f64) * (y)) + (base as f64)); }, ); - assert!(((unsafe { mixed.spec:: i32>().call(2, 3,) }) == (16))); - assert!(((unsafe { mixed.spec:: f64>().call(2, 0.5_f64,) }) == (11_f64))); + assert!(((unsafe { mixed.spec:: i32>(0).call(2, 3,) }) == (16))); + assert!(((unsafe { mixed.spec:: f64>(1).call(2, 0.5_f64,) }) == (11_f64))); return 0; } pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/lambda_generic_explicit_args.rs b/tests/unit/out/unsafe/lambda_generic_explicit_args.rs new file mode 100644 index 000000000..6bac33ed6 --- /dev/null +++ b/tests/unit/out/unsafe/lambda_generic_explicit_args.rs @@ -0,0 +1,96 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct Val { + pub x: i32, +} +pub unsafe fn sum_0(mut a: Val, mut b: Val) -> i32 { + return ((a.x) + (b.x)); +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut total: i32 = 0; + let mut tally: FnPtr = lambda_unsafe!( + Generic, + { + let total: *mut i32 = &mut total; + }, + || { + (*total) = (((*total) as usize).wrapping_add( + ((::std::mem::size_of::() as usize) + .wrapping_add((::std::mem::size_of::() as usize)) + as usize), + )) as i32; + }, + || { + (*total) = (((*total) as usize).wrapping_add( + ((::std::mem::size_of::() as usize) + .wrapping_add((::std::mem::size_of::() as usize)) + as usize), + )) as i32; + }, + ); + (unsafe { tally.spec::(0).call() }); + (unsafe { tally.spec::(1).call() }); + assert!(((total) == (7))); + let mut v: Val = Val { x: 5 }; + let mut acc: i32 = 0; + let mut pick: FnPtr = lambda_unsafe!( + Generic, + { + let v: *mut Val = &mut v; + let acc: *mut i32 = &mut acc; + }, + || { + (*acc) += (unsafe { + let _a: Val = (*v); + let _b: Val = (*v); + sum_0(_a, _b) + }); + }, + || { + (*acc) += (unsafe { + let _a: Val = (*v); + let _b: Val = (*v); + sum_0(_a, _b) + }); + }, + || { + (*acc) += (unsafe { + let _a: Val = (*v); + let _b: Val = (*v); + sum_0(_a, _b) + }); + }, + ); + (unsafe { pick.spec::(0).call() }); + (unsafe { pick.spec::(1).call() }); + (unsafe { pick.spec::(2).call() }); + assert!(((acc) == (30))); + let mut cast_to: FnPtr = lambda_unsafe!( + Generic, + {}, + |x: i32| -> i32 { + return ((x as i32) / (2)); + }, + |x: i32| -> f64 { + return ((x as f64) / (2_f64)); + }, + ); + assert!(((unsafe { cast_to.spec:: i32>(0).call(5,) }) == (2))); + assert!(((unsafe { cast_to.spec:: f64>(1).call(5,) }) == (2.5_f64))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/lambda_self_recursive.rs b/tests/unit/out/unsafe/lambda_self_recursive.rs index c78cb9591..ef46d6101 100644 --- a/tests/unit/out/unsafe/lambda_self_recursive.rs +++ b/tests/unit/out/unsafe/lambda_self_recursive.rs @@ -22,14 +22,14 @@ unsafe fn main_0() -> i32 { * (unsafe { let _self_: FnPtr = self_.clone(); self_ - .spec::, i32) -> i32>() + .spec::, i32) -> i32>(0) .call(_self_, ((n) - (1))) })); },); assert!( ((unsafe { let _self_: FnPtr = fact.clone(); - fact.spec::, i32) -> i32>() + fact.spec::, i32) -> i32>(0) .call(_self_, 5) }) == (120)) ); @@ -48,13 +48,13 @@ unsafe fn main_0() -> i32 { let _self_: *mut FnPtr = self_; let _n: i32 = ((n) - (1)); (*self_) - .spec::, i32) -> i32>() + .spec::, i32) -> i32>(0) .call(_self_, _n) }) + (unsafe { let _self_: *mut FnPtr = self_; let _n: i32 = ((n) - (2)); (*self_) - .spec::, i32) -> i32>() + .spec::, i32) -> i32>(0) .call(_self_, _n) })); }, @@ -62,7 +62,7 @@ unsafe fn main_0() -> i32 { assert!( ((unsafe { let _self_: *mut FnPtr = &mut fib; - fib.spec::, i32) -> i32>() + fib.spec::, i32) -> i32>(0) .call(_self_, 6) }) == (8)) ); @@ -82,7 +82,7 @@ unsafe fn main_0() -> i32 { let _self_: *const FnPtr = self_; let _n: i32 = ((n) - (1)); (*self_) - .spec::, i32)>() + .spec::, i32)>(0) .call(_self_, _n) }); }, @@ -90,7 +90,7 @@ unsafe fn main_0() -> i32 { (unsafe { let _self_: *const FnPtr = &count_down; count_down - .spec::, i32)>() + .spec::, i32)>(0) .call(_self_, 4) }); assert!(((depth) == (4))); From 1320b160ef2ddacb68d7afa1044231819da93c96 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 9 Oct 2026 09:50:57 +0100 Subject: [PATCH 5/6] Index through specializations that have the same arguments --- cpp2rust/converter/converter.cpp | 9 ++------- cpp2rust/converter/converter_lib.cpp | 16 ++++++++++++++++ cpp2rust/converter/converter_lib.h | 2 ++ cpp2rust/converter/models/converter_refcount.cpp | 8 ++++---- libcc2rs/src/fn_ptr.rs | 10 +++------- 5 files changed, 27 insertions(+), 18 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 11fbc4a2e..4bc04ae25 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -1978,7 +1978,8 @@ void Converter::ConvertLambdaCall(clang::CallExpr *expr, if (lambda->isGenericLambda()) { auto call_operator = expr->getDirectCallee(); auto proto = call_operator->getType()->castAs(); - StrCat(std::format(".spec::<{}>()", ConvertFunctionPointerType(proto))); + StrCat(std::format(".spec::<{}>({})", ConvertFunctionPointerType(proto), + GetLambdaSpecializationIndex(call_operator))); } StrCat(".call"); } @@ -3963,13 +3964,7 @@ bool Converter::VisitLambdaExpr(clang::LambdaExpr *expr) { } } StrCat(token::kComma); - std::unordered_set signatures; ForEachLambdaCallOperator(decl, [&](clang::CXXMethodDecl *call_operator) { - auto proto = call_operator->getType()->castAs(); - if (!signatures.insert(ConvertFunctionPointerType(proto)).second) { - llvm::report_fatal_error("generic lambda with two specializations of " - "the same signature is not supported"); - } ConvertLambdaClosure(decl, call_operator); StrCat(token::kComma); }); diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index 5cfa8792c..d00c67ec3 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -1210,6 +1210,22 @@ AsLambdaCallOperator(const clang::CXXConversionDecl *conversion) { return found; } +unsigned +GetLambdaSpecializationIndex(const clang::FunctionDecl *call_operator) { + std::optional index; + unsigned i = 0; + ForEachLambdaCallOperator( + clang::cast(call_operator)->getParent(), + [&](const clang::CXXMethodDecl *op) { + if (op->getCanonicalDecl() == call_operator->getCanonicalDecl()) { + index = i; + } + ++i; + }); + assert(index); + return *index; +} + const clang::LambdaCapture *AsLambdaCapture(const clang::FieldDecl *field) { auto decl = clang::dyn_cast(field->getParent()); if (!decl || !decl->isLambda()) { diff --git a/cpp2rust/converter/converter_lib.h b/cpp2rust/converter/converter_lib.h index 3790a8c2b..c619b9f31 100644 --- a/cpp2rust/converter/converter_lib.h +++ b/cpp2rust/converter/converter_lib.h @@ -221,6 +221,8 @@ void ForEachLambdaCallOperator( clang::CXXMethodDecl * AsLambdaCallOperator(const clang::CXXConversionDecl *conversion); +unsigned GetLambdaSpecializationIndex(const clang::FunctionDecl *call_operator); + const clang::LambdaCapture *AsLambdaCapture(const clang::FieldDecl *field); bool IsLambdaCopyOrMoveConstructor(const clang::CXXConstructorDecl *ctor); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index af1cbce35..9a5f74873 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1579,10 +1579,10 @@ void ConverterRefCount::ConvertLambdaToFunctionPointer( StrCat(ConvertFreshRValue(lambda)); auto decl = AsLambdaClass(lambda->getType()); if (decl->isGenericLambda()) { - auto proto = conversion->getConversionType() - ->getPointeeType() - ->castAs(); - StrCat(std::format(".spec::<{}>()", ConvertFunctionPointerType(proto))); + auto call_operator = AsLambdaCallOperator(conversion); + auto proto = call_operator->getType()->castAs(); + StrCat(std::format(".spec::<{}>({})", ConvertFunctionPointerType(proto), + GetLambdaSpecializationIndex(call_operator))); } } diff --git a/libcc2rs/src/fn_ptr.rs b/libcc2rs/src/fn_ptr.rs index 1ae6c222d..8aaf3d8a6 100644 --- a/libcc2rs/src/fn_ptr.rs +++ b/libcc2rs/src/fn_ptr.rs @@ -458,14 +458,10 @@ impl FnPtr { } } - pub fn spec(&self) -> FnPtr { + pub fn spec(&self, index: usize) -> FnPtr { assert!(!self.is_null(), "ub: null fn pointer call"); - self.original - .as_ref() - .unwrap() - .specializations() - .iter() - .find_map(|spec| spec.downcast_ref::>()) + self.original.as_ref().unwrap().specializations()[index] + .downcast_ref::>() .expect("ub: calling through incompatible fn pointer type") .clone() } From aa9463cfacc4112ad4a61f3f5f9f01f5e32940fd Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 9 Oct 2026 09:56:51 +0100 Subject: [PATCH 6/6] Drop useless comma --- cpp2rust/converter/converter.cpp | 3 +-- .../out/refcount/lambda_as_template_argument.rs | 8 ++++---- .../out/refcount/lambda_capture_copy_ctor.rs | 14 +++++++------- .../unit/out/refcount/lambda_capture_implicit.rs | 6 +++--- .../out/refcount/lambda_capture_library_types.rs | 8 ++++---- tests/unit/out/refcount/lambda_capture_ref.rs | 12 ++++++------ .../out/refcount/lambda_capture_star_this.rs | 6 +++--- tests/unit/out/refcount/lambda_capture_this.rs | 6 +++--- tests/unit/out/refcount/lambda_capture_value.rs | 16 ++++++++-------- tests/unit/out/refcount/lambda_generic.rs | 10 +++++----- .../out/refcount/lambda_generic_explicit_args.rs | 6 +++--- .../out/refcount/lambda_generic_to_fn_ptr.rs | 4 ++-- .../out/refcount/lambda_move_only_capture.rs | 6 +++--- tests/unit/out/refcount/lambda_mutable.rs | 4 ++-- tests/unit/out/refcount/lambda_nested.rs | 8 ++++---- tests/unit/out/refcount/lambda_self_recursive.rs | 6 +++--- tests/unit/out/refcount/unboxed_locals.rs | 2 +- .../out/unsafe/lambda_as_template_argument.rs | 8 ++++---- .../unit/out/unsafe/lambda_capture_copy_ctor.rs | 14 +++++++------- tests/unit/out/unsafe/lambda_capture_implicit.rs | 6 +++--- .../out/unsafe/lambda_capture_library_types.rs | 8 ++++---- tests/unit/out/unsafe/lambda_capture_ref.rs | 12 ++++++------ .../unit/out/unsafe/lambda_capture_star_this.rs | 6 +++--- tests/unit/out/unsafe/lambda_capture_this.rs | 6 +++--- tests/unit/out/unsafe/lambda_capture_value.rs | 16 ++++++++-------- tests/unit/out/unsafe/lambda_generic.rs | 10 +++++----- .../out/unsafe/lambda_generic_explicit_args.rs | 6 +++--- .../unit/out/unsafe/lambda_generic_to_fn_ptr.rs | 4 ++-- .../unit/out/unsafe/lambda_move_only_capture.rs | 6 +++--- tests/unit/out/unsafe/lambda_mutable.rs | 4 ++-- tests/unit/out/unsafe/lambda_nested.rs | 8 ++++---- tests/unit/out/unsafe/lambda_self_recursive.rs | 6 +++--- tests/unit/out/unsafe/unboxed_locals.rs | 2 +- 33 files changed, 123 insertions(+), 124 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 4bc04ae25..0dd1debc5 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -3963,10 +3963,9 @@ bool Converter::VisitLambdaExpr(clang::LambdaExpr *expr) { ConvertLambdaCapture(field, *init++); } } - StrCat(token::kComma); ForEachLambdaCallOperator(decl, [&](clang::CXXMethodDecl *call_operator) { - ConvertLambdaClosure(decl, call_operator); StrCat(token::kComma); + ConvertLambdaClosure(decl, call_operator); }); computed_expr_type_ = ComputedExprType::FreshValue; return false; diff --git a/tests/unit/out/refcount/lambda_as_template_argument.rs b/tests/unit/out/refcount/lambda_as_template_argument.rs index 11bc926d8..1733f28f8 100644 --- a/tests/unit/out/refcount/lambda_as_template_argument.rs +++ b/tests/unit/out/refcount/lambda_as_template_argument.rs @@ -50,7 +50,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x * (*factor.borrow())); - }, + } ))); assert!((({ apply_twice_6((*scale.borrow()).copy_from(), 4,) }) == 36)); assert!( @@ -75,7 +75,7 @@ fn main_0() -> i32 { }, |x: f64| -> f64 { return (x * ((*factor.borrow()) as f64)); - }, + } ))); assert!((({ apply_int_1((*generic_scale.borrow()).copy_from(), 4,) }) == 12)); assert!((({ apply_double_4((*generic_scale.borrow()).copy_from(), 1.5_f64,) }) == 4.5_f64)); @@ -84,7 +84,7 @@ fn main_0() -> i32 { apply_int_2( lambda!(Generic, {}, |x: i32| -> i32 { return -x; - },), + }), 9, ) }) == -9_i32) @@ -99,7 +99,7 @@ fn main_0() -> i32 { }, |x: f64| -> f64 { return (x + ((*factor.borrow()) as f64)); - }, + } ))); assert!((({ apply_int_3((*offset.borrow()).copy_from(), 4,) }) == 7)); assert!((({ apply_double_5((*offset.borrow()).copy_from(), 1.5_f64,) }) == 4.5_f64)); diff --git a/tests/unit/out/refcount/lambda_capture_copy_ctor.rs b/tests/unit/out/refcount/lambda_capture_copy_ctor.rs index 8ea3112f1..1dcd24481 100644 --- a/tests/unit/out/refcount/lambda_capture_copy_ctor.rs +++ b/tests/unit/out/refcount/lambda_capture_copy_ctor.rs @@ -88,7 +88,7 @@ fn main_0() -> i32 { }, || -> i32 { return (({ (*c.borrow()).copies } * 10) + { (*c.borrow()).moves }); - }, + } ))); assert!((({ (*f.borrow()).call() }) == 10)); let g: Value i32>> = Rc::new(RefCell::new((*f.borrow()).copy_from())); @@ -105,7 +105,7 @@ fn main_0() -> i32 { }, || -> Counted { return Counted::copy_from({ c.as_pointer() }); - }, + } ) .call() }) @@ -127,7 +127,7 @@ fn main_0() -> i32 { return ({ (*arr.borrow())[(0) as usize].copies } + { (*arr.borrow())[(1) as usize].copies }); - }, + } ))); assert!((({ (*a.borrow()).call() }) == 2)); let a2: Value i32>> = Rc::new(RefCell::new((*a.borrow()).copy_from())); @@ -139,7 +139,7 @@ fn main_0() -> i32 { { let d: Value = Rc::new(RefCell::new(Dropped::new())); }, - || {}, + || {} ))); let _dtor_m = ScopedDestructor::new(&m, |__p| __p.with(|__f| __f.destroy())); let m2: Value> = Rc::new(RefCell::new((*m.borrow()).move_from())); @@ -151,7 +151,7 @@ fn main_0() -> i32 { { let d: Value = Rc::new(RefCell::new(Dropped::new())); }, - || {}, + || {} ))); let _dtor_k = ScopedDestructor::new(&k, |__p| __p.with(|__f| __f.destroy())); let k2: Value> = Rc::new(RefCell::new((*k.borrow()).copy_from())); @@ -163,7 +163,7 @@ fn main_0() -> i32 { { let d: Value = Rc::new(RefCell::new(Dropped::new())); }, - || {}, + || {} ))); let _dtor_inner = ScopedDestructor::new(&inner, |__p| __p.with(|__f| __f.destroy())); let outer: Value> = Rc::new(RefCell::new(lambda!( @@ -171,7 +171,7 @@ fn main_0() -> i32 { let inner: Value> = Rc::new(RefCell::new((*inner.borrow()).copy_from())); }, - || {}, + || {} ))); let _dtor_outer = ScopedDestructor::new(&outer, |__p| __p.with(|__f| __f.destroy())); } diff --git a/tests/unit/out/refcount/lambda_capture_implicit.rs b/tests/unit/out/refcount/lambda_capture_implicit.rs index b2e834aa5..4f287e427 100644 --- a/tests/unit/out/refcount/lambda_capture_implicit.rs +++ b/tests/unit/out/refcount/lambda_capture_implicit.rs @@ -22,7 +22,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return ((((*a.borrow()) + (*b.borrow())) + (*c.borrow())) + x); - }, + } ))); assert!((({ (*by_value.borrow()).call(10,) }) == 16)); (*a.borrow_mut()) = 100; @@ -35,7 +35,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return ((((a.read()) + (b.read())) + (c.read())) + x); - }, + } ))); assert!((({ (*by_ref.borrow()).call(10,) }) == 115)); (*b.borrow_mut()) = 200; @@ -52,7 +52,7 @@ fn main_0() -> i32 { c.with_mut(|__v| *__v = *__v + __rhs) }; return (((*a.borrow()) + (*b.borrow())) + (c.read())); - }, + } ))); assert!((({ (*mixed.borrow()).call(1,) }) == ((100 + 200) + 4))); assert!(((*c.borrow()) == 4)); diff --git a/tests/unit/out/refcount/lambda_capture_library_types.rs b/tests/unit/out/refcount/lambda_capture_library_types.rs index 79ea3b25a..be1be47d0 100644 --- a/tests/unit/out/refcount/lambda_capture_library_types.rs +++ b/tests/unit/out/refcount/lambda_capture_library_types.rs @@ -18,7 +18,7 @@ fn main_0() -> i32 { }, || -> i32 { return ((*v.borrow()).len() as i32); - }, + } ))); let g: Value i32>> = Rc::new(RefCell::new((*f.borrow()).copy_from())); let h: Value i32>> = Rc::new(RefCell::new((*f.borrow()).move_from())); @@ -36,7 +36,7 @@ fn main_0() -> i32 { } else { 0 }; - }, + } ))); let q: Value i32>> = Rc::new(RefCell::new((*p.borrow()).move_from())); assert!((({ (*q.borrow()).call() }) == 5)); @@ -48,7 +48,7 @@ fn main_0() -> i32 { }, || -> i32 { return (*n.borrow_mut()).prefix_inc(); - }, + } ))); let outer: Value i32>> = Rc::new(RefCell::new(lambda!( { @@ -57,7 +57,7 @@ fn main_0() -> i32 { }, || -> i32 { return ({ (*inner.borrow()).call() }).clone(); - }, + } ))); assert!((({ (*outer.borrow()).call() }) == 1)); let outer2: Value i32>> = Rc::new(RefCell::new((*outer.borrow()).copy_from())); diff --git a/tests/unit/out/refcount/lambda_capture_ref.rs b/tests/unit/out/refcount/lambda_capture_ref.rs index 4dbf1ff65..265efb0fa 100644 --- a/tests/unit/out/refcount/lambda_capture_ref.rs +++ b/tests/unit/out/refcount/lambda_capture_ref.rs @@ -26,7 +26,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x + (base.read())); - }, + } ))); assert!((({ (*add_base.borrow()).call(5,) }) == 15)); (*base.borrow_mut()) = 100; @@ -38,7 +38,7 @@ fn main_0() -> i32 { }, || -> i32 { return (s.with(|__s| __s.x) + s.with(|__s| __s.y)); - }, + } ))); assert!((({ (*sum.borrow()).call() }) == 3)); (*s.borrow_mut()).x = 50; @@ -50,7 +50,7 @@ fn main_0() -> i32 { }, || { counter.with_mut(|__v| __v.postfix_inc()); - }, + } ))); ({ (*bump.borrow()).call() }); ({ (*bump.borrow()).call() }); @@ -64,7 +64,7 @@ fn main_0() -> i32 { let mut t: u16 = (elem!((arr), j).read()); elem!((arr), j).write({ (elem!((arr), i).read()) }); elem!((arr), i).write(t); - }, + } ))); ({ (*swap.borrow()).call(0_usize, 3_usize) }); assert!((((*arr.borrow())[(0) as usize] as i32) == 0)); @@ -79,7 +79,7 @@ fn main_0() -> i32 { let __rhs = { x }; t.with_mut(|__v| *__v = *__v + __rhs) }; - }, + } ))); ({ (*add.borrow()).call(2) }); ({ (*add.borrow()).call(3) }); @@ -90,7 +90,7 @@ fn main_0() -> i32 { }, |v: i32| { y.write({ v }); - }, + } ))); ({ (*set_y.borrow()).call(9) }); assert!(({ (*s.borrow()).y } == 9)); diff --git a/tests/unit/out/refcount/lambda_capture_star_this.rs b/tests/unit/out/refcount/lambda_capture_star_this.rs index 58a6959fd..53bf2be9d 100644 --- a/tests/unit/out/refcount/lambda_capture_star_this.rs +++ b/tests/unit/out/refcount/lambda_capture_star_this.rs @@ -46,7 +46,7 @@ impl SImpl for Ptr { field!(this_.as_pointer(), n).with_mut(|__v| *__v = *__v + 10) }; return this_.as_pointer().with(|__s| __s.n); - }, + } ))); let mut r: i32 = ({ (*f.borrow()).call() }).clone(); return ((r * 100) + (*self).with(|__s| __s.n)); @@ -58,7 +58,7 @@ impl SImpl for Ptr { }, || -> i32 { return ({ SImpl::twice(&this_.as_pointer()) }); - }, + } ))); field!((*self), n).write(99); return ({ (*f.borrow()).call() }).clone(); @@ -72,7 +72,7 @@ impl SImpl for Ptr { }, || -> i32 { return (this_.as_pointer().with(|__s| __s.n) + (*k.borrow())); - }, + } ))); field!((*self), n).write(0); return ({ (*f.borrow()).call() }).clone(); diff --git a/tests/unit/out/refcount/lambda_capture_this.rs b/tests/unit/out/refcount/lambda_capture_this.rs index 1e601a364..1d310cb29 100644 --- a/tests/unit/out/refcount/lambda_capture_this.rs +++ b/tests/unit/out/refcount/lambda_capture_this.rs @@ -54,7 +54,7 @@ impl SImpl for Ptr { let __rhs = k; field!((*this_.borrow()).clone(), n).with_mut(|__v| *__v = *__v + __rhs) }; - }, + } ))); ({ (*inc.borrow()).call(by) }); ({ (*inc.borrow()).call(by) }); @@ -66,7 +66,7 @@ impl SImpl for Ptr { }, |k: i32| { ({ SImpl::add(&(*this_.borrow()).clone(), k) }); - }, + } ))); ({ (*inc.borrow()).call(by) }); } @@ -77,7 +77,7 @@ impl SImpl for Ptr { }, || -> i32 { return ({ SImpl::scaled(&(*this_.borrow()).clone()) }); - }, + } ))); return ({ (*get.borrow()).call() }).clone(); } diff --git a/tests/unit/out/refcount/lambda_capture_value.rs b/tests/unit/out/refcount/lambda_capture_value.rs index 666f9a1b7..a2d060a01 100644 --- a/tests/unit/out/refcount/lambda_capture_value.rs +++ b/tests/unit/out/refcount/lambda_capture_value.rs @@ -29,7 +29,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x * (*factor.borrow())); - }, + } ))); assert!((({ (*scale.borrow()).call(4,) }) == 12)); (*factor.borrow_mut()) = 100; @@ -42,7 +42,7 @@ fn main_0() -> i32 { }, || -> i32 { return ((*p.borrow()).read()); - }, + } ))); (*slot.borrow_mut()) = 8; assert!((({ (*read_ptr.borrow()).call() }) == 8)); @@ -53,7 +53,7 @@ fn main_0() -> i32 { }, || -> i32 { return ({ (*s.borrow()).x } + { (*s.borrow()).y }); - }, + } ))); (*s.borrow_mut()).x = 50; assert!((({ (*sum.borrow()).call() }) == 3)); @@ -64,7 +64,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x + (*y.borrow())); - }, + } ))); assert!((({ (*shifted.borrow()).call(5,) }) == 16)); let k: Value = Rc::new(RefCell::new(3)); @@ -74,7 +74,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x + 3); - }, + } ))); assert!((({ (*by_copy.borrow()).call(1,) }) == 4)); let by_copy_used: Value i32>> = Rc::new(RefCell::new(lambda!( @@ -83,7 +83,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x + ({ read_0(k.as_pointer()) })); - }, + } ))); assert!((({ (*by_copy_used.borrow()).call(1,) }) == 4)); let implicit_used: Value i32>> = Rc::new(RefCell::new(lambda!( @@ -92,7 +92,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x + ({ read_0(k.as_pointer()) })); - }, + } ))); assert!((({ (*implicit_used.borrow()).call(1,) }) == 4)); let by_ref: Value i32>> = Rc::new(RefCell::new(lambda!( @@ -101,7 +101,7 @@ fn main_0() -> i32 { }, |x: i32| -> i32 { return (x + 3); - }, + } ))); assert!((({ (*by_ref.borrow()).call(1,) }) == 4)); return 0; diff --git a/tests/unit/out/refcount/lambda_generic.rs b/tests/unit/out/refcount/lambda_generic.rs index 790e0d597..e94e309b3 100644 --- a/tests/unit/out/refcount/lambda_generic.rs +++ b/tests/unit/out/refcount/lambda_generic.rs @@ -19,7 +19,7 @@ fn main_0() -> i32 { }, |x: f64| -> f64 { return (x + x); - }, + } ))); assert!((({ (*twice.borrow()).spec:: i32>(0).call(4,) }) == 8)); assert!((({ (*twice.borrow()).spec:: f64>(1).call(1.5_f64,) }) == 3_f64)); @@ -34,7 +34,7 @@ fn main_0() -> i32 { }, |x: f64| -> f64 { return (x + ((*base.borrow()) as f64)); - }, + } ))); assert!((({ (*add_base.borrow()).spec:: i32>(0).call(5,) }) == 15)); assert!( @@ -56,7 +56,7 @@ fn main_0() -> i32 { }, |x: u32, y: u32| { total.write({ (((total.read()) as u32).wrapping_add((x).wrapping_mul(y))) as i32 }); - }, + } ))); ({ (*accumulate.borrow()).spec::(0).call(2, 3) }); ({ @@ -73,7 +73,7 @@ fn main_0() -> i32 { }, |x: f64, y: f64| -> f64 { return (x - y); - }, + } ))); assert!((({ (*sub.borrow()).spec:: i32>(0).call(9, 4,) }) == 5)); assert!( @@ -93,7 +93,7 @@ fn main_0() -> i32 { }, |x: i32, y: f64| -> f64 { return (((x as f64) * y) + ((*base.borrow()) as f64)); - }, + } ))); assert!((({ (*mixed.borrow()).spec:: i32>(0).call(2, 3,) }) == 16)); assert!( diff --git a/tests/unit/out/refcount/lambda_generic_explicit_args.rs b/tests/unit/out/refcount/lambda_generic_explicit_args.rs index 7e296b791..4dfae14d3 100644 --- a/tests/unit/out/refcount/lambda_generic_explicit_args.rs +++ b/tests/unit/out/refcount/lambda_generic_explicit_args.rs @@ -43,7 +43,7 @@ fn main_0() -> i32 { as usize), )) as i32 }); - }, + } ))); ({ (*tally.borrow()).spec::(0).call() }); ({ (*tally.borrow()).spec::(1).call() }); @@ -85,7 +85,7 @@ fn main_0() -> i32 { }); acc.with_mut(|__v| *__v = *__v + __rhs) }; - }, + } ))); ({ (*pick.borrow()).spec::(0).call() }); ({ (*pick.borrow()).spec::(1).call() }); @@ -99,7 +99,7 @@ fn main_0() -> i32 { }, |x: i32| -> f64 { return ((x as f64) / 2_f64); - }, + } ))); assert!((({ (*cast_to.borrow()).spec:: i32>(0).call(5,) }) == 2)); assert!((({ (*cast_to.borrow()).spec:: f64>(1).call(5,) }) == 2.5_f64)); diff --git a/tests/unit/out/refcount/lambda_generic_to_fn_ptr.rs b/tests/unit/out/refcount/lambda_generic_to_fn_ptr.rs index ae43286d0..3616dd703 100644 --- a/tests/unit/out/refcount/lambda_generic_to_fn_ptr.rs +++ b/tests/unit/out/refcount/lambda_generic_to_fn_ptr.rs @@ -19,7 +19,7 @@ fn main_0() -> i32 { }, |x: f64| -> f64 { return -x; - }, + } ))); let mut fi: FnPtr i32> = (*negate.borrow()).clone().spec:: i32>(0); let mut fd: FnPtr f64> = (*negate.borrow()).clone().spec:: f64>(1); @@ -33,7 +33,7 @@ fn main_0() -> i32 { }, |x: f64| -> f64 { return (x * x); - }, + } ))); let mut si: FnPtr i32> = (*square.borrow()).clone().spec:: i32>(0); let mut sd: FnPtr f64> = (*square.borrow()).clone().spec:: f64>(1); diff --git a/tests/unit/out/refcount/lambda_move_only_capture.rs b/tests/unit/out/refcount/lambda_move_only_capture.rs index a2115dd3f..fe42942ae 100644 --- a/tests/unit/out/refcount/lambda_move_only_capture.rs +++ b/tests/unit/out/refcount/lambda_move_only_capture.rs @@ -38,7 +38,7 @@ fn main_0() -> i32 { }, || -> i32 { return ({ (*h.borrow()).p.clone() }.read()); - }, + } ))); let _dtor_f = ScopedDestructor::new(&f, |__p| __p.with(|__f| __f.destroy())); assert!(({ (*o.borrow()).p.clone() }).is_null()); @@ -58,7 +58,7 @@ fn main_0() -> i32 { total.with_mut(|__v| *__v = *__v + __rhs) }; { (*h.borrow()).p.clone() }.write(0); - }, + } ))); let _dtor_consume = ScopedDestructor::new(&consume, |__p| __p.with(|__f| __f.destroy())); ({ (*consume.borrow()).call() }); @@ -89,7 +89,7 @@ impl OwnerImpl for Ptr { }, || -> i32 { return ({ (*self_.borrow()).p.clone() }.read()); - }, + } ); } } diff --git a/tests/unit/out/refcount/lambda_mutable.rs b/tests/unit/out/refcount/lambda_mutable.rs index 56284ef24..8222bd58d 100644 --- a/tests/unit/out/refcount/lambda_mutable.rs +++ b/tests/unit/out/refcount/lambda_mutable.rs @@ -18,7 +18,7 @@ fn main_0() -> i32 { }, || -> i32 { return (*start.borrow_mut()).postfix_inc(); - }, + } ))); assert!((({ (*next.borrow()).call() }) == 5)); assert!((({ (*next.borrow()).call() }) == 6)); @@ -32,7 +32,7 @@ fn main_0() -> i32 { |x: i32| -> i32 { (*total.borrow_mut()) += x; return (*total.borrow()); - }, + } ))); assert!((({ (*accumulate.borrow()).call(1,) }) == 1)); assert!((({ (*accumulate.borrow()).call(2,) }) == 3)); diff --git a/tests/unit/out/refcount/lambda_nested.rs b/tests/unit/out/refcount/lambda_nested.rs index e097aec70..819a1efa7 100644 --- a/tests/unit/out/refcount/lambda_nested.rs +++ b/tests/unit/out/refcount/lambda_nested.rs @@ -31,10 +31,10 @@ fn main_0() -> i32 { }, |z: i32| -> i32 { return (((x.read()) + (*y.borrow())) + z); - }, + } ))); return ({ (*inner.borrow()).call(1) }); - }, + } ))); assert!((({ (*outer.borrow()).call(20,) }) == 31)); (*x.borrow_mut()) = 100; @@ -61,10 +61,10 @@ impl SImpl for Ptr { }, |z: i32| -> i32 { return (((*this_.borrow()).clone().with(|__s| __s.v) + (*y.borrow())) + z); - }, + } ))); return ({ (*inner.borrow()).call(1) }); - }, + } ))); return ({ (*outer.borrow()).call(20) }); } diff --git a/tests/unit/out/refcount/lambda_self_recursive.rs b/tests/unit/out/refcount/lambda_self_recursive.rs index 02bee8896..4753be5a1 100644 --- a/tests/unit/out/refcount/lambda_self_recursive.rs +++ b/tests/unit/out/refcount/lambda_self_recursive.rs @@ -28,7 +28,7 @@ fn main_0() -> i32 { .spec::, i32) -> i32>(0) .call(_self_, (n - 1)) })); - },))); + }))); assert!( (({ let _self_: FnPtr = (*fact.borrow()).clone(); @@ -61,7 +61,7 @@ fn main_0() -> i32 { .spec::>, i32) -> i32>(0) .call(_self_, _n) })); - }, + } ))); assert!( (({ @@ -90,7 +90,7 @@ fn main_0() -> i32 { .spec::>, i32)>(0) .call(_self_, _n) }); - }, + } ))); ({ let _self_: Ptr> = count_down.as_pointer(); diff --git a/tests/unit/out/refcount/unboxed_locals.rs b/tests/unit/out/refcount/unboxed_locals.rs index 59178cde6..2ad5f6dcc 100644 --- a/tests/unit/out/refcount/unboxed_locals.rs +++ b/tests/unit/out/refcount/unboxed_locals.rs @@ -85,7 +85,7 @@ fn main_0() -> i32 { }, || -> i32 { return (captured.read()); - }, + } ))); (*captured.borrow_mut()) = 8; assert!((({ (*get.borrow()).call() }) == 8)); diff --git a/tests/unit/out/unsafe/lambda_as_template_argument.rs b/tests/unit/out/unsafe/lambda_as_template_argument.rs index bee88302a..8e9afd495 100644 --- a/tests/unit/out/unsafe/lambda_as_template_argument.rs +++ b/tests/unit/out/unsafe/lambda_as_template_argument.rs @@ -44,7 +44,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) * (factor)); - }, + } ); assert!(((unsafe { apply_twice_6(scale.copy_from(), 4,) }) == (36))); assert!( @@ -69,7 +69,7 @@ unsafe fn main_0() -> i32 { }, |x: f64| -> f64 { return ((x) * (factor as f64)); - }, + } ); assert!(((unsafe { apply_int_1(generic_scale.copy_from(), 4,) }) == (12))); assert!(((unsafe { apply_double_4(generic_scale.copy_from(), 1.5_f64,) }) == (4.5_f64))); @@ -78,7 +78,7 @@ unsafe fn main_0() -> i32 { apply_int_2( lambda_unsafe!(Generic, {}, |x: i32| -> i32 { return -x; - },), + }), 9, ) }) == (-9_i32)) @@ -93,7 +93,7 @@ unsafe fn main_0() -> i32 { }, |x: f64| -> f64 { return ((x) + (factor as f64)); - }, + } ); assert!(((unsafe { apply_int_3(offset.copy_from(), 4,) }) == (7))); assert!(((unsafe { apply_double_5(offset.copy_from(), 1.5_f64,) }) == (4.5_f64))); diff --git a/tests/unit/out/unsafe/lambda_capture_copy_ctor.rs b/tests/unit/out/unsafe/lambda_capture_copy_ctor.rs index 33ad5686a..c8a093317 100644 --- a/tests/unit/out/unsafe/lambda_capture_copy_ctor.rs +++ b/tests/unit/out/unsafe/lambda_capture_copy_ctor.rs @@ -90,7 +90,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (((c.copies) * (10)) + (c.moves)); - }, + } ); assert!(((unsafe { f.call() }) == (10))); let mut g: FnPtr i32> = f.copy_from(); @@ -105,7 +105,7 @@ unsafe fn main_0() -> i32 { }, || -> Counted { return Counted::copy_from({ &c }); - }, + } ) .call() }) @@ -119,7 +119,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return ((arr[(0) as usize].copies) + (arr[(1) as usize].copies)); - }, + } ); assert!(((unsafe { a.call() }) == (2))); let mut a2: FnPtr i32> = a.copy_from(); @@ -131,7 +131,7 @@ unsafe fn main_0() -> i32 { { let d: Dropped = Dropped::new(); }, - || {}, + || {} ); let _dtor_m = ScopedDestructorUnsafe::new(&raw mut m, |__f| __f.destroy()); let mut m2: FnPtr = m.move_from(); @@ -143,7 +143,7 @@ unsafe fn main_0() -> i32 { { let d: Dropped = Dropped::new(); }, - || {}, + || {} ); let _dtor_k = ScopedDestructorUnsafe::new(&raw mut k, |__f| __f.destroy()); let mut k2: FnPtr = k.copy_from(); @@ -155,14 +155,14 @@ unsafe fn main_0() -> i32 { { let d: Dropped = Dropped::new(); }, - || {}, + || {} ); let _dtor_inner = ScopedDestructorUnsafe::new(&raw mut inner, |__f| __f.destroy()); let mut outer: FnPtr = lambda_unsafe!( { let inner: FnPtr = inner.copy_from(); }, - || {}, + || {} ); let _dtor_outer = ScopedDestructorUnsafe::new(&raw mut outer, |__f| __f.destroy()); } diff --git a/tests/unit/out/unsafe/lambda_capture_implicit.rs b/tests/unit/out/unsafe/lambda_capture_implicit.rs index f3303778d..b6c4ed0d8 100644 --- a/tests/unit/out/unsafe/lambda_capture_implicit.rs +++ b/tests/unit/out/unsafe/lambda_capture_implicit.rs @@ -24,7 +24,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((((a) + (b)) + (c)) + (x)); - }, + } ); assert!(((unsafe { by_value.call(10,) }) == (16))); a = 100; @@ -37,7 +37,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((((*a) + (*b)) + (*c)) + (x)); - }, + } ); assert!(((unsafe { by_ref.call(10,) }) == (115))); b = 200; @@ -51,7 +51,7 @@ unsafe fn main_0() -> i32 { |x: i32| -> i32 { (*c) += x; return (((a) + (b)) + (*c)); - }, + } ); assert!(((unsafe { mixed.call(1,) }) == (((100) + (200)) + (4)))); assert!(((c) == (4))); diff --git a/tests/unit/out/unsafe/lambda_capture_library_types.rs b/tests/unit/out/unsafe/lambda_capture_library_types.rs index e46730e86..ebdf8087c 100644 --- a/tests/unit/out/unsafe/lambda_capture_library_types.rs +++ b/tests/unit/out/unsafe/lambda_capture_library_types.rs @@ -20,7 +20,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (v.len() as i32); - }, + } ); let mut g: FnPtr i32> = f.copy_from(); let mut h: FnPtr i32> = f.move_from(); @@ -43,7 +43,7 @@ unsafe fn main_0() -> i32 { } else { 0 }; - }, + } ); let mut q: FnPtr i32> = p.move_from(); assert!(((unsafe { q.call() }) == (5))); @@ -55,7 +55,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return n.prefix_inc(); - }, + } ); let mut outer: FnPtr i32> = lambda_unsafe!( { @@ -63,7 +63,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (unsafe { inner.call() }); - }, + } ); assert!(((unsafe { outer.call() }) == (1))); let mut outer2: FnPtr i32> = outer.copy_from(); diff --git a/tests/unit/out/unsafe/lambda_capture_ref.rs b/tests/unit/out/unsafe/lambda_capture_ref.rs index cefa6eb20..89e896634 100644 --- a/tests/unit/out/unsafe/lambda_capture_ref.rs +++ b/tests/unit/out/unsafe/lambda_capture_ref.rs @@ -26,7 +26,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) + (*base)); - }, + } ); assert!(((unsafe { add_base.call(5,) }) == (15))); base = 100; @@ -38,7 +38,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (((*s).x) + ((*s).y)); - }, + } ); assert!(((unsafe { sum.call() }) == (3))); s.x = 50; @@ -50,7 +50,7 @@ unsafe fn main_0() -> i32 { }, || { (*counter).postfix_inc(); - }, + } ); (unsafe { bump.call() }); (unsafe { bump.call() }); @@ -64,7 +64,7 @@ unsafe fn main_0() -> i32 { let mut t: u16 = (*arr)[(j)]; (*arr)[(j)] = (*arr)[(i)]; (*arr)[(i)] = t; - }, + } ); (unsafe { swap.call(0_usize, 3_usize) }); assert!(((arr[(0) as usize] as i32) == (0))); @@ -76,7 +76,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| { (*t) += x; - }, + } ); (unsafe { add.call(2) }); (unsafe { add.call(3) }); @@ -87,7 +87,7 @@ unsafe fn main_0() -> i32 { }, |v: i32| { (*y) = v; - }, + } ); (unsafe { set_y.call(9) }); assert!(((s.y) == (9))); diff --git a/tests/unit/out/unsafe/lambda_capture_star_this.rs b/tests/unit/out/unsafe/lambda_capture_star_this.rs index b8948c736..c31f5fc68 100644 --- a/tests/unit/out/unsafe/lambda_capture_star_this.rs +++ b/tests/unit/out/unsafe/lambda_capture_star_this.rs @@ -23,7 +23,7 @@ impl S { || -> i32 { (*(&raw mut this_)).n += 10; return (*(&raw mut this_)).n; - }, + } ); let mut r: i32 = (unsafe { f.call() }); return (((r) * (100)) + (self.n)); @@ -35,7 +35,7 @@ impl S { }, || -> i32 { return (unsafe { S::twice(&(*(&raw mut this_))) }); - }, + } ); self.n = 99; return (unsafe { f.call() }); @@ -48,7 +48,7 @@ impl S { }, || -> i32 { return (((*(&raw mut this_)).n) + (k)); - }, + } ); self.n = 0; return (unsafe { f.call() }); diff --git a/tests/unit/out/unsafe/lambda_capture_this.rs b/tests/unit/out/unsafe/lambda_capture_this.rs index 0d81fda54..d54d64ec0 100644 --- a/tests/unit/out/unsafe/lambda_capture_this.rs +++ b/tests/unit/out/unsafe/lambda_capture_this.rs @@ -26,7 +26,7 @@ impl S { }, |k: i32| { (*this_).n += k; - }, + } ); (unsafe { inc.call(by) }); (unsafe { inc.call(by) }); @@ -38,7 +38,7 @@ impl S { }, |k: i32| { (unsafe { S::add(&mut (*this_), k) }); - }, + } ); (unsafe { inc.call(by) }); } @@ -49,7 +49,7 @@ impl S { }, || -> i32 { return (unsafe { S::scaled(&(*this_)) }); - }, + } ); return (unsafe { get.call() }); } diff --git a/tests/unit/out/unsafe/lambda_capture_value.rs b/tests/unit/out/unsafe/lambda_capture_value.rs index b34880798..2cd64b629 100644 --- a/tests/unit/out/unsafe/lambda_capture_value.rs +++ b/tests/unit/out/unsafe/lambda_capture_value.rs @@ -29,7 +29,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) * (factor)); - }, + } ); assert!(((unsafe { scale.call(4,) }) == (12))); factor = 100; @@ -42,7 +42,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (*p); - }, + } ); slot = 8; assert!(((unsafe { read_ptr.call() }) == (8))); @@ -53,7 +53,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return ((s.x) + (s.y)); - }, + } ); s.x = 50; assert!(((unsafe { sum.call() }) == (3))); @@ -64,7 +64,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) + (y)); - }, + } ); assert!(((unsafe { shifted.call(5,) }) == (16))); let k: i32 = 3; @@ -74,7 +74,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) + (3)); - }, + } ); assert!(((unsafe { by_copy.call(1,) }) == (4))); let mut by_copy_used: FnPtr i32> = lambda_unsafe!( @@ -83,7 +83,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) + (unsafe { read_0(&k) })); - }, + } ); assert!(((unsafe { by_copy_used.call(1,) }) == (4))); let mut implicit_used: FnPtr i32> = lambda_unsafe!( @@ -92,7 +92,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) + (unsafe { read_0(&k) })); - }, + } ); assert!(((unsafe { implicit_used.call(1,) }) == (4))); let mut by_ref: FnPtr i32> = lambda_unsafe!( @@ -101,7 +101,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> i32 { return ((x) + (3)); - }, + } ); assert!(((unsafe { by_ref.call(1,) }) == (4))); return 0; diff --git a/tests/unit/out/unsafe/lambda_generic.rs b/tests/unit/out/unsafe/lambda_generic.rs index 774b38cab..4bcaa4021 100644 --- a/tests/unit/out/unsafe/lambda_generic.rs +++ b/tests/unit/out/unsafe/lambda_generic.rs @@ -21,7 +21,7 @@ unsafe fn main_0() -> i32 { }, |x: f64| -> f64 { return ((x) + (x)); - }, + } ); assert!(((unsafe { twice.spec:: i32>(0).call(4,) }) == (8))); assert!(((unsafe { twice.spec:: f64>(1).call(1.5_f64,) }) == (3_f64))); @@ -36,7 +36,7 @@ unsafe fn main_0() -> i32 { }, |x: f64| -> f64 { return ((x) + (base as f64)); - }, + } ); assert!(((unsafe { add_base.spec:: i32>(0).call(5,) }) == (15))); assert!(((unsafe { add_base.spec:: f64>(1).call(2.5_f64,) }) == (12.5_f64))); @@ -51,7 +51,7 @@ unsafe fn main_0() -> i32 { }, |x: u32, y: u32| { (*total) = (((*total) as u32).wrapping_add((x).wrapping_mul(y))) as i32; - }, + } ); (unsafe { accumulate.spec::(0).call(2, 3) }); (unsafe { accumulate.spec::(1).call(4_u32, 5_u32) }); @@ -64,7 +64,7 @@ unsafe fn main_0() -> i32 { }, |x: f64, y: f64| -> f64 { return ((x) - (y)); - }, + } ); assert!(((unsafe { sub.spec:: i32>(0).call(9, 4,) }) == (5))); assert!(((unsafe { sub.spec:: f64>(1).call(2.5_f64, 1_f64,) }) == (1.5_f64))); @@ -78,7 +78,7 @@ unsafe fn main_0() -> i32 { }, |x: i32, y: f64| -> f64 { return (((x as f64) * (y)) + (base as f64)); - }, + } ); assert!(((unsafe { mixed.spec:: i32>(0).call(2, 3,) }) == (16))); assert!(((unsafe { mixed.spec:: f64>(1).call(2, 0.5_f64,) }) == (11_f64))); diff --git a/tests/unit/out/unsafe/lambda_generic_explicit_args.rs b/tests/unit/out/unsafe/lambda_generic_explicit_args.rs index 6bac33ed6..2c9b02f55 100644 --- a/tests/unit/out/unsafe/lambda_generic_explicit_args.rs +++ b/tests/unit/out/unsafe/lambda_generic_explicit_args.rs @@ -40,7 +40,7 @@ unsafe fn main_0() -> i32 { .wrapping_add((::std::mem::size_of::() as usize)) as usize), )) as i32; - }, + } ); (unsafe { tally.spec::(0).call() }); (unsafe { tally.spec::(1).call() }); @@ -73,7 +73,7 @@ unsafe fn main_0() -> i32 { let _b: Val = (*v); sum_0(_a, _b) }); - }, + } ); (unsafe { pick.spec::(0).call() }); (unsafe { pick.spec::(1).call() }); @@ -87,7 +87,7 @@ unsafe fn main_0() -> i32 { }, |x: i32| -> f64 { return ((x as f64) / (2_f64)); - }, + } ); assert!(((unsafe { cast_to.spec:: i32>(0).call(5,) }) == (2))); assert!(((unsafe { cast_to.spec:: f64>(1).call(5,) }) == (2.5_f64))); diff --git a/tests/unit/out/unsafe/lambda_generic_to_fn_ptr.rs b/tests/unit/out/unsafe/lambda_generic_to_fn_ptr.rs index 5bfe3e66d..78dd373ec 100644 --- a/tests/unit/out/unsafe/lambda_generic_to_fn_ptr.rs +++ b/tests/unit/out/unsafe/lambda_generic_to_fn_ptr.rs @@ -21,7 +21,7 @@ unsafe fn main_0() -> i32 { }, |x: f64| -> f64 { return -x; - }, + } ); let mut fi: Option i32> = Some(|x: i32| -> i32 { return -x; @@ -39,7 +39,7 @@ unsafe fn main_0() -> i32 { }, |x: f64| -> f64 { return ((x) * (x)); - }, + } ); let mut si: Option i32> = Some(|x: i32| -> i32 { return ((x) * (x)); diff --git a/tests/unit/out/unsafe/lambda_move_only_capture.rs b/tests/unit/out/unsafe/lambda_move_only_capture.rs index ed0d87186..1d16cf92b 100644 --- a/tests/unit/out/unsafe/lambda_move_only_capture.rs +++ b/tests/unit/out/unsafe/lambda_move_only_capture.rs @@ -38,7 +38,7 @@ impl Owner { }, || -> i32 { return (*self_.p); - }, + } ); } } @@ -57,7 +57,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (*h.p); - }, + } ); let _dtor_f = ScopedDestructorUnsafe::new(&raw mut f, |__f| __f.destroy()); assert!((o.p).is_null()); @@ -74,7 +74,7 @@ unsafe fn main_0() -> i32 { || { (*total) += (*h.p); (*h.p) = 0; - }, + } ); let _dtor_consume = ScopedDestructorUnsafe::new(&raw mut consume, |__f| __f.destroy()); (unsafe { consume.call() }); diff --git a/tests/unit/out/unsafe/lambda_mutable.rs b/tests/unit/out/unsafe/lambda_mutable.rs index 615031c8c..b0ea9c84c 100644 --- a/tests/unit/out/unsafe/lambda_mutable.rs +++ b/tests/unit/out/unsafe/lambda_mutable.rs @@ -20,7 +20,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return start.postfix_inc(); - }, + } ); assert!(((unsafe { next.call() }) == (5))); assert!(((unsafe { next.call() }) == (6))); @@ -34,7 +34,7 @@ unsafe fn main_0() -> i32 { |x: i32| -> i32 { total += x; return total; - }, + } ); assert!(((unsafe { accumulate.call(1,) }) == (1))); assert!(((unsafe { accumulate.call(2,) }) == (3))); diff --git a/tests/unit/out/unsafe/lambda_nested.rs b/tests/unit/out/unsafe/lambda_nested.rs index 1561f7541..dc19d51db 100644 --- a/tests/unit/out/unsafe/lambda_nested.rs +++ b/tests/unit/out/unsafe/lambda_nested.rs @@ -25,10 +25,10 @@ impl S { }, |z: i32| -> i32 { return ((((*this_).v) + (y)) + (z)); - }, + } ); return (unsafe { inner.call(1) }); - }, + } ); return (unsafe { outer.call(20) }); } @@ -53,10 +53,10 @@ unsafe fn main_0() -> i32 { }, |z: i32| -> i32 { return (((*x) + (y)) + (z)); - }, + } ); return (unsafe { inner.call(1) }); - }, + } ); assert!(((unsafe { outer.call(20,) }) == (31))); x = 100; diff --git a/tests/unit/out/unsafe/lambda_self_recursive.rs b/tests/unit/out/unsafe/lambda_self_recursive.rs index ef46d6101..7f95fb6c6 100644 --- a/tests/unit/out/unsafe/lambda_self_recursive.rs +++ b/tests/unit/out/unsafe/lambda_self_recursive.rs @@ -25,7 +25,7 @@ unsafe fn main_0() -> i32 { .spec::, i32) -> i32>(0) .call(_self_, ((n) - (1))) })); - },); + }); assert!( ((unsafe { let _self_: FnPtr = fact.clone(); @@ -57,7 +57,7 @@ unsafe fn main_0() -> i32 { .spec::, i32) -> i32>(0) .call(_self_, _n) })); - }, + } ); assert!( ((unsafe { @@ -85,7 +85,7 @@ unsafe fn main_0() -> i32 { .spec::, i32)>(0) .call(_self_, _n) }); - }, + } ); (unsafe { let _self_: *const FnPtr = &count_down; diff --git a/tests/unit/out/unsafe/unboxed_locals.rs b/tests/unit/out/unsafe/unboxed_locals.rs index 427ab351e..885ce0db3 100644 --- a/tests/unit/out/unsafe/unboxed_locals.rs +++ b/tests/unit/out/unsafe/unboxed_locals.rs @@ -84,7 +84,7 @@ unsafe fn main_0() -> i32 { }, || -> i32 { return (*captured); - }, + } ); captured = 8; assert!(((unsafe { get.call() }) == (8)));