Rust boxed closure in global variable - rust

I'd like to store a boxed closure (Box<dyn Fn(f64, f64) -> f64>) in a global variable EXPRESSION_FUNCTION.
Here is my attempt at achieving this:
type F2d = Box<dyn Fn(f64, f64) -> f64>;
static mut EXPRESSION_FUNCTION: *mut F2d = 0 as *mut F2d;
fn create_function() -> F2d {
Box::new(|_: f64, _: f64| 0.0)
}
fn set_expression_function() {
unsafe {
EXPRESSION_FUNCTION = Box::into_raw(create_function());
}
}
I get a type mismatch:
error[E0308]: mismatched types
--> src\lib.rs:79:45
|
79 | EXPRESSION_FUNCTION = Box::into_raw(create_function());
| ^^^^^^^^^^^^^^^^^ expected struct `Box`, found trait object `dyn Fn`
|
= note: expected struct `Box<Box<(dyn Fn(f64, f64) -> f64 + 'static)>, _>`
found struct `Box<(dyn Fn(f64, f64) -> f64 + 'static), std::alloc::Global>`
How can I convert the result of create_function to fit into a global variable?

Do not use static mut. It is extremely easy to write incorrect programs that violate Rust's reference and aliasing rules using static mut. Instead, use static together with some kind of cell (interior-mutable type) — even UnsafeCell (which should be a last resort) is easier to use correctly than static mut.
If your variable is going to be initialized only once, the simplest solution is to use once_cell (which is on its way to being included in the standard library, but for now is a widely used third-party library).
use once_cell::sync::OnceCell;
type F2d = Box<dyn Fn(f64, f64) -> f64 + Send + Sync>;
static EXPRESSION_FUNCTION: OnceCell<F2d> = OnceCell::new();
fn create_function() -> F2d {
Box::new(|_: f64, _: f64| 2.0)
}
fn set_expression_function() {
if let Err(_) = EXPRESSION_FUNCTION.set(create_function()) {
panic!("already set");
}
}
fn main() {
set_expression_function();
let f = EXPRESSION_FUNCTION.get().expect("not set");
assert_eq!(f(10., 0.), 2.0);
}
If it needs to be reassignable, then you need a lock. parking_lot::RwLock is a nice choice because it can be constructed at compile time, so no lazy initialization is needed:
use parking_lot::RwLock;
type F2d = Box<dyn Fn(f64, f64) -> f64 + Send + Sync>;
static EXPRESSION_FUNCTION: RwLock<Option<F2d>> = RwLock::new(None);
fn create_function() -> F2d {
Box::new(|_: f64, _: f64| 2.0)
}
fn set_expression_function() {
*EXPRESSION_FUNCTION.write() = Some(create_function());
}
fn main() {
set_expression_function();
let option_fn_guard = EXPRESSION_FUNCTION.read();
let f = option_fn_guard.as_ref().expect("not set");
assert_eq!(f(10., 0.), 2.0);
}
Unlike the static mut you started with, both of these programs are sound (will not segfault, etc.) no matter how the functions and global variable are used. This is good Rust programming practice.

I got it working using Some:
type F2d = Box<dyn Fn(f64, f64) -> f64>;
static mut EXPRESSION_FUNCTION: Option<F2d> = None;
fn create_function() -> F2d {
Box::new(|x: f64, y: f64| x+y)
}
fn set_expression_function() {
unsafe {
EXPRESSION_FUNCTION = Some(create_function());
}
}
fn main() {
set_expression_function();
unsafe {
if let Some(f) = &EXPRESSION_FUNCTION{
println!("{}", f(1.0, 2.0));
}
};
}

Related

How should I understand &**self in Box

Code in boxed.rs:
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
impl<T: ?Sized, A: Allocator> const Deref for Box<T, A> {
type Target = T;
fn deref(&self) -> &T {
&**self
}
}
In my understanding:
self -> &Box,
*self -> Box.
**self -> *Box, will call: *(Box.deref())? Doesn't that lead to recursion?
I create a test code:
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &T {
&**self
}
}
When I run it, Rust return me: fatal runtime error: stack overflow
So how does &**self work in std's Box?
Box is special. It is a lang item, and the compiler knows to deref it without help. So:
self - &Box.
*self - Box, builtin deref of shared reference.
**self - T, builtin deref of Box.
&**self - &T.
Similar things happen for all builtin operations. For example, this is the Add impl for integers (inside a macro):
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_ops", issue = "90080")]
impl const Add for $t {
type Output = $t;
#[inline]
#[rustc_inherit_overflow_checks]
fn add(self, other: $t) -> $t { self + other }
}
Again, the compiler knows to add integers. It is a builtin operation.
The reason we need the impl is for generics. Code like 0i32 + 0i32 translates to the builtin addition, but in a generic function:
fn add<T: Add>(a: T, b: T) -> T::Output { a + b }
If integers wouldn't implement Add, this function wouldn't accept them. The same happens for Box and Deref.
You can see that by inspecting the MIR. For example, the following function:
pub fn deref(b: &Box<i32>) -> &i32 {
&**b
}
Generates the following MIR:
fn deref(_1: &Box<i32>) -> &i32 {
let mut _0: &i32;
bb0: {
_0 = &(*(*_1));
return;
}
}
However, the following function:
pub fn deref<T: std::ops::Deref<Target = i32>>(b: &T) -> &i32 {
&**b
}
Generates the following MIR, that calls deref():
fn deref(_1: &T) -> &i32 {
let mut _0: &i32;
let _2: &i32;
let mut _3: &T;
bb0: {
_3 = _1;
_2 = <T as Deref>::deref(move _3) -> bb1;
}
bb1: {
_0 = _2;
return;
}
}
The same happens for other Deref implementors, e.g. Rc:
pub fn deref(b: &std::rc::Rc<i32>) -> &i32 {
&**b
}
fn deref(_1: &Rc<i32>) -> &i32 {
let mut _0: &i32;
let _2: &i32;
let mut _3: &std::rc::Rc<i32>;
bb0: {
_3 = _1;
_2 = <Rc<i32> as Deref>::deref(move _3) -> bb1;
}
bb1: {
_0 = _2;
return;
}
}

Generic type parameter with constraints from unsigned integer type

I am trying to use a generic datatype which implements 2 methods from the unsigned primitive integer types in rust (u8, u32, u64, etc.). The goal is to be able to read some predefined datatype from a stream (playground link):
use std::io::Read;
use std::io::BufReader;
pub trait ReadExt {
fn read<T>(&mut self) -> Result<T, std::io::Error>;
}
impl<R: Read> ReadExt for R {
fn read<T>(&mut self) -> Result<T, std::io::Error> {
let mut v = Vec::with_capacity((T::BITS >> 3).into());
self.read_exact(&mut v);
Ok(T::from_le_bytes(v))
}
}
fn main() {
let mut stream = BufReader::new(&0xffffffffu32.to_le_bytes()[..]);
let x = ReadExt::read::<u32>(&mut stream).unwrap();
assert_eq!(x, 0xffffffffu32);
}
I get the compile error:
error[E0599]: no associated item named `BITS` found for type parameter `T` in the current scope
--> src/main.rs:11:44
|
11 | let mut v = Vec::with_capacity((T::BITS >> 3).into());
| ^^^^ associated item not found in `T`
error[E0599]: no function or associated item named `from_le_bytes` found for type parameter `T` in the current scope
--> src/main.rs:13:15
|
13 | Ok(T::from_le_bytes(v))
| ^^^^^^^^^^^^^ function or associated item not found in `T`
How do I add constraints on T and specify that T must implement the traits from u8, u16, u32? Specifically, I want T to implement BITS and from_le_bytes.
If you want to use any methods or constants coming from T, then T must be bounded/constrained by some trait, because you can use only methods/constants/etc coming from the trait bounds.
In your case that would be:
pub trait FromLeBytes {
const BITS: u32;
fn from_le_bytes(bytes: [u8; 4]) -> Self;
}
which defines the required method from_le_bytes() and the constant BITS.
You will have to implement that trait for each type that you want to use. Currently I've implemented it only for u32:
impl FromLeBytes for u32 {
const BITS: u32 = u32::BITS;
fn from_le_bytes(bytes: [u8; 4]) -> Self {
u32::from_le_bytes(bytes)
}
}
Then you need to declare that constraint by modifying your ReadExt trait:
pub trait ReadExt {
fn read<T: FromLeBytes>(&mut self) -> Result<T, std::io::Error>;
}
After which you are ready to use the method and the constant in your code:
use std::io::BufReader;
use std::io::Read;
pub trait FromLeBytes {
const BITS: u32;
fn from_le_bytes(bytes: [u8; 4]) -> Self;
}
impl FromLeBytes for u32 {
const BITS: u32 = u32::BITS;
fn from_le_bytes(bytes: [u8; 4]) -> Self {
u32::from_le_bytes(bytes)
}
}
pub trait ReadExt {
fn read<T: FromLeBytes>(&mut self) -> Result<T, std::io::Error>;
}
impl<R: Read> ReadExt for R {
fn read<T: FromLeBytes>(&mut self) -> Result<T, std::io::Error> {
// Could NOT have been done like that because of: https://github.com/rust-lang/rust/issues/68436
// let mut v = [0; T::BITS as usize / 8];
// self.read_exact(&mut v);
// Ok(T::from_le_bytes(v))
let mut v = Vec::with_capacity(T::BITS as usize / 8);
v.resize(v.capacity(), 0);
self.read_exact(&mut v).unwrap();
let mut a = [0; 4];
for (i, b) in v.iter().copied().enumerate() {
a[i] = b;
}
Ok(T::from_le_bytes(a))
}
}
fn main() {
let x = &0xffffffffu32.to_le_bytes()[..];
let mut stream = BufReader::new(x);
let x = ReadExt::read::<u32>(&mut stream).unwrap();
assert_eq!(x, 0xffffffffu32);
}
PS: I've also fixed some compilation errors in your original code
This is not easily possible because BITS and from_le_bytes are both not from a trait, but associated functions of u8, u16 etc. There is no common trait that has those functions/consts.
You can partially work around this by relying on num_traits::int::PrimInt::from_le() to convert endianness and std::mem::size_of() to get the number of bytes in the integer. However, from_le() only allows converting an existing integer – it does not allow to convert a byte buffer, and your use case needs that.
If you are okay with using unsafe Rust, you can achieve what you want via std::mem::transmute_copy. Below you find code doing exactly that (I also fixed a few bugs in your original code). But please read on – there is still a subtle problem.
use std::io::Read;
use std::io::BufReader;
use num_traits::int::PrimInt;
pub trait ReadExt {
fn read<T: PrimInt>(&mut self) -> Result<T, std::io::Error>;
}
impl<R: Read> ReadExt for R {
fn read<T: PrimInt>(&mut self) -> Result<T, std::io::Error> {
let mut v = vec![0u8; std::mem::size_of::<T>()];
self.read_exact(&mut v).unwrap();
let result_in_le: T = unsafe {
std::mem::transmute_copy(&v[0])
};
Ok(T::from_le(result_in_le))
}
}
fn main() {
let buf = 0xffffffffu32.to_le_bytes();
let mut stream = BufReader::new(&buf[..]);
let x = ReadExt::read::<u32>(&mut stream).unwrap();
assert_eq!(x, 0xffffffffu32);
}
Playground
This implementation has a way for the user to trigger undefined behavior: As PrimInt is not sealed, one could implement the trait on some custom struct containing a f64. Using ReadExt::read(), one could then transform arbitrary byte patterns into a f64 – this triggers undefined behavior.
To solve this, we can construct our own trait that is a subtrait of PrimInt and unsafe:
use std::io::Read;
use std::io::BufReader;
use num_traits::int::PrimInt;
pub unsafe trait UnsafeInt: PrimInt {
}
unsafe impl UnsafeInt for u8 {}
unsafe impl UnsafeInt for u16 {}
unsafe impl UnsafeInt for u32 {}
unsafe impl UnsafeInt for u64 {}
unsafe impl UnsafeInt for usize {}
unsafe impl UnsafeInt for i8 {}
unsafe impl UnsafeInt for i16 {}
unsafe impl UnsafeInt for i32 {}
unsafe impl UnsafeInt for i64 {}
unsafe impl UnsafeInt for isize {}
pub trait ReadExt {
fn read<T: UnsafeInt>(&mut self) -> Result<T, std::io::Error>;
}
impl<R: Read> ReadExt for R {
fn read<T: UnsafeInt>(&mut self) -> Result<T, std::io::Error> {
let mut v = vec![0u8; std::mem::size_of::<T>()];
self.read_exact(&mut v).unwrap();
let result_in_le: T = unsafe {
std::mem::transmute_copy(&v[0])
};
Ok(T::from_le(result_in_le))
}
}
fn main() {
let buf = 0xffffffffu32.to_le_bytes();
let mut stream = BufReader::new(&buf[..]);
let x = ReadExt::read::<u32>(&mut stream).unwrap();
assert_eq!(x, 0xffffffffu32);
}
Playground
This guarantees that T is a primitive type, thereby making the transmute_copy sound.

Return only an owned type from a trait method that can accept an owned or borrowed value as input

I want to have a trait that can be implemented for T and &T but has methods that always return T.
What I would like to do is something like this
use std::borrow::ToOwned;
trait Foo<X: ToOwned> {
fn f(&self, x: X) -> f64;
fn g(&self) -> X::Owned;
}
struct Float(f64);
impl Foo<f64> for Float {
fn f(&self, x: f64) -> f64 {
x + self.0
}
fn g(&self) -> f64 {
self.0 * 2.0
}
}
struct List(Vec<f64>);
impl Foo<&Vec<f64>> for List {
fn f(&self, x: &Vec<f64>) -> f64 {
x.iter().sum()
}
// Error here - `&Vec<f64>` return type expected
fn g(&self) -> Vec<f64> {
self.0.iter().map(|&x| 2.0 * x).collect()
}
}
fn main() {
let float = Float(2.0);
println!("{} {}", float.f(3.0), float.g());
let list = List(vec![0.0, 1.0, 2.0]);
println!("{} {:?}", list.f(&vec![1.0, 2.0]), list.g());
}
I know that one option is to have a trait that defines the output type like so
trait FooReturn {
type Output;
}
trait Foo<X: FooReturn> {
fn f(&self, x: X) -> f64;
fn g(&self) -> X::Output;
}
then implement the trait for all relevant types, but I was wondering if there was a more standard/robust way to do this.
This is how you would do it once specialization is complete. Meanwhile, I couldn't even get a simple working example to compile on 1.55.0-nightly.
#![feature(specialization)]
trait MaybeOwned {
type Owned;
}
default impl<X> MaybeOwned for X {
type Owned = X;
}
impl<'a, X> MaybeOwned for &'a X {
type Owned = X;
}
trait Foo<X: MaybeOwned> {
fn f(&self, x: &X) -> f64;
fn g(&self) -> <X as MaybeOwned>::Owned;
}

What is the idiomatic way to handle the actual data and not care about how the data is protected/wrapped?

This is valid code:
use std::rc::Rc;
use std::sync::{Arc, Mutex};
fn foo(n: i32) {
println!("n = {}", n)
}
fn main() {
let a = 1;
let b = Rc::new(2);
let c = Mutex::new(3);
let d = Arc::new(Mutex::new(4));
foo(a);
foo(*b);
foo(*(c.lock().unwrap()));
foo(*((*d).lock().unwrap()));
}
Are there any traits (or anything else) that I can implement so that the function calls could simply become:
foo(a);
foo(b);
foo(c);
foo(d);
What is the Rust idiomatic way for handling the actual data and not caring about how the data is protected/wrapped?
As others have pointed out, it is a bad idea to ignore the fallibility of Mutex::lock. However for the other cases, you can make your function accept owned values and references transparently by using Borrow:
use std::borrow::Borrow;
use std::rc::Rc;
fn foo (n: impl Borrow<i32>) {
println!("n = {}", n.borrow())
}
fn main() {
let a = 1;
let b = Rc::new (2);
let c = &3;
foo (a);
foo (b);
foo (c);
}
Playground
Here is an extremely literal answer to your specific question. I wouldn't use it.
use std::{
rc::Rc,
sync::{Arc, Mutex},
};
fn foo(n: impl DontCare<Output = i32>) {
let n = n.gimme_it();
println!("n = {}", n)
}
fn main() {
let a = 1;
let b = Rc::new(2);
let c = Mutex::new(3);
let d = Arc::new(Mutex::new(4));
foo(a);
foo(b);
foo(c);
foo(d);
}
trait DontCare {
type Output;
fn gimme_it(self) -> Self::Output;
}
impl DontCare for i32 {
type Output = Self;
fn gimme_it(self) -> Self::Output {
self
}
}
impl<T: DontCare> DontCare for Mutex<T> {
type Output = T::Output;
fn gimme_it(self) -> Self::Output {
self.into_inner()
.expect("Lets first assume unwrap() will not panic")
.gimme_it()
}
}
impl<T: DontCare> DontCare for Rc<T> {
type Output = T::Output;
fn gimme_it(self) -> Self::Output {
match Rc::try_unwrap(self) {
Ok(v) => v.gimme_it(),
_ => unreachable!("Lets first assume unwrap() will not panic"),
}
}
}
impl<T: DontCare> DontCare for Arc<T> {
type Output = T::Output;
fn gimme_it(self) -> Self::Output {
match Arc::try_unwrap(self) {
Ok(v) => v.gimme_it(),
_ => unreachable!("Lets first assume unwrap() will not panic"),
}
}
}
The function signatures you've specified take ownership of the value. That will be highly painful, especially paired with any type that doesn't implement Copy.
There are a number of code paths that panic implicitly. I'm not a fan of baking in panics — I reserve that for algorithmic failures, not data-driven ones.
See also:
Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?
My answer is similar to Shepmaster's answer, but maybe a little more practical since it doesn't consume the argument to foo2 and it gives you a reference to the target instead of taking it out of the container.
I never have any luck implementing traits based on other traits so I didn't try to do that here.
use std::ops::Deref;
use std::rc::Rc;
use std::sync::{Arc, Mutex, MutexGuard};
fn foo(n: i32) {
println!("n = {}", n)
}
trait Holding<T> {
type Holder: Deref<Target = T>;
fn held(self) -> Self::Holder;
}
fn foo2<H: Holding<i32>>(x: H) {
let h = x.held();
println!("x = {}", *h);
}
impl<'a, T: 'a> Holding<T> for &'a T {
type Holder = &'a T;
fn held(self) -> Self::Holder {
self
}
}
impl<'a, T> Holding<T> for &'a Rc<T> {
type Holder = &'a T;
fn held(self) -> Self::Holder {
&**self
}
}
impl<'a, T> Holding<T> for &'a Mutex<T> {
type Holder = MutexGuard<'a, T>;
fn held(self) -> Self::Holder {
// this can panic
self.lock().unwrap()
}
}
impl<'a, T> Holding<T> for &'a Arc<Mutex<T>> {
type Holder = MutexGuard<'a, T>;
fn held(self) -> Self::Holder {
// this can panic
(*self).lock().unwrap()
}
}
fn main() {
let a = 1;
let b = Rc::new(2);
let c = Mutex::new(3);
let d = Arc::new(Mutex::new(4));
foo(a);
foo(*b);
foo(*(c.lock().unwrap()));
foo(*((*d).lock().unwrap()));
foo2(&a);
foo2(&b);
foo2(&c);
foo2(&d);
}

Parametric mutability

(Hi), I have tow questions concerning generics in rust:
1-I'm trying to port some C++ boost like concepts to rust (here an example with a 2D point):
#![feature(associated_types)]
pub trait Point2D {
type value_type;
fn x(&self) -> &<Self as Point2D>::value_type;
fn y(&self) -> &<Self as Point2D>::value_type;
}
#[deriving(Show)]
pub struct Point2<T> {
x : T,
y : T,
}
impl<T> Point2D for Point2<T> {
type value_type = T;
#[inline]
fn x(&self) -> &T {
&self.x
}
#[inline]
fn y(&self) -> &T {
&self.y
}
}
fn main(){
let mut p = Point2{x: 0i32, y : 0i32};
println!("p = {}", p);
//*p.x() = 1i32; //error: cannot assign to immutable dereference of `&`-pointer
}
Here what I want is that x() and y() return a reference to mutable T when T is mutable, and an immutable reference otherwise, is it possible ?
I saw some internals talks about parametric mutability but I didn't find any established RFC.
2- Is there any plans to add parametrization over numeric values (like template<size_t n>) to rust ?
thanks
Update: so I guest for now the only solution is something like that :
#![feature(associated_types)]
pub trait Point2D {
type value_type;
fn x_as_mut(&mut self) -> &mut <Self as Point2D>::value_type;
fn y_as_mut(&mut self) -> &mut <Self as Point2D>::value_type;
fn x_as_ref(&self) -> &<Self as Point2D>::value_type;
fn y_as_ref(&self) -> &<Self as Point2D>::value_type;
}
#[deriving(Show)]
pub struct Point2<T> {
x : T,
y : T,
}
impl<T> Point2D for Point2<T> {
type value_type = T;
#[inline]
fn x_as_mut(&mut self) -> &mut T {
&mut self.x
}
#[inline]
fn y_as_mut(&mut self) -> &mut T {
&mut self.y
}
#[inline]
fn x_as_ref(&self) -> &T {
&self.x
}
#[inline]
fn y_as_ref(&self) -> &T {
&self.y
}
}
trait Channel {
}
fn main(){
let mut p1 = Point2{x: 0i32, y : 0i32};
println!("p1 = {}", p1);
*p1.x_as_mut() = 1i32;
println!("p1 = {}", p1);
let p2 = Point2{x:0u8, y:10u8};
println!("p2 = {}", p2.y_as_ref());
}
Any cleaner way ?
There is no parametric mutability. I know that several people have expressed a strong desire for something along those lines, but I'm not aware of any actual plans as yet.
There is also no generic value parameters. I believe the core team definitely wants it, but it's not a priority right now.

Resources