Hi community,
I'm fiddling with c++ p2300 proposal in Rust and have an issue about cycling generic bounds.
In short, I have the following requirements:
-
S
is a sender withS::Output
to specify it's output, while 'R' is a receiver withR::Value
to specify it's input. - Normally,
S::Output
should equal toR::Value
to be able to pass the value fromS
toR
- But in this case, I need to add an
F
which isFnOnce
betweenS
andR
to harmony their requirements. For example, ifS::Output = String
,F: FnOnce(String) -> i32
andR::Value = i32
, then it's still workable.
Now comes the issue. Here I add one wrap receiver ThenReceiver
which wraps F
and R
in order to apply F
before passing to R
, and S
need to make sure it's output is compatible with R
after applying the transform F
- In implementation of
ThenReceiver
, it makes sure the inputI
can be transformer byF: FnOnce(I) -> O
, and can be fed intoR
with boundR: SetValue<Value = O>
pub trait SetValue {
type Value;
fn set_value(self, value: Self::Value);
}
pub struct ThenReceiver<I, F, R> {
func: F,
receiver: R,
_phantom: PhantomData<I>,
}
impl<I, F, R, O> SetValue for ThenReceiver<I, F, R>
where
F: FnOnce(I) -> O,
R: SetValue<Value = O>,
{
type Value = I;
fn set_value(self, value: Self::Value) {
self.receiver.set_value((self.func)(value));
}
}
- Here is what I get the cycling issue whem compiling (exec-rs/then.rs at master · npuichigo/exec-rs · GitHub). Since
ThenReceiver
already takes over connectingF
's output toR
's input, it's quite straightforward that what I need to do here is specifying the input generic argument ofThenReceiver
withS::Output
. But the compile complains with cycling issues.
pub trait Sender<R> {
type Output;
type Operation: OperationState;
fn connect(self, receiver: R) -> Self::Operation;
}
impl<S, F, R, O> Sender<R> for Then<S, F>
where
S: Sender<ThenReceiver<S::Output, F, R>>,
F: FnOnce(S::Output) -> O,
R: SetValue<Value = O>,
{
type Output = O;
type Operation = ThenOperation<S::Operation>;
fn connect(self, receiver: R) -> Self::Operation {
ThenOperation {
operation: self.sender.connect(ThenReceiver {
func: self.func,
receiver,
_phantom: Default::default(),
}),
}
}
}
error[E0391]: cycle detected when computing the bounds for type parameter `S`
--> exec\src\adaptors\then.rs:49:28
|
49 | S: Sender<ThenReceiver<S::Output, F, R>>,
| ^^^^^^^^^
|
= note: ...which immediately requires computing the bounds for type parameter `S` again
I think the idea is really simpile to express by traits and bounds, but it seems that I just cannot rely on S
's associated types when adding bound to itself.
Really need your helps. Thanks!