1

In trying to recall what I learnt last night from the third chapter of Rust By Example I've created an enum linked-list type this way:

#[derive(Debug)]
enum List {
    Nil,
    Cons(i32, Box<List>),
}

I've attempted attaching a tail() method to this type as follows:

impl List {
    // unrelated code not shown
    
    fn tail(&self) -> Self {
        match *self {
            Self::Cons(_, ref tail) => tail,
            nil => nil,
        }
    }
}

But I get the following compiler error:

error[E0308]: mismatched types
  --> .\ee-enum-recall-linked-lists.rs:32:40
   |
30 |     fn tail(&self) -> Self {
   |                       ---- expected `List` because of return type
31 |         match *self {
32 |             Self::Cons(_, ref tail) => tail,
   |                                        ^^^^ expected enum `List`, found `&Box<List>`
   |
   = note:   expected enum `List`
           found reference `&Box<List>`

Which is baffling, because some other code I'd written in this same style to attach a length() method worked, and made me believe that the variable tail there is actually of type List.

impl List {
    // unrelated code not shown

    fn length(&self) -> i32 {
        match *self {
            Self::Cons(_, ref tail) =>  1 + tail.length(),
            _ => 0,
        }
    }
}

So, I'm wondering:

  • What is the type of the value held by the variable tail there, really?
  • Why does tail.length() work if tail isn't a List?
  • How do I match down to the list contained in tail?
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
mfonism
  • 535
  • 6
  • 15
  • 1
    What is your intent with `List::tail`? It takes a reference, but returns a value. How do you intend to get this _owned_ value: steal from a non-mutable reference? Make a clone? – Matthieu M. May 19 '21 at 16:18
  • At this point of my Rust journey I'm working by constructing and deconstructing knowledge based on what I see my code do. @MatthieuM.'s comment has helped me dig deeper and realise that my former intuition for what `ref` is doing in that pattern matching was wrong -- and I've promptly updated my knowledge. I have working code now. – mfonism May 19 '21 at 19:21
  • 1
    I am glad for you! If you have quick questions, you may find it easier to jump in the Rust chatroom: https://chat.stackoverflow.com/rooms/62927/rust. There's all the usual suspects of the [tag:rust] tag, and the format is more "discussion" than formal question/answer, so it's a bit easier to get clarifications :) – Matthieu M. May 20 '21 at 08:16

0 Answers0