I am new to Rust and working through the Rust Exercism track. While working on the Simple Linked List project, I ran into a problem I would like to understand.
All tests for my solution passed, but Clippy warned that I should implement the From trait since it includes Into. A twofer ... I couldn't resist. I implemented From and commented out the existing Into. The compilation failed on the test test_into_vector
The error was:
124 | let s_as_vec: Vec = s.into();
| ^^^^ the trait std::convert::From<simple_linked_list::SimpleLinkedList<{integer}>> is not implemented for std::vec::Vec<i32>
The test code is:
#[test]
#[ignore]
fn test_into_vector() {
let mut v = Vec::new();
let mut s = SimpleLinkedList::new();
for i in 1..4 {
v.push(i);
s.push(i);
}
let s_as_vec: Vec<i32> = s.into();
assert_eq!(v, s_as_vec);
}
I tested my From implementation with a new test and the new test is successful. The code for the test is
#[test]
#[ignore]
fn test_from_vector() {
let mut v :Vec<i32> = Vec::new();
let mut s: SimpleLinkedList<i32> = SimpleLinkedList::new();
for i in 1..4 {
v.push(i);
s.push(i);
}
let s_from_vec = SimpleLinkedList::<i32>::from(v);
assert_eq!(s, s_from_vec);
}
The code for the From implementation looks like
impl<T: Debug>From<Vec<T>> for SimpleLinkedList<T> {
fn from(items: Vec<T>) -> Self {
let mut list: SimpleLinkedList<T> = SimpleLinkedList::new();
for item in items {
list.push(item)
}
println!("{:?}", list);
list
}
}
Why does test_into_vector fail if I only have the From as shown above? Please help me understand what at the moment is misunderstood.
Because you've not defined the SimpleLinkedList<T> -> Vec<T> conversion. impl From<Vec<T>> for SimpleLinkedList<T> defines Vec<T> -> SimpleLinkedList<T> conversion.
I don't understand; I am still missing something. Isn't the SimpleLinkedList -> Vec conversion the implementation of Into? If I have implemented From should I need to implement Into? Both Clippy and the documentation appear to indicate that I should not need to implement Into.
When you implemented From<SimpleLinkedList<T>> for Vec<T>, you got implementation for Into<Vec<T>> for SimpleLinkedList<T>, not the other way round. And logically, how could the compiler deduce the way to convert vector into linked list, if you only described the method to do the opposite?
That is exactly what I wanted. I originally implemented Into as follows:
#[allow(clippy::from_over_into)]
impl<T: Debug> Into<Vec<T>> for SimpleLinkedList<T> {
fn into(self) -> Vec<T> {
let mut vec_list: Vec<T> = Vec::new();
for item in self {
vec_list.push(item)
}
//The following line works as well.
//let vec_list: Vec<_> = self.into_iter().collect();
vec_list.reverse();
vec_list
}
}
Clippy complained, so I implemented From, commented out Into and ended with a compilation error on the test test_into_vector.
Ah, sorry, looks like I myself messed up You have implemented From<Vec<T>> for SimpleLinkedList<T>, so you get for free Into<SimpleLinkedList<T>> for Vec<T>.
I get the compilation error on the test_into_vector test though. Is it a fault in my implementation of From? Is it a limitation in the generation of the "free" Into? Is it just some silly mistake on my part that escapes me?
I think you misread what clippy was saying. Clippy has a lint saying that Into<U> for T should be replaced by From<T> for U, because implementing From<T> for U automatically provides Into<U> for T.
However, it looks like you have replaced Into<T> for U with From<T> for U.
In other words Into<Vec<T>> for SimpleLinkedList<T> with From<Vec<T>> for SimpleLinkedList<T>, which provides Into<SimpleLinkedList<T>> for Vec<T>, which is different from what you started out with.