-1

I have a trait for types which process data:

pub trait Stage<I, O>: Sized {}

Here, I and O represent the input and output data types respectively. I want to create an implementation of Stage which combines two other Stages:

pub struct CompoundStage<S0: Stage<_, _>, S1: Stage<_, _>>(S0, S1);

CompoundStage must itself be a Stage:

impl<S0: Stage<_, _>, S1: Stage<_, _>> Stage<S0::I, S1::O> for CompoundStage<S0, S1> {}

How can I constrain the type arguments of CompoundStage such that the “intermediate” type is consistent (i.e. S0::O == S1::I)? I know I could do it by adding another type parameter like below, but is there a cleaner way?

pub struct CompoundStage<S0: Stage<_, T>, S1: Stage<T, _>, T>(S0, S1);

impl<S0: Stage<_, T>, S1: Stage<T, _>, T> Stage<S0::I, S1::O> for CompoundStage<S0, S1, T> {}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
MTCoster
  • 5,868
  • 3
  • 28
  • 49
  • It's hard to answer your question because it doesn't include a [MRE]. The code you've provided isn't consistent with itself and fails to compile. It would make it easier for us to help you if you try to reproduce your error on the [Rust Playground](https://play.rust-lang.org) if possible, otherwise in a brand new Cargo project, then [edit] your question to include the additional info. There are [Rust-specific MRE tips](//stackoverflow.com/tags/rust/info) you can use to reduce your original code for posting here. Thanks! – Shepmaster Dec 02 '20 at 15:10

1 Answers1

3

You probably want a trait with associated types instead of generic types:

pub trait Stage: Sized {
    type I;
    type O;
}

pub struct CompoundStage<S0, S1>(S0, S1);

impl<S0, S1> Stage for CompoundStage<S0, S1>
where
    S0: Stage,
    S1: Stage<I = S0::O>,
{
    type I = S0::I;
    type O = S1::O;
}

See also:


If you must use generic types, you will need to introduce PhantomData:

use std::marker::PhantomData;

pub trait Stage<I, O>: Sized {}

pub struct CompoundStage<S0, S1, M>(S0, S1, PhantomData<M>);

impl<S0, S1, I, O, M> Stage<I, O> for CompoundStage<S0, S1, M>
where
    S0: Stage<I, M>,
    S1: Stage<M, O>,
{
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366