简体   繁体   中英

Complex trait requirements on struct

I have a fairly complex trait set up and I'm having trouble lining the pieces up. Right now it looks roughly like this:

/// Trait for models which can be gradient-optimized.
pub trait Optimizable {
    type Data;
    type Target;

    // The contract //
}

/// Trait for optimization algorithms.
pub trait OptimAlgorithm<M : Optimizable> {

    // The contract //
}

Now I want to be able to allow a struct implementing OptimAlgorithm to be a field in a struct implementing Optimizable . This would look something like this:

/// Model struct
pub struct Model<A: OptimAlgorithm<Self>> {
    alg: A,
}

impl Optimizable for Model<A> {
...
}

This doesn't work as the Self reference on the struct is nonsense. I tried using associated types for OptimAlgorithm but I need the algorithms to be generic over the models so this doesn't work. Is there a magic syntax I'm missing or does this need an overhaul?

Edit --

Here's a minimal example which shows error E0275 as described in Steven's answer. It's a little closer to my source code but less messy.

Just use Model<A> instead of Self . Self is only really useful in traits where one needs to be able to refer to the concrete type implementing the trait. Here, the concrete type is always Model<A> .

pub trait Optimizable {
    type Data;
    type Target;

    // The contract //
}

/// Trait for optimization algorithms.
pub trait OptimAlgorithm<M: Optimizable> {

    // The contract //
}
pub struct Model<A> where A: OptimAlgorithm<Model<A>> {
    alg: A,
}

impl<A> Optimizable for Model<A>
    where A: OptimAlgorithm<Model<A>>
{
    type Data = ();
    type Target = ();
}

In response to your updated code, the lifetime appears to be giving rust trouble. It appears you can make this work by using a higher-ranked lifetime but I don't know why.

pub trait Optimizable {
    type Data;
    type Target;

    // The contract //
}

/// Trait for optimization algorithms.
pub trait OptimAlgorithm<M: Optimizable> {

    // The contract //
}

pub struct Algorithm;

impl Default for Algorithm {
    fn default() -> Algorithm { Algorithm }
}

impl<M: Optimizable> OptimAlgorithm<M> for Algorithm {

}


pub struct Model<'a, A> where for<'b> A: OptimAlgorithm<Model<'b, A>> {
    layer_sizes: &'a [usize],
    alg: A,
}

impl<'a, A> Model<'a, A>
    where A: for<'b> OptimAlgorithm<Model<'b, A>>
{
    pub fn new(layers: &'a [usize]) -> Model<Algorithm> {
        Model {
            layer_sizes: layers,
            alg: Algorithm::default(),
        }
    }
}

impl<'a, A> Optimizable for Model<'a, A>
    where A: for<'b> OptimAlgorithm<Model<'b, A>>
{
    type Data = ();
    type Target = ();
}

pub fn main() {
    let layers = &[1usize,2,3];
    let a = Model::<Algorithm>::new(layers as &[usize]);
}

I think it's a bug. Or at least surprising behaviour. If you take off the where bound on the Model struct (and just leave it on the impl ), your edited code compiles. I'll try to reduce a bit more and file a bug.

pub trait Optimizable {
    type Data;
    type Target;

    // The contract //
}

/// Trait for optimization algorithms.
pub trait OptimAlgorithm<M: Optimizable> {

    // The contract //
}

pub struct Algorithm;

impl Default for Algorithm {
    fn default() -> Algorithm { Algorithm }
}

impl<M: Optimizable> OptimAlgorithm<M> for Algorithm {

}


pub struct Model<'a, A> { // no bounds here
    layer_sizes: &'a [usize],
    alg: A,
}

impl<'a, A> Model<'a, A>
    where A: OptimAlgorithm<Model<'a, A>>
{
    pub fn new(layers: &[usize]) -> Model<Algorithm> {
        Model {
            layer_sizes: layers,
            alg: Algorithm::default(),
        }
    }
}

impl<'a, A> Optimizable for Model<'a, A>
    where A: OptimAlgorithm<Model<'a, A>>
{
    type Data = ();
    type Target = ();
}

pub fn main() {

}

playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM