0

(Rust noob here) I would like to create a singly linked list in Rust, by holding a reference to the tail and writing into it. Here is the algorithm in C++:

#include <memory>
#include <string>

struct CharList {
    char c;
    std::unique_ptr<CharList> next;
    explicit CharList(char c) : c(c) {}
};

CharList make_list(const std::string &s) {
    CharList res{'a'};
    auto *tail = &res.next;
    for (char c : s) {
        *tail = std::make_unique<CharList>(c);
        tail = &(*tail)->next;
    }
    return res;
}

This is my attempt in Rust (Rust playground link)

struct CharList {
    c: char,
    next: Option<Box<CharList>>,
}

fn make(s:&str) -> CharList {
    let mut result = CharList{
        c: 'a',
        next: None
    };
    {
        let mut tail = &mut result.next;
        for c in s.chars() {
            let cl = CharList {
                c: c,
                next: None
            };
            mem::replace(tail, Some(Box::new(cl)))
            let mut next = &mut tail.as_mut().unwrap().next;
            tail = next
        }
    }
    result
}

The resulting error is:

error[E0499]: cannot borrow `*tail` as mutable more than once at a time
  --> src/main.rs:21:26
   |
21 |             mem::replace(tail, Some(Box::new(cl)));
   |                          ^^^^ second mutable borrow occurs here
22 |             let next = &mut tail.as_mut().unwrap().next;
   |                             ---- first mutable borrow occurs here
...
25 |     }
   |     - first borrow ends here

I find it confusing that the first borrow is reported to occur after the second borrow, but I suppose that is because they occur in different iterations of the loop.

What is the right way to implement this algorithm in Rust?

ridiculous_fish
  • 17,273
  • 1
  • 54
  • 61
  • 4
    Due to borrowing rules, linked lists are actually surprisingly hard to do in rust. In fact, there is a rather comprehensive [introduction to rust](https://cglab.ca/~abeinges/blah/too-many-lists/book/) built solely on them. You might find it interesting. – Michail Nov 18 '18 at 08:54
  • TL;DR the duplicate: `let next = &mut {tail}.as_mut().unwrap().next;` – Shepmaster Nov 18 '18 at 13:30
  • 1
    How [I'd write the entire function](https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=aeae36d2af68b325454e368a358a3c53) – Shepmaster Nov 18 '18 at 14:50

0 Answers0