How to solve "cycle detected when computing the supertrait"? - rust

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()
}
}

Related

How to make type-erased version of a trait with associated type?

Say there is a collection trait that has an associated type for its items:
trait CollectionItem {
// ...
}
trait Collection {
type Item: CollectionItem;
fn get(&self, index: usize) -> Self::Item;
// ...
}
Can I somehow type-erase this into a type that uses dynamic dispatch for both the Collection and the CollectionItem trait? i.e. wrap it into something like the following:
struct DynCollection(Box<dyn Collection<Item=Box<dyn CollectionItem>>>);
impl DynCollection {
fn get(&self, index: usize) -> Box<dyn CollectionItem> {
// ... what to do here?
}
}
impl <C: Collection> From<C> for DynCollection {
fn from(c: C) -> Self {
// ... what to do here?
}
}
Playground
You can add a private, type-erased helper trait:
trait DynCollectionCore {
fn get_dyn(&self, index: usize) -> Box<dyn CollectionItem>;
}
impl<C> DynCollectionCore for C
where
C: ?Sized + Collection,
C::Item: 'static,
{
fn get_dyn(&self, index: usize) -> Box<dyn CollectionItem> {
Box::new(self.get(index))
}
}
Then use this to build a wrapper type:
struct DynCollection(Box<dyn DynCollectionCore>);
impl DynCollection {
fn new<C>(inner: C) -> Self
where
C: Collection + 'static,
C::Item: 'static,
{
Self(Box::new(inner))
}
}
impl Collection for DynCollection {
type Item = Box<dyn CollectionItem>;
fn get(&self, index: usize) -> Box<dyn CollectionItem> {
self.0.get_dyn(index)
}
}
// note: something like this is also needed for `Box<dyn CollectionItem>:
// CollectionItem` to be satisfied
impl<T: ?Sized + CollectionItem> CollectionItem for Box<T> {
// ...
}

cannot satisfy `_: Runnable<dyn A, Arc<Mutex<Option<Box<dyn A>>>>>`

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());
}

'move occurs because value has type' Rust error

I'm learning Rust and I don't udestrand what is the problem of the following code
pub enum BagEntryState {
UNUSED, USED, REMOVED
}
impl PartialEq for BagEntryState {
fn eq(&self, other: &Self) -> bool {
self == other
}
}
pub struct BagEntry< T: std::cmp::PartialEq + fmt::Display> {
state : BagEntryState,
value: T,
}
impl<'a, T: std::cmp::PartialEq + fmt::Display> BagEntry<T> {
pub fn new(value: T) -> BagEntry< T> {
BagEntry {
value,
state: BagEntryState::UNUSED,
}
}
pub fn value(self)->T {
self.value
}
}
impl<'a, T: std::cmp::PartialEq + fmt::Display> PartialEq for BagEntry<T> {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl<T: std::cmp::PartialEq + fmt::Display> fmt::Display for BagEntry<T> {
// This trait requires `fmt` with this exact signature.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value)
}
}
use core::fmt;
fn main() {
let my_bagentry = BagEntry::new(String::from("ciao"));
//println!("{}", my_bagentry.value());
let mut contVec : Vec<BagEntry<String>>=vec![];
contVec.push(my_bagentry);
println!("state ={}", contVec[0]);
println!("state ={}", contVec[0].value());
}
The code is not compiling becaus of the error:
54 | println!("state ={}", contVec[0].value());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `BagEntry<std::string::String>`, which does not implement the `Copy` trait
My guess is that the problem is that with value()
I'm exposing the struct inner value, but I cannot really understand where the problem is and how to solve it.
My aim is that BagEntry owns the value but I want safely expose it outside the struct
Basically what is happening:
pub fn value(self)->T {
self.value
}
Here -> T means that you are moving the struct field out of the struct. This is fine, but you cannot use your object anymore. You can verify this - you cannot call your println!("{}", my_bagentry.value()); twice in a row - after the first one the my_bagentry is invalidated.
If I understand correctly you want only to borrow the value out of the object. To do this you need change your method signature to borrowing one.
pub fn value(&self)-> &T {
&self.value
}
Now the call will only borrow on the object and the the resulting reference will have the lifetime of that borrow.

Why is the failure::Fail trait bound not satisfied by my Result type alias?

I'm trying to implement event hooks as demonstrated by "simple event hooks in Rust" while also using the Error + ErrorKind pattern of the failure crate.
This is a stripped down version of my code:
#[macro_use]
extern crate failure;
use failure::{Backtrace, Context, Error, Fail};
use std::fmt;
#[derive(Debug)]
pub struct PortalError {
inner: Context<PortalErrorKind>,
}
impl Fail for PortalError {
fn cause(&self) -> Option<&Fail> {
self.inner.cause()
}
fn backtrace(&self) -> Option<&Backtrace> {
self.inner.backtrace()
}
}
impl fmt::Display for PortalError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.inner, f)
}
}
#[derive(Copy, Clone, PartialEq, Debug, Fail)]
pub enum PortalErrorKind {
#[fail(display = "Unknown Error")]
Unknown,
}
//----------------------------------------------------------
pub type PortalResult<T> = Result<PortalError, T>;
pub trait Portal {
fn get_something(&self) -> PortalResult<Vec<u32>>;
}
//----------------------------------------------------------
pub trait FeedApi<'a> {
type T: FeedApi<'a>;
fn new<P: Portal + 'a>(portal: P) -> Result<Self::T, Error>;
}
//----------------------------------------------------------
pub struct Feedly<'a> {
portal: Box<Portal + 'a>,
}
impl<'a> FeedApi<'a> for Feedly<'a> {
type T = Feedly<'a>;
fn new<P: Portal + 'a>(portal: P) -> Result<Self::T, Error> {
Ok(Feedly {
portal: Box::new(portal),
})
}
}
impl<'a> Feedly<'a> {
pub fn demo_function(&self) -> Result<(), Error> {
let _ = self.portal.get_something().context(PortalErrorKind::Unknown)?;
Ok(())
}
}
fn main() {
println!("Hello, world!");
}
[dependencies]
failure = "0.1.1"
In a method of 'Feedly' I want to use the portal:
self.portal.get_something().context(PortalErrorKind::Unknown)?
But I get the following error:
error[E0599]: no method named `context` found for type `std::result::Result<PortalError, std::vec::Vec<u32>>` in the current scope
--> src/main.rs:67:45
|
67 | let _ = self.portal.get_something().context(PortalErrorKind::Unknown)?;
| ^^^^^^^
|
= note: the method `context` exists but the following trait bounds were not satisfied:
`std::result::Result<PortalError, std::vec::Vec<u32>> : failure::Fail`
`&std::result::Result<PortalError, std::vec::Vec<u32>> : failure::Fail`
`&mut std::result::Result<PortalError, std::vec::Vec<u32>> : failure::Fail`
Looking through the docs the failure::Fail trait has a bound 'static. And the method context has a bound Self: Sized.
I'm not sure which trait is not satisfied here. The boxed Portal is neither Sized nor 'static, but the returned result should be, right?
This is the first time I'm handling boxes and lifetimes in Rust.
pub type PortalResult<T> = Result<PortalError, T>;
Result has two type parameters: the success type and the error type. You have transposed them; you want:
pub type PortalResult<T> = Result<T, PortalError>;

Implementing PartialEq on a boxed trait

I have a Rust program which contains a number of different structs which all implement a trait called ApplyAction. Another struct, ActionList, contains a vector of boxed objects which implement ApplyAction. I would like to create some unit tests which compare ActionLists with one another.
There are a few different SO questions which deal with PartialEq on boxed traits, and I've used these to get some way towards an implementation. However, in the (simplified) code below (and on the Playground), the assertions in main() fail because the type ids of the objects passed to eq() differ. Why?
Also, this seems extremely complicated for such a simple use case -- is there an easier way to do this?
use std::any::TypeId;
use std::boxed::Box;
use std::fmt;
use std::mem::transmute;
#[derive(Debug, Eq, PartialEq)]
pub struct MyAction<T: fmt::Debug> {
label: T,
}
impl<T: fmt::Debug> MyAction<T> {
pub fn new(label: T) -> MyAction<T> {
MyAction { label: label }
}
}
pub trait ApplyAction<T: fmt::Debug + PartialEq>: fmt::Debug {
fn get_type(&self) -> TypeId;
fn is_eq(&self, other: &ApplyAction<T>) -> bool;
}
impl<T: fmt::Debug + Eq + 'static> ApplyAction<T> for MyAction<T> {
fn get_type(&self) -> TypeId {
TypeId::of::<MyAction<T>>()
}
fn is_eq(&self, other: &ApplyAction<T>) -> bool {
if other.get_type() == TypeId::of::<Self>() {
// Rust thinks that self and other are different types in the calls below.
let other_ = unsafe { *transmute::<&&ApplyAction<T>, &&Self>(&other) };
self.label == other_.label
} else {
false
}
}
}
impl<T: fmt::Debug + Eq + PartialEq + 'static> PartialEq for ApplyAction<T> {
fn eq(&self, other: &ApplyAction<T>) -> bool {
if other.get_type() == TypeId::of::<Self>() {
self.is_eq(other)
} else {
false
}
}
}
#[derive(Debug)]
pub struct ActionList<T: fmt::Debug> {
actions: Vec<Box<ApplyAction<T>>>,
}
impl<T: fmt::Debug + PartialEq> ActionList<T> {
pub fn new() -> ActionList<T> {
ActionList { actions: vec![] }
}
pub fn push<A: ApplyAction<T> + 'static>(&mut self, action: A) {
self.actions.push(Box::new(action));
}
}
impl<T: fmt::Debug + Eq + PartialEq + 'static> PartialEq for ActionList<T> {
fn eq(&self, other: &ActionList<T>) -> bool {
for (i, action) in self.actions.iter().enumerate() {
if **action != *other.actions[i] {
return false;
}
}
true
}
}
fn main() {
let mut script1: ActionList<String> = ActionList::new();
script1.push(MyAction::new("foo".to_string()));
let mut script2: ActionList<String> = ActionList::new();
script2.push(MyAction::new("foo".to_string()));
let mut script3: ActionList<String> = ActionList::new();
script3.push(MyAction::new("bar".to_string()));
assert_eq!(script1, script2);
assert_ne!(script1, script3);
}
In the impl<...> PartialEq for ApplyAction<T> you used TypeId::of::<Self>(); i.e. the type of the unsized trait object. That isn't what you wanted; but remove the if and directly call self.is_eq(other), and your code should be working.
Sadly your example requires a lot of code to implement ApplyAction<T> for MyAction<T> - and again for each other action type you might want to use.
I tried to remove that overhead, and with nightly features it is completely gone (and otherwise only a small stub remains):
Playground
// see `default impl` below
#![feature(specialization)]
// Any::<T>::downcast_ref only works for special trait objects (`Any` and
// `Any + Send`); having a trait `T` derive from `Any` doesn't allow you to
// coerce ("cast") `&T` into `&Any` (that might change in the future).
//
// Implementing a custom `downcast_ref` which takes any
// `T: Any + ?Sized + 'static` as input leads to another problem: if `T` is a
// trait that didn't inherit `Any` you still can call `downcast_ref`, but it
// won't work (it will use the `TypeId` of the trait object instead of the
// underlying (sized) type).
//
// Use `SizedAny` instead: it's only implemented for sized types by default;
// that prevents the problem above, and we can implement `downcast_ref` without
// worrying.
mod sized_any {
use std::any::TypeId;
// don't allow other implementations of `SizedAny`; `SizedAny` must only be
// implemented for sized types.
mod seal {
// it must be a `pub trait`, but not be reachable - hide it in
// private mod.
pub trait Seal {}
}
pub trait SizedAny: seal::Seal + 'static {
fn get_type_id(&self) -> TypeId {
TypeId::of::<Self>()
}
}
impl<T: 'static> seal::Seal for T {}
impl<T: 'static> SizedAny for T {}
// `SizedAny + ?Sized` means it can be a trait object, but `SizedAny` was
// implemented for the underlying sized type.
pub fn downcast_ref<From, To>(v: &From) -> Option<&To>
where
From: SizedAny + ?Sized + 'static,
To: 'static,
{
if TypeId::of::<To>() == <From as SizedAny>::get_type_id(v) {
Some(unsafe { &*(v as *const From as *const To) })
} else {
None
}
}
}
use sized_any::*;
use std::boxed::Box;
use std::fmt;
// `ApplyAction`
fn foreign_eq<T, U>(a: &T, b: &U) -> bool
where
T: PartialEq + 'static,
U: SizedAny + ?Sized + 'static,
{
if let Some(b) = downcast_ref::<U, T>(b) {
a == b
} else {
false
}
}
pub trait ApplyAction<T: 'static>: fmt::Debug + SizedAny + 'static {
fn foreign_eq(&self, other: &ApplyAction<T>) -> bool;
}
// requires `#![feature(specialization)]` and a nightly compiler.
// could also copy the default implementation manually to each `impl` instead.
//
// this implementation only works with sized `A` types; we cannot make
// `ApplyAction<T>` inherit `Sized`, as that would destroy object safety.
default impl<T: 'static, A: PartialEq + 'static> ApplyAction<T> for A {
fn foreign_eq(&self, other: &ApplyAction<T>) -> bool {
foreign_eq(self, other)
}
}
impl<T: 'static> PartialEq for ApplyAction<T> {
fn eq(&self, other: &ApplyAction<T>) -> bool {
self.foreign_eq(other)
}
}
// `MyAction`
#[derive(Debug, Eq, PartialEq)]
pub struct MyAction<T: fmt::Debug> {
label: T,
}
impl<T: fmt::Debug> MyAction<T> {
pub fn new(label: T) -> MyAction<T> {
MyAction { label: label }
}
}
impl<T: fmt::Debug + PartialEq + 'static> ApplyAction<T> for MyAction<T> {}
// `ActionList`
#[derive(Debug)]
pub struct ActionList<T> {
actions: Vec<Box<ApplyAction<T>>>,
}
impl<T: 'static> ActionList<T> {
pub fn new() -> ActionList<T> {
ActionList { actions: vec![] }
}
pub fn push<A: ApplyAction<T> + 'static>(&mut self, action: A) {
self.actions.push(Box::<A>::new(action));
}
}
impl<T: 'static> PartialEq for ActionList<T> {
fn eq(&self, other: &ActionList<T>) -> bool {
if self.actions.len() != other.actions.len() {
return false;
}
for (i, action) in self.actions.iter().enumerate() {
if **action != *other.actions[i] {
return false;
}
}
true
}
}
// `main`
fn main() {
let mut script1: ActionList<String> = ActionList::new();
script1.push(MyAction::new("foo".to_string()));
let mut script2: ActionList<String> = ActionList::new();
script2.push(MyAction::new("foo".to_string()));
let mut script3: ActionList<String> = ActionList::new();
script3.push(MyAction::new("bar".to_string()));
assert_eq!(script1, script2);
assert_ne!(script1, script3);
}
See also:
Object Safety

Resources