3
votes

I have a simple linked list type and an implementation of Clone for it:

#[deriving(Show)]
enum List {
    Cons(int, Box<List>),
    Nil,
}

impl Clone for List {
    fn clone(&self) -> List {
        match *self {
            Cons(val, ref rest) => Cons(val, rest.clone()),
            Nil => Nil,
        }
    }
}

It works as expected. But if I make my own MyClone trait with the same signature as that of Clone, I get an error:

trait MyClone {
    fn my_clone(&self) -> Self;
}

impl MyClone for List {
    fn my_clone(&self) -> List {
        match *self {
            Cons(val, ref rest) => Cons(val, rest.my_clone()),
            Nil => Nil,
        }
    }
}

.../src/main.rs:23:46: 23:61 error: mismatched types: expected `Box<List>`, found `List` (expected box, found enum List)
.../src/main.rs:23             Cons(val, ref rest) => Cons(val, rest.my_clone()),

It works fine if I change it to box rest.my_clone(), but I don't understand why. The MyClone and Clone traits are the same, so it seems to me they would accept the same implementation.

(I'm compiling with rustc 0.12.0-nightly (72841b128 2014-09-21 20:00:29 +0000).)

1

1 Answers

5
votes

This is because rust also has an implementation of Clone for Box<T>. If you implement MyClone for it, it will owrk at expected.

#[deriving(Show)]
enum List {
    Cons(int, Box<List>),
    Nil,
}

trait MyClone {
    fn my_clone(&self) -> Self;
}

impl<T: MyClone> MyClone for Box<T> {
    fn my_clone(&self) -> Box<T> {
        self.my_clone()
    }
}

impl MyClone for List {
    fn my_clone(&self) -> List {
        match *self {
            Cons(val, ref rest) => Cons(val, rest.my_clone()),
            Nil => Nil,
        }
    }
}