There's a thread (now closed) about generalizing Index
and IndexMut
to return "view" types that aren't references. There's also a prior RFC which was declined for accidentally proposing a solution that breaks backwards compatibility.
Here, I'd like to discuss a potential non-breaking solution: adding new indexing trait which supersedes the old ones, while providing covering implementations for types that implement the old types. More concretely:
trait CoolIndex<'a, Idx: ?Sized> {
type Output: ?Sized;
fn cool_index(&'a self, index: Idx) -> Self::Output;
}
impl<'a, T> CoolIndex<'a, usize> for TypeWithView<T>
where T: 'a
{
type Output = View<'a, T>;
fn cool_index(&'a self, index: usize) -> View<'a, T> {
magic!()
}
}
This is essentially copied from @CAD97's solution from the RFC, which is similar to @japaric's attempt #3 from 2014. Heres's a playground with a more complete definition plus examples.
For me, I have the following unanswered questions:
-
If we're parametrizing the trait with the lifetime
'a
, are there any issues lettingcool_index
take ownership ofself
and instead implementCoolIndex<'a, _>
for&'a Whatever
?Update: I tried out something like this in the playground. Benefit: the one trait can be implemented for both
&'a T
and&'a mut T
. Problem: we lose syntactic disambiguation via&_[_]
vs&mut _[_]
(and people would probably be surprised if something with&
in the calling syntax could somehow take ownership of the referent). -
Could someone give a more concrete example of how lifetime contravaiance in the returned "view" type causes problems? To me it looks like
CoolIndex
has a straightforward translation toIndex
, which would have the same lifetime issues if any.