2
votes

I'm playing with some Rust Traits and Generics to get familiar with the language.

fn main() {
    println(test(6f).to_str());
}

enum Result<TS,TE>{
    Success(TS),
    Error(TE)
}

impl<TS: ToStr, TE: ToStr> ToStr for Result<TS,TE> {
    fn to_str(&self) -> ~str {
        match *self {
            Success(s) => s.to_str(),
            Error(e)   => e.to_str()
        }
    }
}    

fn test(x:float) -> Result<float,int> {
    match x {
        0f..5f => Success(x/5f),
        _      => Error(1i)
    }
}

I get the folloing errow with the code above.

C:\Users\mflamer\Dropbox\Rust Projects\Tests\rust.rs:27:8: 27:13 error: moving out of dereference of immutable & pointer C:\Users\mflamer\Dropbox\Rust Projects\Tests\rust.rs:27 match *self

                                                                    ^~~~~

It builds fine without the generics on the trait. Whats going on here?

Edit: If I change the code to this it works. Not sure why.

enum Result<TS,TE>{
    Success{ value:TS },
    Error{ error:TE }
}

impl<TS: ToStr, TE: ToStr> ToStr for Result<TS,TE> {
    fn to_str(&self) -> ~str {
        match *self {
            Success{ value: value } => value.to_str(),
            Error{ error: error }   => error.to_str()
        }
    }
}

fn test(x:float) -> Result<float,int> {
    match x {
        0f..5f => Success{ value: x/5f },
        _      => Error{ error: 1i }
    }
}
1
That last one could be a bug, where the compiler is letting a match occur that is actually illegal. - huon
Hm, ok, the last one gives the same error as the first for me, so it's possibly something that was fixed recently. - huon

1 Answers

4
votes

The problem is how the match and generic interacts. The following code works:

impl<TS: ToStr, TE: ToStr> ToStr for Result<TS,TE> {
    fn to_str(&self) -> ~str {
        match *self {
            Success(ref s) => s.to_str(),
            Error(ref e)   => e.to_str()
        }
    }
}

(The only differences is the refs.)

This means that s and e are pointers to the internals of self, that is, they have type &TS and &TE rather than TS and TE.

The reason why not having ref worked without generics is int and float are implicitly copiable, so s and e were just copied out of self, whereas with arbitrary generics, Rust can't do the copy automatically.