Skip to content

Scratchpad on PropertyMaps

Lukas Kalbertodt edited this page May 24, 2018 · 5 revisions

Ways to access elements

Access is in the form fn get($self, handle: Handle) -> $ret where $self is one of self, &self and &mut self and $ret one of P, &P and &mut P (where the references have the same lifetime as $self references!). This leaves us with 9 possibilities in theory:

Impossible

  • self -> &P
    • Not possible: since self then lives in the stack of the function, we cannot return references to self.
  • self -> &mut P
    • Not possible: see above.
  • &self -> &mut P
    • This is interior mutability. It's usually not implementable like this (because then the caller could make the mut ref live forever without the collection knowing about it). The only way I can imagine implementing this is by allowing only a "one-shot borrow". Where the first call succeeds and all of the following panic. Not very useful.

Not useful

  • self -> P
    • As we are talking about collections, consuming self doesn't really make a whole lot of sense. It's like Vec<T> -> T... useful in only a few rare situations.
  • &mut self -> &P
    • If &mut self is required to create a &P, this means that there is some non-semantic mutability at play. Like ... caching or something. In those cases, usually interior mutability should be used. So we can ignore this (as do many of the std traits, like Index).

Useful

  • &self -> P
    • Useful e.g. for mappings where from one value a new one is created. This new one doesn't live anywhere in the collection.
  • &self -> &P
    • Very useful, like Index
  • &mut self -> &mut P
    • Very useful, like IndexMut

Questionable

  • &mut self -> P

The Plan

Without GATs, it's not very useful to have a &self -> P trait, because such a trait would be unrelated to a &self -> &P trait. With GATs we would like to have something like this:

trait PropMap<H: Handle> {
    type Property<'a>;
    fn get(&self) -> Self::Property;
}

trait PropIndex<H: Handle>
    : Index<H> + for<'a> PropMap<H, Property = &'a <Self as Index<H>>::Output> 
{}

Meaning: PropMap is a super trait of PropIndex. This in turn means that many functions can bound their maps with PropMap (because they don't care if they get a reference or an owned value).

But again, without GATs, it's not really nice to implement this. It can be done something like this, but this spills lifetimes everywhere.

So for now, we will only use the two trait analogous to ops::Index and ops::IndexMut. This makes a few pattern impossible (like a nice Mapping which doesn't just use subreferences), but it's a sensible start for now and works for most cases.

Clone this wiki locally