However, for Copy types like f32 returning a copy makes perfect sense. Would it be possible to add an indexing trait to the language that returns copies?
I think this is sort of blocked on generic associated types, which would allow an Index trait whose Output is parametreizes by a lifetime, so that you can return arbitrary reference or an ownded value
type Output<‘a>;
fun index(&’a self) -> Self::Output<‘a>;
You’d still need some kind of proxy type to implement IndexMut, but at least with GAT it could be something like RefMut<'a, T>. If nothing else, this indicates that such Index and IndexMut traits need to allow distinct Output types.
Wouldn’t the “right” solution be something like IndexMove that goes &move self -> &move Output? Of course, that requires solving outstanding problems with &move…
I mean, yes, lifetime elision adds a lifetime to the signature. I don’t see why you need a GAT for for IndexMove.
Mind, I totally misread the OP, and IndexMove is the Wrong Thing. The thing that worries me about an Index-like trait that spits out copies is that &xs[n] is xs.index(n) right now, and in the situation in which you have e.g. IndexCopy, it is not clear if &xs[n] is a reference into xs or a reference to the immediate xs[n]. In this case, &xs[n] is absurd (since, notionally, it’s a reference into Cell), but it sounds to me like OP doesn’t want users to know about the Cells.
Phrased differently: I don’t think a type should have xs[n] (like Vec<impl Copy>, which simply copies out of the returned pointer) but not have &xs[n] (i.e., a notional pointer into xs which xs[n] can be copied out of).
Well, if we follow precedent, then &xs[n] is a reference to the immediate xs[n]. But as you said this is silly. I also think that adding an IndexMove or IndexCopy for this would be the Wrong Thing. I would use normal functions like index for this.