How to get many references to one object, using SlotMap?

enum List<'a> {
    Cons(isize, &'a List<'a>),
    Nil,
}

fn main() {
    use List::*;
    use slotmap::SlotMap;
    let mut table = SlotMap::new();
    let nil = table.insert(Nil);
    table.insert(Cons(1, table[nil]));
}

SlotMap<K: Key, V>‘s insert is

pub fn insert(&mut self, value: V) -> K

and its impl<K: Key, V> Index<K> is

fn index(&self, key: K) -> &V

So surely since I insert List into table, table[key] should return &List right?

Why am I getting this error:

error[E0308]: mismatched types
  --> src/main.rs:11:26
   |
11 |     table.insert(Cons(1, table[nil]));
   |                  ----    ^^^^^^^^^^
   |                  |       |
   |                  |       expected `&List<'_>`, found enum `List`
   |                  |       help: consider borrowing here: `&table[nil]`
   |                  arguments to this enum variant are incorrect
   |

How should I actually be using SlotMap to get many (immutable) references to SlotMap-owned objects?

>Solution :

Yes, index() returns a &V, but the operator [] works such that a[b] is equivalent to *a.index(b).

Which is handy, because when you write for example an array:

let mut a = [1,2,3];
a[0] = 0;

you don’t want to write *a[0] = 0;! And consider arrays of arrays… *(*m[0])[1] = 0;, that wouldn’t be pretty.

So if you want the reference to the value just reborrow (that is what the compiler suggests):

table.insert(Cons(1, &table[nil]));

Or alternatively call index manually:

table.insert(Cons(1, table.index(nil)));

But that begs the question, if you are adding all your lists and partial lists to the slotmap, why not:

enum List {
    Cons(isize, Key),
    Nil,
}

And get rid of lifetime issues forever?

Leave a Reply