yggie
yggie

Reputation: 317

Traits with associated type in templates

I have been having problems compiling my Rust code, I managed to boil down the issue to this snippet:

use std::slice::Iter;

pub trait Foo<'a> {
    type Bar: Iterator<Item=&'a usize>;

    fn make(&self) -> usize;
}

pub struct Juice;

impl <'a> Foo<'a> for Juice {
    type Bar = Iter<'a, usize>;

    fn make(&self) -> usize { 0us }
}


// Uncomment this line to break things
// fn get_int<'a, T: Foo<'a>>(t: T) -> usize {
//   t.make()
// }


fn main() {
    println!("Hello, {:?} world!" , Juice.make());
}

I am pretty sure I am just missing something, is there anything I need to do to make this trait work? I am using the latest nightly alpha build (at the time of writing):

rustc 1.0.0-nightly (458a6a2f6 2015-01-25 21:20:37 +0000)

Upvotes: 5

Views: 1850

Answers (1)

Vladimir Matveev
Vladimir Matveev

Reputation: 128051

Unfortunately, you need to write this:

fn get_int<'a, T: Foo<'a, Bar=I>, I: Iterator<Item=&'a usize>>(t: T) -> usize {
  t.make()
}

That is, you have to specify explicitly that the type of Bar is an iterator of the corresponding type. The trait bound inside the trait definition alone is insufficient.

This is very much like regular type parameters work. Even if you write something like

trait Parameterized<T: Clone> { ... }

You still need to write

fn do_something<P: Parameterized<T>, T: Clone>() { ... }

Or with structs:

struct S<T: Iterator<i32>> { ... }

impl<T: Iterator<i32>> for S<T> { ... }

This does look counterintuitive (and I've stumbled upon this several times as well) and probably deserves an issue in RFC repo.

Upvotes: 7

Related Questions