I have the following structure:
struct MyStruct {
foo: Box<dyn Fn(usize) -> usize>
}
And I want to derive Clone for MyStruct. However, the compiler turns out error:
the trait bound `dyn std::ops::Fn(usize) -> usize: std::clone::Clone` is not satisfied
And for now (rustc 1.46.0), the dyn does not support addition of non-auto traits like Box<dyn Fn(usize) -> usize + Clone>.
From the rust-reference:
A closure is Clone or Copy if it does not capture any values by unique immutable or mutable reference, and if all values it captures by copy or move are Clone or Copy, respectively.
So I think this derivation makes sense in theory, but I don't know if I can do it for now.
I don't mind manually implementing Clone for MyStruct, but I don't know how to do it, either.
I don't want to do something like
#[derive(Clone)]
struct MyStruct<F: Fn(usize) -> usize> {
foo: F
}
because this struct is used as an associated type for an implementation of another struct for a trait, and both that struct and the trait has no generics, and I don't want to messed up with PhantomData.
Expanding on #mcarton comment above, but using the dyn-clone crate to overcome Clone not being object safe, the code is quite straightforward.
use dyn_clone::DynClone;
trait FnClone: DynClone {
fn call(&self, x: usize) -> usize;
}
impl<F> FnClone for F
where F: Fn(usize) -> usize + Clone
{
fn call(&self, x: usize) -> usize {
self(x)
}
}
struct MyStruct {
foo: Box<dyn FnClone>
}
impl Clone for MyStruct {
fn clone(&self) -> MyStruct {
MyStruct {
foo: dyn_clone::clone_box(&*self.foo),
}
}
}
fn main() {
let a = MyStruct{
foo: Box::new(|x| x + 1)
};
let b = a.clone();
println!("{} {}", a.foo.call(1), b.foo.call(2));
}
This crate also provides a macro clone_trait_object! to make the Clone derivable for the Box<dyn FnClone>, but you don't seem to want that.
Related
When I do cycle as
fn main() {
let mut a = vec![1,2].into_iter().cycle();
assert_eq!(a.next().unwrap(), 1);
assert_eq!(a.next().unwrap(), 2);
assert_eq!(a.next().unwrap(), 1);
assert_eq!(a.next().unwrap(), 2);
}
it works well as I expect.
But when I try to write generalized function as
pub fn cycle_generalized_func<T>(into_iter: T) -> impl Iterator<Item = T::Item>
where
T: IntoIterator,
T::Item: Clone,
{
into_iter.into_iter().cycle()
}
And try to use as
let mut a = cycle(vec![1,2]);
id does not compline and produce errors on into_iter.into_iter().cycle() row like:
the trait bound <T as IntoIterator>::IntoIter: Clone is not satisfied
the trait Clone is not implemented for <T as IntoIterator>::IntoIterrustcE0277
iterator.rs(3270, 23): required by a bound in std::iter::Iterator::cycle
main.rs(6, 19): consider further restricting the associated type: , <T as IntoIterator>::IntoIter: Clone
What do I do wrong? I have no idea how to fix it
The type of Iterator::cycle is:
fn cycle(self) -> Cycle<Self>ⓘ
where
Self: Clone
That is, it requires the iterator itself to be : Clone, not the Item. To fix your code, replace T::Item: Clone with T::IntoIter: Clone.
This compiles for me:
pub fn cycle_generalized_func<T>(into_iter: T) -> impl Iterator<Item = T::Item>
where
T: IntoIterator,
T::IntoIter: Clone,
{
into_iter.into_iter().cycle()
}
If you need this to work with iterators that are not Clone but the items are, you'll have to collect all items into a container like Vec first:
pub fn cycle_generalized_func<T>(into_iter: T) -> impl Iterator<Item = T::Item>
where
T: IntoIterator,
T::Item: Clone,
{
into_iter
.into_iter()
.collect::<Vec<_>>()
.into_iter()
.cycle()
}
I have a function that can handle both owned and borrowed values of some type Foo by accepting a Cow<'_, Foo>. However, I'd like to make it more convenient by allowing to pass in owned or borrowed Foos directly.
Is it possible to have a conversion trait to Cow that's implemented both on a reference type and its owned version?
This is what I tried:
trait Convert<'a> : Clone {
fn into_cow(self) -> Cow<'a, Self>;
}
// Works
impl<'a> Convert<'a> for Foo {
fn into_cow(self) -> Cow<'a, Self> {
println!("owned");
Cow::Owned(self)
}
}
// Doesn't work
impl<'a> Convert<'a> for &'a Foo {
fn into_cow(self) -> Cow<'a, Self> {
println!("borrowed");
Cow::Borrowed(self)
}
}
The borrowed version says that Borrowed expected a &&'a Foo but found a &'a Foo.
Self in the implementation of a trait for &Foo is &Foo, so into_cow() doesn't return the same type in both impls.
One solution would be to change the return type to Cow<'a, Foo>, but that of course limits the trait to only work on Foo.
A better way is to make the owned type a generic parameter of Convert like this:
trait Convert<'a, T: Clone> {
fn into_cow(self) -> Cow<'a, T>;
}
impl<'a, T: Clone> Convert<'a, T> for T {
fn into_cow(self) -> Cow<'a, T> {
println!("owned");
Cow::Owned(self)
}
}
impl<'a, T: Clone> Convert<'a, T> for &'a T {
fn into_cow(self) -> Cow<'a, T> {
println!("borrowed");
Cow::Borrowed(self)
}
}
fn take_foo<'a>(foo: impl Convert<'a, Foo>) {
let cow = foo.into_cow();
}
fn main() {
take_foo(&Foo{});
take_foo(Foo{});
}
Do you ever make use of the ownership, or always reborrow it? If only reborrowing, is std::convert::AsRef what you're looking for?
fn take_foo(foo: impl AsRef<Foo>) {
let foo: &Foo = foo.as_ref();
todo!();
}
I try to write my own RefCell-like mutable memory location but without runtime borrow checking (no overhead). I adopted the code architecture from RefCell (and Ref, and RefMut). I can call .borrow() without problems but if I call .borrow_mut() then the rust compiler says cannot borrow as mutable. I don't see the problem, my .borrow_mut() impl looks fine?
code that fails:
let real_refcell= Rc::from(RefCell::from(MyStruct::new()));
let nooverhead_refcell = Rc::from(NORefCell::from(MyStruct::new()));
// works
let refmut_refcell = real_refcell.borrow_mut();
// cannot borrow as mutable
let refmut_norefcell = nooverhead_refcell.borrow_mut();
norc.rs (No Overhead RefCell)
use crate::norc_ref::{NORefMut, NORef};
use std::cell::UnsafeCell;
use std::borrow::Borrow;
#[derive(Debug)]
pub struct NORefCell<T: ?Sized> {
value: UnsafeCell<T>
}
impl<T> NORefCell<T> {
pub fn from(t: T) -> NORefCell<T> {
NORefCell {
value: UnsafeCell::from(t)
}
}
pub fn borrow(&self) -> NORef<'_, T> {
NORef {
value: unsafe { &*self.value.get() }
}
}
pub fn borrow_mut(&mut self) -> NORefMut<'_, T> {
NORefMut {
value: unsafe { &mut *self.value.get() }
}
}
}
norc_ref.rs (data structure returned by NORefCell.borrow[_mut]()
use std::ops::{Deref, DerefMut};
#[derive(Debug)]
pub struct NORef<'b, T: ?Sized + 'b> {
pub value: &'b T,
}
impl<T: ?Sized> Deref for NORef<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
self.value
}
}
/// No Overhead Ref Cell: Mutable Reference
#[derive(Debug)]
pub struct NORefMut<'b, T: ?Sized + 'b> {
pub value: &'b mut T,
}
impl<T: ?Sized> Deref for NORefMut<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
self.value
}
}
impl<T: ?Sized> DerefMut for NORefMut<'_, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
self.value
}
}
NORefCell::borrow_mut() takes &mut self, which requires a DerefMut on the Rc in which it is wrapped. This won't work because Rc does not give mutable references just by asking nicely (you need it to check if the reference count is exactly one, otherwise there would be multiple mutable borrows).
borrow_mut has to take &self instead of &mut self.
As mentioned in my comment: What you are basically doing is providing a safe-looking abstraction around an UnsafeCell. This is incredibly dangerous. Notice the docs regarding UnsafeCell:
The compiler makes optimizations based on the knowledge that &T is not mutably aliased or mutated, and that &mut T is unique. UnsafeCell is the only core language feature to work around the restriction that &T may not be mutated.
You are providing a thin wrapper around this powerful object, with no unsafe on the API-boundary. The "No-overhead-RefCell" is really a "no-trigger-guard-foot-gun". It does work, yet be warned about its dangers.
This code works fine (playground):
use std::rc::Rc;
trait Foo {
fn foo(&self);
}
struct Bar<T> {
v: Rc<T>,
}
impl<T> Bar<T> where
T: Foo {
fn new(rhs: Rc<T>) -> Bar<T> {
Bar{v: rhs}
}
}
struct Zzz {
}
impl Zzz {
fn new() -> Zzz {
Zzz{}
}
}
impl Foo for Zzz {
fn foo(&self) {
println!("Zzz foo");
}
}
fn make_foo() -> Rc<Foo> {
Rc::new(Zzz{})
}
fn main() {
let a = Bar::new(Rc::new(Zzz::new()));
a.v.as_ref().foo()
}
but if I make a wrapper to generate Rc like below, the compiler complains about missing sized trait (playground)
fn make_foo() -> Rc<dyn Foo> {
Rc::new(Zzz::new())
}
fn main() {
let a = Bar::new(make_foo());
a.v.as_ref().foo()
}
in both cases, Bar::new received parameters with same type Rc, why the rust compiler reacts different?
By default, all type variables are assumed to be Sized. For example, in the definition of the Bar struct, there is an implicit Sized constraint, like this:
struct Bar<T: Sized> {
v: Rc<T>,
}
The object dyn Foo cannot be Sized since each possible implementation of Foo could have a different size, so there isn't one size that can be chosen. But you are trying to instantiate a Bar<dyn Foo>.
The fix is to opt out of the Sized trait for T:
struct Bar<T: ?Sized> {
v: Rc<T>,
}
And also in the context of the implementations:
impl<T: ?Sized> Bar<T>
where
T: Foo
?Sized is actually not a constraint, but relaxing the existing Sized constraint, so that it is not required.
A consequence of opting out of Sized is that none of Bar's methods from that impl block can use T, except by reference.
I'm trying to create a trait that should abstract over functions/closures with a different number of arguments. Something like this:
trait MyTrait {}
impl MyTrait for Box<Fn() -> &'static str> {}
impl MyTrait for Box<Fn(u8) -> u8> {}
Initially I planned to use it like this:
fn myf<F: MyTrait>(_fun: F) {}
fn main() {
myf(Box::new(|i: u8| i + 2))
}
But this code fails with error:
error[E0277]: the trait bound `std::boxed::Box<[closure#src/main.rs:11:18: 11:31]>: MyTrait` is not satisfied
When I cast the box like this, everything compiles correctly:
myf(Box::new(|i: u8| i + 2) as Box<Fn(_) -> _>)
Playground
Why can't the Rust compiler infer this trait without a cast? Is my approach (using cast) correct, or is there a simpler way? I prefer to enable trivial_casts warning for my projects and this syntax triggers it.
This is a thing that one tends to forget: each closure is a different struct that implements Fn: Fn is a trait, not a struct, and trait implementations are not transitive.
Here is a little example that shows this point:
trait Base {}
trait Derived {}
struct Foo {}
impl Base for Derived {}
impl Derived for Foo {}
fn myf<T>(_t: Box<T>)
where
T: Base + ?Sized,
{
}
fn main() {
let foo = Box::new(Foo {});
//myf(foo) // does not compile
myf(foo as Box<Derived>)
}
The thing you really wanted to do is:
trait MyTrait {}
impl<T> MyTrait for T
where
T: Fn() -> &'static str,
{
}
impl<T> MyTrait for T
where
T: Fn(u8) -> u8,
{
}
fn myf<F>(_fun: Box<F>)
where
F: MyTrait,
{
}
fn main() {
myf(Box::new(|i: u8| i + 2))
}
But this cannot compile because there are two conflicting implementations.