How to specify a lifetime for an Option<closure>? - syntax

I'm trying to put a field on a struct that should hold an Option<closure>.
However, Rust is yelling at me that I have to specify the lifetime (not that I would have really grokked that yet). I'm trying my best to do so but Rust is never happy with what I come up with. Take a look at my inline comments for the compile errors I got.
struct Floor{
handler: Option<|| ->&str> //this gives: missing lifetime specifier
//handler: Option<||: 'a> // this gives: use of undeclared lifetime name `'a`
}
impl Floor {
// I guess I need to specify life time here as well
// but I can't figure out for the life of me what's the correct syntax
fn get(&mut self, handler: || -> &str){
self.handler = Some(handler);
}
}

This gets a bit trickier.
As a general rule of thumb, whenever you're storing a borrowed reference (i.e., an & type) in a data structure, then you need to name its lifetime. In this case, you were on the right track by using a 'a, but that 'a has to be introduced in the current scope. It's done the same way you introduce type variables. So to define your Floor struct:
struct Floor<'a> {
handler: Option<|| -> &'a str>
}
But there's another problem here. The closure itself is also a reference with a lifetime, which also must be named. So there are two different lifetimes at play here! Try this:
struct Floor<'cl, 'a> {
handler: Option<||:'cl -> &'a str>
}
For your impl Floor, you also need to introduce these lifetimes into scope:
impl<'cl, 'a> Floor<'cl, 'a> {
fn get(&mut self, handler: ||:'cl -> &'a str){
self.handler = Some(handler);
}
}
You could technically reduce this down to one lifetime and use ||:'a -> &'a str, but this implies that the &str returned always has the same lifetime as the closure itself, which I think is a bad assumption to make.

Answer for current Rust version 1.x:
There are two possibilities to get what you want: either an unboxed closure or a boxed one. Unboxed closures are incredibly fast (most of the time, they are inlined), but they add a type parameter to the struct. Boxed closures add a bit freedom here: their type is erased by one level of indirection, which sadly is a bit slower.
My code has some example functions and for that reason it's a bit longer, please excuse that ;)
Unboxed Closure
Full code:
struct Floor<F>
where F: for<'a> FnMut() -> &'a str
{
handler: Option<F>,
}
impl<F> Floor<F>
where F: for<'a> FnMut() -> &'a str
{
pub fn with_handler(handler: F) -> Self {
Floor {
handler: Some(handler),
}
}
pub fn empty() -> Self {
Floor {
handler: None,
}
}
pub fn set_handler(&mut self, handler: F) {
self.handler = Some(handler);
}
pub fn do_it(&mut self) {
if let Some(ref mut h) = self.handler {
println!("Output: {}", h());
}
}
}
fn main() {
let mut a = Floor::with_handler(|| "hi");
a.do_it();
let mut b = Floor::empty();
b.set_handler(|| "cheesecake");
b.do_it();
}
Now this has some typical problems: You can't simply have a Vec of multiple Floors and every function using a Floor object needs to have type parameter on it's own. Also: if you remove the line b.set_handler(|| "cheesecake");, the code won't compile, because the compiler is lacking type information for b.
In some cases you won't run into those problems -- in others you'll need another solution.
Boxed closures
Full code:
type HandlerFun = Box<for<'a> FnMut() -> &'a str>;
struct Floor {
handler: Option<HandlerFun>,
}
impl Floor {
pub fn with_handler(handler: HandlerFun) -> Self {
Floor {
handler: Some(handler),
}
}
pub fn empty() -> Self {
Floor {
handler: None,
}
}
pub fn set_handler(&mut self, handler: HandlerFun) {
self.handler = Some(handler);
}
pub fn do_it(&mut self) {
if let Some(ref mut h) = self.handler {
println!("Output: {}", h());
}
}
}
fn main() {
let mut a = Floor::with_handler(Box::new(|| "hi"));
a.do_it();
let mut b = Floor::empty();
b.set_handler(Box::new(|| "cheesecake"));
b.do_it();
}
It's a bit slower, because we have a heap allocation for every closure and when calling a boxed closure it's an indirect call most of the time (CPUs don't like indirect calls...).
But the Floor struct does not have a type parameter, so you can have a Vec of them. You can also remove b.set_handler(Box::new(|| "cheesecake")); and it will still work.

Related

Should I try to access self in a PointerPressed event handler for a CoreApp in the Rust Crate for Windows?

E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement. E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement. E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement. E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement.
#![windows_subsystem = "windows"]
use windows::{
core::*,
Foundation::*,
ApplicationModel::Core::*,
Foundation::Numerics::*,
Foundation::TypedEventHandler,
Win32::System::Com::*,
UI::{
Core::*,
Composition::*,
},
};
use windows as Windows;
#[implement(Windows::ApplicationModel::Core::IFrameworkViewSource)]
struct App();
#[allow(non_snake_case)]
impl App {
fn CreateView(&self) -> Result<IFrameworkView> {
// TODO: need self query `self.into()` to support implementing both IFrameworkViewSource and IFrameworkView on the same object.
Ok(AppView::new().into())
}
}
#[implement(Windows::ApplicationModel::Core::IFrameworkView)]
struct AppView {
m_target: Option<CompositionTarget>,
m_visuals: Option<VisualCollection>,
m_selected: Option<Visual>,
m_offset: Option<Vector2>,
}
#[allow(non_snake_case)]
impl AppView {
fn new() -> Self {
Self {
m_target: None,
m_visuals: None,
m_selected: None,
m_offset: None,
}
}
fn Initialize(&self, _: &Option<CoreApplicationView>) -> Result<()> {
Ok(())
}
fn Load(&self, _: &HSTRING) -> Result<()> {
Ok(())
}
fn Uninitialize(&self) -> Result<()> {
Ok(())
}
fn Run(&self) -> Result<()> {
let window = CoreWindow::GetForCurrentThread()?;
window.Activate()?;
let dispatcher = window.Dispatcher()?;
dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit)?;
Ok(())
}
fn SetWindow(&mut self, window: &Option<CoreWindow>) -> Result<()> {
let compositor = Compositor::new()?;
let root = compositor.CreateContainerVisual()?;
self.m_target = Some(compositor.CreateTargetForCurrentView()?);
let target = self.m_target.as_ref().unwrap();
target.SetRoot(&root)?;
self.m_visuals = Some(root.Children()?);
let visuals = self.m_visuals.as_ref().unwrap(); // extra line for test is ok
window.as_ref().unwrap().PointerPressed(TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, args|
{
let args = args.as_ref().unwrap();
let currentpoint = args.CurrentPoint().unwrap();
let point = currentpoint.Position().unwrap(); // Point not Vector2
//let visuals: &VisualCollection = self.m_visuals.as_ref().unwrap();
let visuals = self.m_visuals.as_ref().unwrap(); // E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement
Ok(())
}
))?;
window.as_ref().unwrap().PointerMoved(TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, _args|
{
Ok(())
}
))?;
window.as_ref().unwrap().PointerReleased(TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, _args|
{
Ok(())
}
))?;
Ok(())
}
fn AddVisual(_point: Point) {
//...
}
}
fn main() -> Result<()> {
unsafe {
CoInitializeEx(std::ptr::null_mut(), COINIT_MULTITHREADED)?;
}
let app: IFrameworkViewSource = App().into();
CoreApplication::Run(app)?;
Ok(())
}
Capturing AppView's instance self reference in v0.30 doesn't seem to be possible, because TypedEventHandler::new has a + 'static requirement for the callback (see), so any reference it captures must be 'static (a global variable basically).
Please raise an issue here if you want this. Your code looks like a reasonable way to use this API.
Until then, as a workaround you could make a level of indirection, where instead of storing the state directly in AppView, you store it in a shared helper object, for example:
struct AppView {
m_state: Rc<RefCell<AppViewState>>,
}
struct AppViewState {
m_target: Option<CompositionTarget>,
m_visuals: Option<VisualCollection>,
m_selected: Option<Visual>,
m_offset: Option<Vector2>,
}
You can clone it move into the callback for modification:
let pointer_pressed_state = Rc::clone(self.m_state);
let pointer_pressed_handler = TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, args| {
let state_ref = pointer_pressed_state.borrow(); // or .borrow_mut()
...
});
let pointer_moved_state = Rc::clone(self.m_state);
let pointer_moved_handler = TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, args| {
let state_ref = pointer_moved_state.borrow(); // or .borrow_mut()
...
});
This should work, because now the closure doesn't capture any references (everything gets moved).
If you want, you can add methods to AppViewState, and call them from the closures like state_ref.OnPointerPressed(...).
Another option that I don't recommend is to use unsafe and cast self to 'static.
Rc<RefCell> gives a thread related compiler error but changing to Arc<Mutex> resolves this.
struct AppView {
m_state: Arc<Mutex<AppViewState>>,
}
struct AppViewState {
m_target: Option<CompositionTarget>,
m_visuals: Option<VisualCollection>,
m_selected: Option<Visual>,
m_offset: Option<Vector2>,
}

How can I use the same default implementation for this Rust trait

I want to implement a trait that allows assigning generic types. So far I have tested this for u32 and String types:
trait Test {
fn test(&self, input: &str) -> Self;
}
impl Test for String {
fn test(&self, input: &str) -> Self {
input.parse().unwrap()
}
}
impl Test for u32 {
fn test(&self, input: &str) -> Self {
input.parse().unwrap()
}
}
fn main() {
let mut var = 0u32;
let mut st = String::default();
var = var.test("12345678");
st = st.test("Text");
println!("{}, {}", var, st);
}
I know this code is not perfect, and I should be using a Result return instead of unwrapping, but please set this aside as this is a quick example. The implementations for u32 and String are exactly the same, so I would like to use a default implementation for both instead of copying & pasting the code. I have tried using one, but as the returned type Self differs in both, compiler cannot determine the type size and errors.
How could I write a default implementation in this case?
Default implementation
The following bounds on Self are required for the default implementation:
Self: Sized because Self is returned from the function and will be placed in the caller's stack
Self: FromStr because you're calling parse() on input and expecting it to produce a value of type Self
<Self as FromStr>::Err: Debug because when you unwrap a potential error and the program panics Rust wants to be able to print the error message, which requires the error type to implement Debug
Full implementation:
use std::fmt::Debug;
use std::str::FromStr;
trait Test {
fn test(&self, input: &str) -> Self
where
Self: Sized + FromStr,
<Self as FromStr>::Err: Debug,
{
input.parse().unwrap()
}
}
impl Test for String {}
impl Test for u32 {}
fn main() {
let mut var = 0u32;
let mut st = String::default();
var = var.test("12345678");
st = st.test("Text");
println!("{}, {}", var, st);
}
playground
Generic implementation
A generic blanket implementation is also possible, where you automatically provide an implementation of Test for all types which satisfy the trait bounds:
use std::fmt::Debug;
use std::str::FromStr;
trait Test {
fn test(&self, input: &str) -> Self;
}
impl<T> Test for T
where
T: Sized + FromStr,
<T as FromStr>::Err: Debug,
{
fn test(&self, input: &str) -> Self {
input.parse().unwrap()
}
}
fn main() {
let mut var = 0u32;
let mut st = String::default();
var = var.test("12345678");
st = st.test("Text");
println!("{}, {}", var, st);
}
playground
Macro implementation
This implementation, similar to the default implementation, allows you to pick which types get the implementation, but it's also similar to the generic implementation, in that it doesn't require you to modify the trait method signature with any additional trait bounds:
trait Test {
fn test(&self, input: &str) -> Self;
}
macro_rules! impl_Test_for {
($t:ty) => {
impl Test for $t {
fn test(&self, input: &str) -> Self {
input.parse().unwrap()
}
}
}
}
impl_Test_for!(u32);
impl_Test_for!(String);
fn main() {
let mut var = 0u32;
let mut st = String::default();
var = var.test("12345678");
st = st.test("Text");
println!("{}, {}", var, st);
}
playground
Key differences
The key differences between the 3 approaches:
The default implementation makes the trait bounds inherent to the method's signature, so all types which impl Test must be sized, and have a FromStr impl with a debuggable error type.
The default implementation allows you to selectively pick which types get Test implementations.
The generic implementation doesn't add any trait bounds to the trait method's signature so a greater variety of types could potentially implement the trait.
The generic implementation automatically implements the trait for all types which satisfy the bounds, you cannot selectively "opt out" of the generic implementation if there are some types which you'd prefer not to implement the trait.
The macro implementation does not require modifying the trait method signature with additional trait bounds and allows you to selectively pick which types get the implementation.
The macro implementation is a macro and suffers all the downsides of being a macro: harder to read, write, maintain, increases compile times, and macros are essentially opaque to static code analyzers which makes it harder to easily type-check your code.

Replace a struct member with a new value that uses the previous value

I have a struct which owns a boxed value of some trait type. The struct itself also implements the same trait. I would like to replace the value with a new instance of the same struct, which wraps it.
The following code, which does not compile, should make it more clear what I am trying to do:
trait T {}
struct S {
t: Box<dyn T>,
}
impl T for S {}
impl S {
fn new(t: Box<dyn T>) -> Self {
Self { t }
}
fn wrap_t(&mut self) {
self.t = Box::new(Self::new(self.t))
}
}
This fails:
error[E0507]: cannot move out of borrowed content
--> src/lib.rs:14:37
|
14 | self.t = Box::new(Self::new(self.t))
| ^^^^ cannot move out of borrowed content
Implementing wrap_t like this does compile:
use std::mem;
fn wrap_t(&mut self) {
unsafe {
let old_t = mem::replace(&mut self.t, mem::uninitialized());
let new_t = Box::new(Self::new(old_t));
let uninit = mem::replace(&mut self.t, new_t);
mem::forget(uninit);
}
}
I wonder if there is a safe way to do this.
The only unsafe function you are using is mem::uninitialized. You need something to pass to mem::replace, but implementing Default won't work because default() returns Self, which prevents it from being object-safe. Similarly, you can't implement Clone to duplicate the old value, since clone() also returns Self.
You can just implement a dummy type for the purpose though:
struct Dummy;
impl T for Dummy {}
fn wrap_t(&mut self) {
let old_t = mem::replace(&mut self.t, Box::new(Dummy));
let new_t = Box::new(Self::new(old_t));
mem::replace(&mut self.t, new_t);
}
You also won't need the mem::forget here now either (I'm assuming that was there to prevent undefined behaviour when the uninitialised memory was dropped).
As an alternative to Clone, you can roll your own own, which clones to a Box<dyn T>, avoiding having a Self in the method signature, so the trait stays object safe:
trait T: Debug {
fn clone_in_box(&self) -> Box<dyn T>;
}
impl T for S {
fn clone_in_box(&self) -> Box<dyn T> {
Box::new(S {
t: self.t.clone_in_box(),
})
}
}
fn wrap_t(&mut self) {
let cloned = self.clone_in_box();
let old_t = mem::replace(&mut self.t, cloned);
let new_t = Box::new(Self::new(old_t));
mem::replace(&mut self.t, new_t);
}
There is also an alternative design, which is much simpler to understand when reading the code. That is just to consume self and return a new object:
fn wrap_t(self) -> Self {
Self::new(Box::new(Self::new(self.t)))
}
And instead of this:
s.wrap_t();
You would do:
s = s.wrap_t();

I don't understand how borrowing works

I'm trying to write a kd-tree implementation, but I keep getting the error cannot move out of borrowed content.
This is my KDTree struct
pub struct KDTree {
pub bounding_box: Aabb,
pub axis: Option<Axis>,
left: Option<Box<KDTree>>,
right: Option<Box<KDTree>>,
pub objects: Option<Vec<Box<Geometry>>>,
}
This method, however, throws that error.
pub fn direct_samples(&self) -> Vec<u32> {
assert!(self.objects.is_some());
let mut direct_samples = Vec::new();
for (i, object) in self.objects
.expect("Expected tree to have objects")
.iter()
.enumerate() {
if object.material().emittance > 0f32 {
direct_samples.push(i as u32);
}
}
if self.left.is_some() {
direct_samples.extend(self.left.unwrap().direct_samples());
}
if self.right.is_some() {
direct_samples.extend(self.right.unwrap().direct_samples());
}
direct_samples
}
I understand that if I change the parameter to self instead of &self, it should work, but then when I call it, it gives the error use of moved value.
pub fn from_objects(objects: Vec<Box<Geometry>>) -> Scene {
let tree = KDTree::from_objects(objects);
Scene {
camera: Camera::new(),
objects: tree,
direct_samples: tree.direct_samples(),
}
}
Do I need to implement Copy on my KDTree? Won't this use a lot of cpu/memory to copy the entire thing?
The reason your code requires ownership of the KDTree is because you are calling Option::expect and Option::unwrap. The docs for these can be found here.
impl<T> Option<T> {
fn unwrap(self) -> T {
...
}
}
So when you are calling unwrap (or expect) the compiler rightly complains that you are taking the elements of your struct by value. To fix this, use the Option::as_ref method.
impl<T> Option<T> {
fn as_ref(&self) -> Option<&T> {
...
}
}
This will turn a reference to an option into an optional reference, which does not require ownership. You can see this in the signature of the function - it takes &self rather than self.
pub fn direct_samples(&self) -> Vec<u32> {
assert!(self.objects.is_some());
let mut direct_samples = Vec::new();
for (i, object) in self.objects.as_ref()
.expect("Expected tree to have objects")
.iter()
.enumerate() {
if object.material().emittance > 0f32 {
direct_samples.push(i as u32);
}
}
if self.left.is_some() {
direct_samples.extend(self.left.as_ref().unwrap().direct_samples());
}
if self.right.is_some() {
direct_samples.extend(self.right.as_ref().unwrap().direct_samples());
}
direct_samples
}
Do I need to implement Copy on my KDTree? Won't this use a lot of cpu/memory to copy the entire thing?
You can't implement Copy on your KDTree because it contains heap-allocated memory (boxes) - Copy means that your type can be copied just by copying its bytes, but that can't happen without invalidating single ownership in this case.

Pass instance of type from argument list into function declaration (dynamic environment capture)

I made a library that implements an optimization algorithm here. These are the signatures for the relevant function and trait:
pub fn cmaes_loop<T>(object: &T, options: CMAESOptions) -> Option<Vec<f64>>
where T: 'static + FitnessFunction
pub trait FitnessFunction {
fn get_fitness(&self, parameters: &[f64]) -> f64;
}
If I apply the library to a simple problem, I can calculate the fitness based on the parameters given. However, let's say I want to optimize the shape of a wing for a given size and material:
struct Wing<'a> {
material: String,
size: i32,
parameters: &'a [f64]
}
I can implement the fitness function to read from the other fields and factor them into the calculation, then give an instance of Wing to the cmaes_loop function to optimize a specific material and size. I am making another library that will use this one. It optimizes something else (like Wing), so I have a wrapper trait to make the second library easier to use:
pub trait WingFitnessFunction {
fn get_fitness(&self, wing: &Wing) -> f64;
}
I implement the FitnessFunction trait like this:
impl FitnessFunction for Wing {
fn get_fitness(&self, parameters: &[f64]) -> f64 {
let wing = Wing {
parameters: parameters,
.. self
};
// error here
let result = WingFitnessFunction::get_fitness(wing);
}
}
WingFitnessFunction has a &self argument for the the same reason FitnessFunction does. I want a user of my second library to be able to pass an instance of their type that implements the WingFitnessFunction. I put the impl of FitnessFunction into the body of a function that takes an instance of the user's type:
fn foo<T: WingFitnessFunction>(object: T) {
impl FitnessFunction for Wing {
...
object.get_fitness(wing)
}
But when I try to call the get_fitness method of object I get this error:
can't capture dynamic environment in a fn item; use the || { ... } closure form instead
I need to know how to call object's get_fitness method on a specific instance (a closure could do this, but I do not know how I would make it work with the cmaes_loop function).
The solution to my problem is to add a wrapper:
struct WingWrapper<'a, T: WingFitnessFunction> {
wing: Wing,
object: T
}
And implement FitnessFunction for it:
impl<'a, T: WingFitnessFunction> FitnessFunction for WingWrapper<'a, T> {
fn get_fitness(&self, parameters: &[f64]) -> f64 {
let wing = Wing {
parameters: parameters,
.. self.wing
}
self.object.get_fitness(&wing)
}
}
In the function that takes a type that implements WingFitnessFunction as an argument, first build a WingWrapper:
let wrapper = WingWrapper {
wing: // Instance of wing here
object: // Instance of object here (taken as an argument)
}
Now, you can call the get_fitness method from the WingFitnessFunction trait through the method from FitnessFunction:
println!("{}", wrapper.get_fitness(&[1, 2, 3]));
This does not add any difficult to using the library; it is exactly the same from the user's perspective.

Resources