I'm trying to compile this piece of example code:
mod general {
// Shorthand for getting the OperationState type of an Operation with a given Session type
pub type StateOf<'s, A, Sess> = <A as HasOperationState<'s, Sess>>::State;
// Shorthand for getting the Session type of an Operation
pub type SessionOf<A> = <<A as Operation>::SessionLookup as SessionLookup>::Session;
pub trait SessionLookup {
type Session;
}
pub trait Operation: for<'s> HasOperationState<'s, SessionOf<Self>> {
type SessionLookup: SessionLookup + 'static;
}
pub trait OperationState<'s, Sess> {
fn session(&self) -> &Sess;
}
pub trait HasOperationState<'s, Sess> {
type State: OperationState<'s, Sess>;
}
pub struct PhantomOperation<T: Operation>(pub ::std::marker::PhantomData<T>);
}
mod specific {
use crate::general::*;
pub struct MySession {}
pub struct MySessionLookup {}
impl SessionLookup for MySessionLookup {
type Session = MySession;
}
pub trait MyOperationState {}
pub trait MyExtensionTrait {}
// This gives a compilation error:
//
// type annotations needed: cannot satisfy `<A as general::HasOperationState<'s, extension::MySession>>::State == _`
impl<'s, A> MyExtensionTrait for PhantomOperation<A>
where A: Operation<SessionLookup = MySessionLookup> + HasOperationState<'s, MySession>,
StateOf<'s, A, SessionOf<A>>: MyOperationState,
{
}
}
Rust playground link.
This code results in a compiler error that isn't very helpful for me:
type annotations needed: cannot satisfy `<A as general::HasOperationState<'s, extension::MySession>>::State == _`
I already filed a rust bug report about the (un)helpfulness of this error message (it's issue #76870), but now I'd like to figure out why this code doesn't type check.
The code compiles when I change the impl
of MyExtensionTrait
to:
impl<A> MyExtensionTrait for PhantomOperation<A>
where A: Operation<SessionLookup = MySessionLookup> + for<'a> HasOperationState<'a, SessionOf<A>>,
for<'b> StateOf<'b, A, SessionOf<A>>: MyOperationState
{
}
but when I then try to instantiate a trait object that implements MyExtensionTrait
like so:
struct SomeOperation {}
impl Operation for SomeOperation {
type SessionLookup = MySessionLookup;
}
struct SomeOperationState {}
impl<'s> OperationState<'s, MySession> for SomeOperationState {
fn session(&self) -> &MySession { &MySession {} }
}
impl<'s> HasOperationState<'s, MySession> for SomeOperation {
type State = SomeOperationState;
}
impl MyOperationState for SomeOperationState {}
fn create_my_extension_trait_instance() -> Box<dyn MyExtensionTrait> {
Box::new(PhantomOperation::<SomeOperation>(Default::default()))
}
The compiler complains that the MyOperationState
bound is not satisfied:
error[E0277]: the trait bound `for<'b> <SomeOperation as general::HasOperationState<'b, specific::MySession>>::State: MyOperationState` is not satisfied
--> src/lib.rs:75:5
|
75 | Box::new(PhantomOperation::<SomeOperation>(Default::default()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'b> MyOperationState` is not implemented for `<SomeOperation as general::HasOperationState<'b, specific::MySession>>::State`
|
= note: required because of the requirements on the impl of `specific::MyExtensionTrait` for `general::PhantomOperation<SomeOperation>`
= note: required for the cast to the object type `dyn specific::MyExtensionTrait`
Rust playground link.
I thought the type bound that the compiler is complaining about would be satisfied by this line
impl MyOperationState for SomeOperationState {}
but apparently it's not.
Any ideas on how I could satisfy that type bound, or reformulate the type bounds on the MyExtensionTrait
impl
to get this to compile?