The following code:
use std::borrow::Cow;
struct Hip<'a> {
hip: Cow<'a, [u8]>
}
struct Hop<'a, T: ?Sized + 'a> {
hop: Cow<'a, T>
}
fn main() {
let it_be: Hop<[u8]> = [1, 2, 3];
}
Fails to build because "the trait Clone is not implemented for T".
Whereas expecting T to implement Clone (as follows):
struct Hop<'a, T: Clone + ?Sized + 'a> {
hop: Cow<'a, T>
}
Fails to build because "the trait Clone is not implemented for [u8]".
How come Hip, which is using a [u8], compiles, but not Hop?
Why does the compiler request Clone to be implemented for Hop's T, but not for Hip's [u8]?
On the Rust Playground
The documentation says the type should implement ToOwned.
The following works:
struct Hop<'a, T: ?Sized + ToOwned> {
hop: Cow<'a, T>
}
fn main() {
let it_be: Hop<[u8]> = Hop { hop: Cow::Owned(vec![1, 2, 3]) };
}
About the error message: the compiler generates the implementation of ToOwned for every type implementing Clone. So when the trait ToOwned is missing, it suggests to implement Clone.
This is a mistake because some types have good reasons to implement ToOwnedwithout implementing Clone. [u8] is one of them, hence Hip compiles. Whereas Hop's T was not bound to ToOwned, so it fails.
Related
Somewhat new to Trait implementation/usage:
If I declare a trait thus:
pub trait A: Debug + Clone {
fn as_base58_string(&self) -> String;
fn as_bytes(&self) -> [u8; 32];
}
With a concrete implementation:
impl A for P {
fn as_base58_string(&self) -> String {
self.to_base58_string()
}
fn as_bytes(&self) -> [u8; 32] {
self.to_bytes()
}
}
And have a function like:
pub fn print_akey(akey: &dyn A) {
println!("A{:?}", akey);
}
I am getting this error
the trait `A` cannot be made into an object`A` cannot be made into an object
Even though the concrete type P is cloneable?
If I remove Clone from the trait declaration the warning goes away/
Clone is not object safe. That means you cannot create a dyn Clone, and thus you cannot create dyn Trait for any Trait that has Clone as a supertrait.
The reason for that is that Clone::clone() returns Self, and one of the rules for object safe traits is that they must never mention the Self type (outside of &self or &mut self).
If you want to clone a trait object (dyn Trait), see How to clone a struct storing a boxed trait object?.
I am learning Rust and have run into the following problem, which is not obvious to me.
I saw a std::thread::spawn in the library, looked at the implementation, and saw that some type requires an implementation of the Send trait to be able to send something to another thread.
I'm trying to replicate the behavior with my own function and my own trait, but the compiler successfully compiles the code without complaining that the trait is not implemented for my types.
What am I missing?
pub trait SomeTrait {
fn bar(&self);
}
#[derive(Debug)]
struct StructWithoutTrait {
_data: Box<i32>
}
#[derive(Debug)]
struct StructWithTrait {
_data: Box<i32>
}
impl SomeTrait for StructWithTrait {
fn bar(&self) {}
}
fn foo<F, T>(f: F) -> T
where
F: FnOnce() -> T,
F: SomeTrait + 'static,
T: SomeTrait + 'static
{
f.bar();
f()
}
impl<F, T> SomeTrait for F
where
F: FnOnce() -> T,
T: SomeTrait
{
fn bar(&self) {}
}
fn main() {
let without_trait = StructWithoutTrait { _data: Box::new(1) };
let with_trait = StructWithTrait { _data: Box::new(2) };
let x = std::rc::Rc::new(1);
foo(move || {
println!("{:?}", without_trait);
println!("{:?}", x);
with_trait
});
}
Send is an auto trait. Auto-traits are somewhat like compiler-implemented; the steps of determining whether a type T implements an auto trait AutoTrait are the following:
If there is an explicit impl AutoTrait for T, then T always impls AutoTrait (note that because Send is an unsafe trait you need unsafe impl Send for T, but the general principle stays the same).
Otherwise, if there is a negative impl impl !AutoTrait for T, then T does not implement AutoTrait. Note that this is an error to have both positive and negative impl of the same trait for the same type.
Otherwise, if any of the fields of T does not implement AutoTrait, T does not implement it either. For example, if T is defined as struct T(U);, and there's impl !AutoTrait for U, then T does not implement AutoTrait.
Otherwise, T implements AutoTrait.
Both auto traits and negative impls are highly unstable features, and not intended to use as of now outside of the standard library. If you really want, you can, although because the compiler must be able to implement the trait automatically, it cannot contain any associated item (methods, associated types, associated consts). If you remove the bar() method, this is how your code will look like:
#![feature(auto_traits, negative_impls)]
pub auto trait SomeTrait {}
#[derive(Debug)]
struct StructWithoutTrait {
_data: Box<i32>
}
impl !SomeTrait for StructWithoutTrait {}
#[derive(Debug)]
struct StructWithTrait {
_data: Box<i32>
}
fn foo<F, T>(f: F) -> T
where
F: FnOnce() -> T,
F: SomeTrait + 'static,
T: SomeTrait + 'static
{
f()
}
fn main() {
let without_trait = StructWithoutTrait { _data: Box::new(1) };
let with_trait = StructWithTrait { _data: Box::new(2) };
let x = std::rc::Rc::new(1);
foo(move || {
println!("{:?}", without_trait);
println!("{:?}", x);
with_trait
});
}
Playground.
I am pretty sure that is compiler behaviour:
A closure is Send if all variables captured by non-unique immutable reference are Sync, and all values captured by unique immutable or mutable reference, copy, or move are Send.
~ https://doc.rust-lang.org/reference/types/closure.html
It is therefore not something you can really implement right now with how closure types are completely untransparent
Currently Send is handled specially by the the compiler. Quoting from the documentation:
This trait is automatically implemented when the compiler determines it’s appropriate.
There are plans to move the implementation fully into the standard library (tracking issue), which should make it possible to have similar user-defined marker traits. There is a chance that when this feature gets stabilized you might be able to write:
auto trait SomeTrait {}
struct StructWithTrait {}
struct StructWithoutTrait {}
impl !SomeTrait for StructWithoutTrait {}
and get a behaviour similar to Send.
First things first: What am I trying to achieve?
I'm trying to use Iterator::fold() with an accumulator that itself is an Iterator, but in addition I need a clone of that iterator internally.
fn whatever<T,U,V,W>(some_iterator : T, other_cloneable_iterator_init : U) -> impl Iterator<Item=W>
where T: Iterator<Item=V>,
U: Iterator<Item=W>+Clone
{
some_iterator.fold(other_cloneable_iterator_init,|other_cloneable_iterator, value| {
let computed_value =
some_function_that_consumes_an_iterator(other_cloneable_iterator.clone(), value);
other_iterator.filter(|other_value| some_function(computed_value, other_value))
}
}
This of course does not work as written above, because the return type of the closure given to fold is not the same as the type of the initializer.
Why did this problem lead to this question?
They do however have in common that they both implement the Iterator<Item=W>+Clone traits. This almost screams "erase the type by making it a trait object".
If it were just the Iterator<Item=W> trait, I'd do just that. However, the Clone trait is not object-safe. Searching for "clone boxed trait object" online yields various discussions, which all either require 'static lifetime on the trait object (what Iterators usually do not have), or using unsafe code (which I would like to avoid) like the dyn-clone crate.
The actual question:
So, if one wants to avoid using unsafe code, and does not have the luxury of getting 'static lifetimes, how can one implement Clone for a boxed trait object?
I'm talking about code like the following, which has lifetime issues and does not compile:
trait Cu32Tst<'a> : Iterator<Item=u32>+'a {
fn box_clone(&self) -> Box<dyn Cu32Tst+'a>;
}
impl<'a, T : Iterator<Item=u32>+Clone+'a> Cu32Tst<'a> for T {
fn box_clone(&self) -> Box<dyn Cu32Tst+'a> {
Box::new(self.clone())
}
}
impl<'a> Clone for Box<dyn Cu32Tst<'a>>{
fn clone(&self) -> Self {
self.box_clone()
}
}
The reason I want Clone on the Box itself is that in order to use it as accumulator type, I must be able to create a new Box<dyn IteratorTraitObject> out of the output of the Iterator::filter() method, which is only Clone if the iterator it's called on is Clone (I'd then have to implement Iterator for the Box as well then, but that could just forward to the contained value).
Long story short: Can Clone be implemented for a trait object with finite lifetime, and if yes, how?
You need to modify the code to implement Box<dyn Cu32Tst<'a>> rather than Box<dyn Cu32Tst + 'a>. The latter presumably implements Cu32Tst<'static>, which is not what you want for the blanket implementation of Clone for Cu32Tst<'a>. This compiles:
trait Cu32Tst<'a>: Iterator<Item = u32> + 'a {
fn box_clone(&self) -> Box<dyn Cu32Tst<'a>>;
}
impl<'a, T: Iterator<Item = u32> + Clone + 'a> Cu32Tst<'a> for T {
fn box_clone(&self) -> Box<dyn Cu32Tst<'a>> {
Box::new(self.clone())
}
}
impl<'a> Clone for Box<dyn Cu32Tst<'a>> {
fn clone(&self) -> Self {
self.as_ref().box_clone()
}
}
Playground
Note that the Clone implementation invokes box_clone() using self.as_ref().box_clone(). This is because the blanket impl of Cu32Tst matches against the Box<dyn Cu32Tst> as it's both Clone and Iterator, so the box itself gets a box_clone() method. As a result, self.box_clone() would compile, but would cause infinite recursion.
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.
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.