I designed a trait that can run things that are Lockable, that is, can be locked to produce Option<T>, and I implemented it for Arc<Mutex<Option<Box<T>>>>
use std::sync::{LockResult, PoisonError, MutexGuard, Arc, Mutex};
pub type LockableArc<T: ?Sized> = Arc<Mutex<Option<T>>>;
pub struct MutexGuardOptionRef<'a, T: ?Sized> {
pub mutex_guard: MutexGuard<'a, Option<Box<T>>>,
}
pub trait LockableOption<T: ?Sized>: Clone + Send {
fn lock(&self) -> LockResult<MutexGuardOptionRef<T>>;
}
pub trait Runnable<R: ?Sized, T: LockableOption<R> + Clone + Send + ?Sized> {
fn run(s: T) -> Result<(), ()>;
}
impl<T: ?Sized + Send> LockableOption<T> for LockableArc<Box<T>> {
fn lock(&self) -> LockResult<MutexGuardOptionRef<T>> {
unimplemented!()
}
}
pub trait A: Send{}
pub struct S{}
impl A for S{}
impl<R: A, T: LockableOption<R> + Clone + Send + 'static> Runnable<R, T>
for S
{
fn run(arc_rtsp: T) -> Result<(), ()> {
Ok(())
}
}
fn main() {
let r: LockableArc<Box<dyn A>> = Arc::new(Mutex::new(Some(Box::new(S{}))));
Runnable::run(r.clone());
//Runnable::<dyn A, LockableArc<Box<dyn A>>>::run(r.clone());
}
Playground
Error:
error[E0283]: type annotations needed
--> src/main.rs:39:5
|
14 | fn run(s: T) -> Result<(), ()>;
| ------------------------------- required by `Runnable::run`
...
39 | Runnable::run(r.clone());
| ^^^^^^^^^^^^^ cannot infer type
|
= note: cannot satisfy `_: Runnable<dyn A, Arc<Mutex<Option<Box<dyn A>>>>>`
I don't understand this error. First because I don't know what '_ is. It looks like it's the type passed to run as the only argument. So I tried to force the type:
Runnable::<dyn A, LockableArc<Box<dyn A>>>::run(r.clone());
but I get the same error. What is happening?
Runnable is a trait, so Runnable::run does not know which implementation of that trait to use. Use S::run instead.
S::run won't work because its implementation of Runnable requires that R: A whereas here R is dyn A. Just restrict R: ?Sized instead and you should be fine.
Therefore (playground):
use std::sync::{LockResult, PoisonError, MutexGuard, Arc, Mutex};
pub type LockableArc<T: ?Sized> = Arc<Mutex<Option<T>>>;
pub struct MutexGuardOptionRef<'a, T: ?Sized> {
pub mutex_guard: MutexGuard<'a, Option<Box<T>>>,
}
pub trait LockableOption<T: ?Sized>: Clone + Send {
fn lock(&self) -> LockResult<MutexGuardOptionRef<T>>;
}
pub trait Runnable<R: ?Sized, T: LockableOption<R> + Clone + Send + ?Sized> {
fn run(s: T) -> Result<(), ()>;
}
impl<T: ?Sized + Send> LockableOption<T> for LockableArc<Box<T>> {
fn lock(&self) -> LockResult<MutexGuardOptionRef<T>> {
unimplemented!()
}
}
pub trait A: Send{}
pub struct S{}
impl A for S{}
impl<R: ?Sized, T: LockableOption<R> + Clone + Send + 'static> Runnable<R, T>
for S
{
fn run(arc_rtsp: T) -> Result<(), ()> {
Ok(())
}
}
fn main() {
let r: LockableArc<Box<dyn A>> = Arc::new(Mutex::new(Some(Box::new(S{}))));
S::run(r.clone());
}
Related
Given a struct and trait:
// Minimal version of the actual data structure and trait
trait MyTrait {
fn blub(&mut self);
}
struct MyStruct;
impl MyTrait for MyStruct {
fn blub(&mut self) {
println!("Blub!");
}
}
I would like to create a struct that can hold an object that implements MyTrait:
impl<T> Foo<T>
where
T: MyTrait,
{
fn new(t: T) -> Self {
Self { t }
}
fn run(&mut self) {
// Execute `blub` of `t`.
// Something like:
self.t.blub();
}
}
So far, that's easy. Now comes the crux: I want to accept both owned and mutably referenced types, like this:
fn main() {
let t0 = MyStruct;
let mut f0 = Foo::new(t0);
f0.run();
let mut t1 = MyStruct;
let mut f1 = Foo::new(&mut t1);
f1.run();
}
The code here of course doesn't work, because &mut MyStruct does not implement MyTrait.
In theory, this should be possible though, because MyTrait::blub takes &mut self, which is compatible with both owned and mutably borrowed types.
This is how far I've come. It works, but has two problems:
It has a pointless second generic
It requires PhantomData
use std::{borrow::BorrowMut, marker::PhantomData};
// Minimal version of the actual data structure and trait
trait MyTrait {
fn blub(&mut self);
}
struct MyStruct;
impl MyTrait for MyStruct {
fn blub(&mut self) {
println!("Blub!");
}
}
// Object that shall carry objects OR mutable references of type `MyTrait`
struct Foo<T, U> {
t: T,
_p: PhantomData<U>,
}
impl<T, U> Foo<T, U>
where
T: BorrowMut<U>,
U: MyTrait,
{
fn new(t: T) -> Self {
Self { t, _p: PhantomData }
}
fn run(&mut self) {
self.t.borrow_mut().blub();
}
}
fn main() {
let t0 = MyStruct;
let mut f0 = Foo::new(t0);
f0.run();
let mut t1 = MyStruct;
let mut f1: Foo<_, MyStruct> = Foo::new(&mut t1);
f1.run();
}
Blub!
Blub!
Is there a way to implement this more elegantly?
The only other elegant-ish way I have seen so far is to impl MyTrait for &mut MyStruct. Sadly, I do not own the trait or type, so I cannot do that. Although please tell me if my attempts here are misguided and this entire thing is an XY problem; and the actual thing I should do is to report this problem in said library so they can add that impl.
The simplest way is probably to add another implantation of MyTrait for &mut MyStruct.
impl MyTrait for &mut MyStruct {
fn blub(&mut self) {
println!("Blub!");
}
}
If you dont have access to the struct or trait, you can use an enum to manage the Owned and Borrowed versions and implement Deref/DerefMut to keep the usage of t the same.
enum Container<'a, T> {
Owned(T),
Borrowed(&'a mut T)
}
impl<'a, T: MyTrait> From<T> for Container<'a, T> {
fn from(t: T) -> Self {
Self::Owned(t)
}
}
impl<'a, T: MyTrait> From<&'a mut T> for Container<'a, T> {
fn from(t: &'a mut T) -> Self {
Self::Borrowed(t)
}
}
impl<'a, T> Deref for Container<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match self {
Self::Owned(o) => o,
Self::Borrowed(o) => o
}
}
}
impl<'a, T> DerefMut for Container<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
Self::Owned(o) => o,
Self::Borrowed(o) => o
}
}
}
struct Foo<'a, T> {
t: Container<'a, T>
}
impl<'a, T> Foo<'a, T>
where
T: MyTrait,
{
fn new(t: impl Into<Container<'a, T>>) -> Self {
Self{ t: t.into() }
}
fn run(&mut self) {
self.t.blub();
}
}
Other solutions I found:
This one doesn't require looking at an enum at runtime, it solves types at compile time:
use std::marker::PhantomData;
// Minimal version of the actual data structure and trait
trait MyTrait {
fn blub(&mut self);
}
struct MyStruct;
impl MyTrait for MyStruct {
fn blub(&mut self) {
println!("Blub!");
}
}
trait MyTraitFrom<'a, T> {
fn mytrait_from(value: &'a mut T) -> Self;
}
impl<'a, T: MyTrait> MyTraitFrom<'a, T> for &'a mut T {
fn mytrait_from(value: &'a mut T) -> Self {
value
}
}
impl<'a, T: MyTrait> MyTraitFrom<'a, &'a mut T> for &'a mut T {
fn mytrait_from(value: &'a mut &'a mut T) -> Self {
let value: &'a mut T = value;
value
}
}
struct Foo<T, U> {
t: T,
_p: PhantomData<U>,
}
impl<'a, T: 'a, U: 'a> Foo<T, U>
where
&'a mut U: MyTraitFrom<'a, T>,
U: MyTrait,
{
fn new(t: T) -> Self {
Self { t, _p: PhantomData }
}
fn run(&'a mut self) {
let u: &'a mut U = MyTraitFrom::mytrait_from(&mut self.t);
u.blub();
}
}
fn main() {
let t0 = MyStruct;
let mut f0 = Foo::new(t0);
f0.run();
let mut t1 = MyStruct;
let mut f1 = Foo::new(&mut t1);
f1.run();
}
Blub!
Blub!
On the code below, you can see that I forced the implementation of A for everything that implements AsRef<[T]> and Index[T], so B should implement it, because it implements both of these. However this is not the case. Why?
use std::convert::{AsMut, AsRef};
use std::ops::{Index, IndexMut};
use std::slice::SliceIndex;
pub trait A<T, I: SliceIndex<[T], Output = T>>:
AsRef<[T]> + Index<I, Output = T>
{
fn len(&self) -> usize;
}
impl<
T: AsRef<[T]> + Index<I, Output = T>,
I: SliceIndex<[T], Output = T>,
> A<T, I> for T
{
fn len(&self) -> usize {
self.as_ref().len()
}
}
struct B<'a, T>{
data: &'a mut [T]
}
impl<'a, T> AsRef<[T]> for B<'a, T> {
fn as_ref(&self) -> &[T] {
self.data
}
}
impl<'a, T, I: SliceIndex<[T], Output = T>> Index<I> for B<'a, T> {
type Output = T;
fn index(
&self,
v: I,
) -> &Self::Output {
&self.as_ref()[v]
}
}
fn something<'a, T>(r: &'a mut[T]) -> Box<dyn A<T, usize>> {
let a = B{data: r};
Box::new(a)
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=aa2353139f3d097e2497ed700d678ed3
Error:
error[E0277]: the trait bound `B<'_, T>: A<T, usize>` is not satisfied
--> src/lib.rs:46:5
|
46 | Box::new(a)
| ^^^^^^^^^^^ the trait `A<T, usize>` is not implemented for `B<'_, T>`
|
= note: required for the cast to the object type `dyn A<T, usize, Output = T>`
You need to introduce an additional type parameter on the blanket impl for A:
impl<T, I, V> A<T, I> for V
where
V: AsRef<[T]> + Index<I, Output = T>,
I: SliceIndex<[T], Output = T>,
{
fn len(&self) -> usize {
self.as_ref().len()
}
}
After fixing that, you'll get a lifetime error since the trait object returned in the box infers a 'static lifetime, so you'll need to bind it to the input slice's 'a lifetime.
fn something<'a, T>(r: &'a mut [T]) -> Box<dyn A<T, usize> + 'a> {
let a = B { data: r };
Box::new(a)
}
I was playing with the code from this answer but the FromIterator impl does not compile any more:
error[E0276]: impl has stricter requirements than trait --> src/lib.rs:184:9
| 184 | fn from_iter<I: IntoIterator<Item = T> + 'a>(itrbl: I) -> LazyList<'a, T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `I: 'a`
For more information about this error, try `rustc --explain E0276`.
The slightly updated code is on the playground.
// only necessary because Box<FnOnce() -> R> doesn't work...
mod thunk {
pub trait Invoke<R = ()> {
fn invoke(self: Box<Self>) -> R;
}
impl<R, F: FnOnce() -> R> Invoke<R> for F {
#[inline(always)]
fn invoke(self: Box<F>) -> R { (*self)() }
}
}
// Lazy is lazily evaluated contained value using the above Invoke trait
// instead of the desire Box<FnOnce() -> T> or a stable FnBox (currently not)...
pub mod lazy {
use crate::thunk::Invoke;
use std::cell::UnsafeCell;
use std::mem::replace;
use std::ops::Deref;
// Lazy is lazily evaluated contained value using the above Invoke trait
// instead of the desire Box<FnOnce() -> T> or a stable FnBox (currently not)...
pub struct Lazy<'a, T: 'a>(UnsafeCell<LazyState<'a, T>>);
enum LazyState<'a, T: 'a> {
Unevaluated(Box<dyn Invoke<T> + 'a>),
EvaluationInProgress,
Evaluated(T),
}
use self::LazyState::*;
impl<'a, T: 'a> Lazy<'a, T> {
#[inline]
pub fn new<F: 'a + FnOnce() -> T>(func: F) -> Lazy<'a, T> {
Lazy(UnsafeCell::new(Unevaluated(Box::new(func))))
}
#[inline]
pub fn evaluated(val: T) -> Lazy<'a, T> {
Lazy(UnsafeCell::new(Evaluated(val)))
}
#[inline(always)]
fn force(&self) {
unsafe {
match *self.0.get() {
Evaluated(_) => {}, // nothing required; already Evaluated
EvaluationInProgress => panic!("Lazy::force called recursively!!!"),
_ => {
let ue = replace(&mut *self.0.get(), EvaluationInProgress);
if let Unevaluated(thnk) = ue {
*self.0.get() = Evaluated(thnk.invoke());
} // no other possiblity!
}
}
}
}
#[inline]
pub fn unwrap<'b>(self) -> T where T: 'b { // consumes the object to produce the value
self.force(); // evaluatate if not evealutated
match { self.0.into_inner() } {
Evaluated(v) => v,
_ => unreachable!() // previous code guarantees never not Evaluated
}
}
}
impl<'a, T: 'a> Deref for Lazy<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
self.force(); // evaluatate if not evalutated
match *unsafe { &*self.0.get() } {
Evaluated(ref v) => v,
_ => unreachable!(),
}
}
}
}
// LazyList is an immutable lazily-evaluated persistent (memoized) singly-linked list
// similar to lists in Haskell, although here only tails are lazy...
// depends on the contained type being Clone so that the LazyList can be
// extracted from the reference-counted Rc heap objects in which embedded.
pub mod lazylist {
use crate::lazy::Lazy;
use std::rc::Rc;
use std::iter::FromIterator;
use std::mem::{replace, swap};
#[derive(Clone)]
pub enum LazyList<'a, T: 'a + Clone> {
Empty,
Cons(T, RcLazyListNode<'a, T>),
}
pub use self::LazyList::Empty;
use self::LazyList::Cons;
type RcLazyListNode<'a, T> = Rc<Lazy<'a, LazyList<'a, T>>>;
// impl<'a, T:'a> !Sync for LazyList<'a, T> {}
impl<'a, T: 'a + Clone> LazyList<'a, T> {
#[inline]
pub fn singleton(v: T) -> LazyList<'a, T> {
Cons(v, Rc::new(Lazy::evaluated(Empty)))
}
#[inline]
pub fn cons<F>(v: T, cntf: F) -> LazyList<'a, T>
where F: 'a + FnOnce() -> LazyList<'a, T>
{
Cons(v, Rc::new(Lazy::new(cntf)))
}
#[inline]
pub fn head(&self) -> &T {
if let Cons(ref hd, _) = *self {
return hd;
}
panic!("LazyList::head called on an Empty LazyList!!!")
}
#[inline]
pub fn tail<'b>(&'b self) -> &'b Lazy<'a, LazyList<'a, T>> {
if let Cons(_, ref rlln) = *self {
return &*rlln;
}
panic!("LazyList::tail called on an Empty LazyList!!!")
}
#[inline]
pub fn unwrap(self) -> (T, RcLazyListNode<'a, T>) {
// consumes the object
if let Cons(hd, rlln) = self {
return (hd, rlln);
}
panic!("LazyList::unwrap called on an Empty LazyList!!!")
}
#[inline]
fn iter(&self) -> Iter<'a, T> {
Iter(self)
}
}
impl<'a, T: 'a + Clone> Iterator for LazyList<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match replace(self, Empty) {
Cons(hd, rlln) => {
let mut newll = (*rlln).clone();
swap(self, &mut newll); // self now contains tail, newll contains the Empty
Some(hd)
}
_ => None,
}
}
}
pub struct Iter<'a, T: 'a + Clone>(*const LazyList<'a, T>);
impl<'a, T: 'a + Clone> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
unsafe {
if let LazyList::Cons(ref v, ref r) = *self.0 {
self.0 = &***r;
Some(v)
} else {
None
}
}
}
}
impl<'i, 'l, T: 'i + Clone> IntoIterator for &'l LazyList<'i, T> {
type Item = &'i T;
type IntoIter = Iter<'i, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T: 'a + Clone, > FromIterator<T> for LazyList<'a, T> {
fn from_iter<I: IntoIterator<Item = T> + 'a>(itrbl: I) -> LazyList<'a, T> {
let itr = itrbl.into_iter();
#[inline(always)]
fn next_iter<'b, R, Itr>(mut iter: Itr) -> LazyList<'b, R>
where R: 'b + Clone,
Itr: 'b + Iterator<Item = R>
{
match iter.next() {
Some(val) => LazyList::cons(val, move || next_iter(iter)),
None => Empty,
}
}
next_iter(itr)
}
}
}
Unfortunately I've exhausted ideas on how to try and fix this.
The code in the question (though not in the referenced answer, which has since been updated) relies on a soundness bug in older versions of the compiler (#18937) which has since been fixed.
It is not possible to implement FromIterator for LazyList, or indeed for any data structure, by storing the iterator inside the structure. This is because the FromIterator trait allows the implementor (Self) to outlive the iterator type (I::IntoIter). That the compiler ever accepted it was an oversight.
When copying code from the internet, be conscious of the age of the source. This code is also out of date in several other respects, notably:
it uses Rust 2015-style paths
it omits dyn on trait object types
the Invoke workaround is no longer needed, since dyn FnOnce() -> T works properly now.
I have a trait Component with an associated type Msg:
trait Component {
type Msg;
fn update(&self, msg: Self::Msg);
}
I modified it to implement a clone:
trait Component: ComponentClone<Self::Msg> {
type Msg;
fn update(&self, msg: Self::Msg);
}
pub trait ComponentClone<T> {
fn clone_box(&self) -> Box<dyn Component<Msg = T>>;
}
impl<T, M> ComponentClone<M> for T
where
T: 'static + Component<M> + Clone,
{
fn clone_box(&self) -> Box<dyn Component<M>> {
Box::new(self.clone())
}
}
impl<M: 'static> Clone for Box<dyn Component<M>> {
fn clone(&self) -> Box<dyn Component<M>> {
self.clone_box()
}
}
playground
I got an error:
error[E0391]: cycle detected when computing the supertraits of `Component`
--> src/lib.rs:1:1
|
1 | trait Component: ComponentClone<Self::Msg> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: ...which again requires computing the supertraits of `Component`, completing the cycle
note: cycle used when collecting item types in top-level module
--> src/lib.rs:1:1
|
1 | trait Component: ComponentClone<Self::Msg> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If I try to use generics, everything compiles (but I do get warnings):
trait Component<M>: ComponentClone<M> {
fn update(&self, msg: M);
}
pub trait ComponentClone<T> {
fn clone_box(&self) -> Box<dyn Component<T>>;
}
impl<T, M> ComponentClone<M> for T
where
T: 'static + Component<M> + Clone,
{
fn clone_box(&self) -> Box<dyn Component<M>> {
Box::new(self.clone())
}
}
impl<M: 'static> Clone for Box<dyn Component<M>> {
fn clone(&self) -> Box<dyn Component<M>> {
self.clone_box()
}
}
What's wrong? How to solve this problem?
While the code given contains other errorrs I'll focus on the question in particular situation.
When you have a trait bound which depends on an associated type in the trait being defined, provide a full path (aka UFCS) to the associated type:
trait Component: ComponentClone<<Self as Component>::Msg> {
// ^^^^^^^^^^^^^^^^^^^^^^^^ use a full path to Msg
type Msg;
fn update(&self, msg: Self::Msg);
}
pub trait ComponentClone<T> {
/* snip */
}
Related issue rust-lang/rust#62581 "Cycle computing supertraits" error could be more helpful #62581
Maybe you can get away by moving Msg into an own trait:
pub trait ComponentMsg {
type Msg;
}
pub trait Component : ComponentClone + ComponentMsg {
fn update(&self, msg: Self::Msg);
}
pub trait ComponentClone : ComponentMsg {
fn clone_box(&self) -> Box<dyn Component<Msg=Self::Msg>>;
}
impl<T, M> ComponentClone for T
where
T: 'static + Component<Msg=M> + Clone,
{
fn clone_box(&self) -> Box<dyn Component<Msg=M>> {
Box::new(self.clone())
}
}
impl<M: 'static> Clone for Box<dyn Component<Msg=M>> {
fn clone(&self) -> Box<dyn Component<Msg=M>> {
self.clone_box()
}
}
I have a binary trait Resolve.
pub trait Resolve<RHS = Self> {
type Output;
fn resolve(self, rhs: RHS) -> Self::Output;
}
I implemented the trait for something trivial where both arguments are taken by reference (self is &'a Foo and rhs is &'b Foo):
struct Foo;
impl <'a, 'b> Resolve<&'b Foo> for &'a Foo {
type Output = Foo;
fn resolve(self, rhs: &'b Foo) -> Self::Output {
unimplemented!()
}
}
If I now write
fn main() {
let a: &Foo = &Foo;
let b = Foo;
a.resolve(&b);
}
it will compile just fine, but if I try to implement it on my struct Signal, it will not work.
pub struct Signal<'a, T> {
ps: Vec<&'a T>,
}
impl<'a, T: Resolve<&'a T, Output = T> + 'a> Signal<'a, T> {
pub fn foo(&mut self) {
let a: &T = &self.ps[0];
let b = &self.ps[1];
a.resolve(b);
}
}
error[E0507]: cannot move out of borrowed content
--> src/main.rs:25:9
|
25 | a.resolve(b);
| ^ cannot move out of borrowed content
How do I get this example working? (playground)
The trait bound on foo only says that T implements Resolve, but you try to call .resolve() on a value of type &T.
To say, instead, that references to T must implement Resolve, you need a higher-ranked trait bound:
impl<'a, T> Signal<'a, T>
where
for<'b> &'b T: Resolve<&'a T, Output = T>,
{
pub fn foo(&mut self) { ... }
}
After thinking about this I came up with a simpler solution that does not rely on HRTB.
impl<'a, T> Signal<'a, T>
where
&'a T: Resolve<&'a T, Output = T> + 'a,
{
pub fn foo(&mut self) {
let a: &T = &self.ps[0];
let b = &self.ps[1];
a.resolve(b);
}
}
This does the same, namely describe, that &T implements Resolve, but without the need of HRTB.
You have to use the where clause for this, but apart from that this is a nice and easy solution.