How do you implement specific types on generic traits in rust?

rust

Solution

The `impl Bar<int> for Foo` and `impl Bar<uint> for Foo` is an error because, at the moment, only one `impl` is allowed per trait, type pair (ignoring parameters on the trait). I went into more detail in this answer, including a work around using a secondary trait that avoids having to make `Foo` generic (which is probably not what you want).

trait BarForFoo {
    fn do_ex(foo: &Foo) -> Self;
}
impl BarForFoo for int {
    fn do_ex(foo: &Foo) -> int {
        foo.y.floor() as int
    }
}    
impl BarForFoo for uint {
    fn do_ex(foo: &Foo) -> uint {
        foo.y.max(0.0).floor() as uint
    }
}

impl<T: BarForFoo> Bar<T> for Foo {
    fn ex(&self) -> T { BarForFoo::do_ex(self) }
}

The second error is because you have two type parameters `T` and `U` "in scope" for the `new` function, but are only specifying one (`U`). The `T` needs to be specified by writing `Foo::<int>::...`, however I don't think this is what you want, instead, you should be using the `T` generic in the `new` function:

impl<T> Foo<T> {
    fn new(value: f64) -> Foo<T> { ... }
}

As background, the compiler needs to know the concrete type of `T` because the implementation of `new` could change:

impl<T> Foo<T> {
  fn new<U>(value:f64) -> Foo<U> {
    Foo { y: value + std::mem::size_of::<T>() as f64 }
  }
}

and then `Foo::<()>::new::<int>(0.0)` would give `y == 0.0`, but `Foo::<u64>::new::<int>(0.0)` would give `y == 8.0`.

Problem

I initially assumed you could do this, because the documentation (http://doc.rust-lang.org/rust.html#implementations) suggests you can: ``` trait Bar<T> { fn ex(&self) -> T; } struct Foo { y:f64 } impl Bar<int> for Foo { fn ex(&self) -> int { return self.y.floor() as int; } } impl Bar<uint> for Foo { fn ex(&self) -> uint { if (self.y < 0.0) { return 0u; } return self.y.floor() as uint; } } ``` ...but that doesn't seem to work. I get errors like: ``` error: multiple applicable methods in scope error: expected Bar<uint>, but found Bar<int> (expected uint but found int) error: expected Bar<int>, but found Bar<uint> (expected int but found uint) ``` So I figured perhaps Foo has to be generic for this to work, so each specific Foo has it's own Bar implementation on it: ``` trait Bar<T> { fn ex(&self) -> T; } struct Foo<T> { y:f64 } impl<T> Foo<T> { fn new<U>(value:f64) -> Foo<U> { return Foo { y: value } as Foo<U>; } } impl Bar<int> for Foo<int> { fn ex(&self) -> int { return self.y.floor() as int; } } impl Bar<uint> for Foo<uint> { fn ex(&self) -> uint { if (self.y < 0.0) { return 0u; } return self.y.floor() as uint; } } fn main() { let z = Foo::new::<int>(100.5); let q = Foo::new::<uint>(101.5); let i:int = z.ex(); let j:uint = q.ex(); } ``` ...but my constructor seems to not work: ``` x.rs:11:12: 11:38 error: non-scalar cast: `Foo<<generic #1>>` as `Foo<U>` x.rs:11 return Foo { y: value } as Foo<U>; ^~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error ``` Edit: I also tried: ``` impl<T> Foo<T> { fn new<U>(value:f64) -> Foo<U> { let rtn:Foo<U> = Foo { y: value }; return rtn; } } ``` Which solve the casting error, but results in: ``` x.rs:32:11: 32:26 error: cannot determine a type for this expression: unconstrained type x.rs:32 let z = Foo::new::<int>(100.5); ^~~~~~~~~~~~~~~ ``` O_o I have no idea what that means. How do you do this?

Original source

Related problems