Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

split Index into Index, IndexMut and IndexAssign #6515

Closed
thestinger opened this Issue · 21 comments
@thestinger

The current Index isn't great because you have to use &self and return &T or T (via clone) for a map/vector type.

I think it would be best to split it into Index (with &self), IndexMut (with &mut self) and IndexAssign (&mut self, inserting a value).

I'm unsure about the syntax. It would be nice to make it uniform with vector syntax and have &a["foo"] call Index for &T, etc.

@graydon

Relative of #5992 -- dupe?

@thestinger

@graydon: not quite, that's more about adding in-place versions of the binary operators with a mention of index-assign

@chris-morgan

How about foo[bar] += baz? Where will that fit in (with regards to #5992; probably more appropriate there)?

@huonw
Owner

@chris-morgan I imagine that would be handled by IndexMut i.e. "desugared" to something like foo.index_mut(bar).add_assign(&bar).

@bluss
Collaborator

I'll mention the role of RandomAccessIterator (that is an experimental feature yet to find its proper formulation I think); RAI could be unified with the Index traits. However if traits like RandomAccess/RandomAccessMut are fleshed out, we will also see that the vec iterator and vec slice will start to look very similar.. (But, the random access traits are of course there to apply to much more than just vec iterators).

Edit: To give the traits purpose, for RandomAccess, think binary search, for RandomAccessMut, think generic sort.

@nikomatsakis

cc me, I am working on overloading deref and so on, and this is related. I'll put in the specifics of my proposal in a bit.

@brson
Owner

To move vec builders into the library we need overloadable index to be working correctly. Nominating.

@thestinger thestinger referenced this issue
Closed

port from ~[T] to Vec<T> #11875

1 of 3 tasks complete
@pnkfelix
Collaborator

Accepted for 1.0, P-high.

@nikomatsakis

To be concrete, I think it should work like this.

// self[element] -- if used as rvalue, implicitly a deref of the result
trait Index<E,R> {
    fn index<'a>(&'a self, element: &E) -> &'a R;
}

// &mut self[element] -- when used as a mutable lvalue
trait IndexMut<E,R> {
    fn index_mut<'a>(&'a mut self, element: &E) -> &'a mut R;
}

// self[element] = value
trait IndexSet<E,V> {
    fn index_set(&mut self, element: E, value: V);
}

These specifications make one crucial assumption: that the implementer can return a reference to the result. This is suitable for many if not all uses cases, but it disallows e.g. an implementer that was going to synthesize the result.

An alternative is to add a fourth trait, corresponding to self[element] used an rvalue:

// self[element] in an rvalue context
trait IndexGet<E,R> {
    fn index_get(&self, element: &E) -> R;
}

which would be intended for those cases where self[element] is used as an rvalue.

I am more-or-less indifferent as to which of these would be best.

@thestinger

@nikomatsakis: I think it would be fine to reserve the syntax for in-memory data structures able to return a reference. As long as it's possible to implement what slices do today in a user-defined type, I'll be happy!

@wycats
Owner

@nikomatsakis this looks fine as a starting point.

I think I want this as well:

// self[element] = value
trait IndexSetRef<E,V> {
    fn index_set(&mut self, element: &E, value: V);
}

I'm happy to pick up the work for your three traits and see how far I get.

@nikomatsakis

I think it's plausible to have various set traits so long as a type implements at most one (or rather we try them in a specific order, so there's no point in implementing more than one)

@nikomatsakis

I am happy to mentor this bug fyi

@nikomatsakis

With respect to PR #11977, @wycats and I talked privately over IRC some time ago. This current patch doesn't implement the desired semantics. For example, if x implements IndexRef to act like a "vector of T", then x[y] in this patch would have the type &T rather than T (and &x[y] would have type &&T). I'll add a comment shortly detailing what needs to be done (I believe) and in what order.

@nikomatsakis

I've given some more thought to this and I'm not sure that the IndexGet trait that I listed makes sense or is possible. The problem is that, if the type E is POD, you want fn(&self), but the type E is linear, you want fn(self). This seems to be a general difficulty (also with deref traits).

@nikomatsakis

See comments here:

#7141 (comment)

Most of this applies equally to index. The only difference is the IndexSet trait, intended to support hashtables.

@huonw
Owner

With the new Vec type, having this working properly would be really nice (although it is still just sugar).

@sfackler
Collaborator

I'd appreciate the ability to return things by value, personally. It allows for some nice sugar:
https://github.com/sfackler/rust-postgres/blob/537203d3cbd9fe0bf246c65b8d81d7af66568691/src/stmt.rs#L516

@pcwalton
Owner

Nominating for backcompat-lang since this will change the defn. of the Index trait.

@seanmonstar

Does this need a real RFC?

@pcwalton
Owner

This is RFC #111.

@pcwalton pcwalton referenced this issue from a commit in pcwalton/rust
@pcwalton pcwalton librustc (RFC #34): Implement the new `Index` and `IndexMut` traits.
This will break code that used the old `Index` trait. Change this code
to use the new `Index` traits. For reference, here are their signatures:

    pub trait Index<Index,Result> {
        fn index<'a>(&'a self, index: &Index) -> &'a Result;
    }
    pub trait IndexMut<Index,Result> {
        fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
    }

Closes #6515.

[breaking-change]
f02f225
@pcwalton pcwalton referenced this issue from a commit in pcwalton/rust
@pcwalton pcwalton librustc (RFC #34): Implement the new `Index` and `IndexMut` traits.
This will break code that used the old `Index` trait. Change this code
to use the new `Index` traits. For reference, here are their signatures:

    pub trait Index<Index,Result> {
        fn index<'a>(&'a self, index: &Index) -> &'a Result;
    }
    pub trait IndexMut<Index,Result> {
        fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
    }

Closes #6515.

[breaking-change]
7704017
@pcwalton pcwalton referenced this issue from a commit in pcwalton/rust
@pcwalton pcwalton librustc (RFC #34): Implement the new `Index` and `IndexMut` traits.
This will break code that used the old `Index` trait. Change this code
to use the new `Index` traits. For reference, here are their signatures:

    pub trait Index<Index,Result> {
        fn index<'a>(&'a self, index: &Index) -> &'a Result;
    }
    pub trait IndexMut<Index,Result> {
        fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
    }

Closes #6515.

[breaking-change]
f139109
@pcwalton pcwalton referenced this issue from a commit in pcwalton/rust
@pcwalton pcwalton librustc (RFC #34): Implement the new `Index` and `IndexMut` traits.
This will break code that used the old `Index` trait. Change this code
to use the new `Index` traits. For reference, here are their signatures:

    pub trait Index<Index,Result> {
        fn index<'a>(&'a self, index: &Index) -> &'a Result;
    }
    pub trait IndexMut<Index,Result> {
        fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
    }

Closes #6515.

[breaking-change]
ddb0192
@bors bors referenced this issue from a commit
@bors bors auto merge of #15394 : pcwalton/rust/new-index-traits, r=nick29581
This will break code that used the old `Index` trait. Change this code
to use the new `Index` traits. For reference, here are their signatures:

    pub trait Index<Index,Result> {
        fn index<'a>(&'a self, index: &Index) -> &'a Result;
    }
    pub trait IndexMut<Index,Result> {
        fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
    }

Closes #6515.

[breaking-change]

r? @nick29581
00cdd63
@pcwalton pcwalton closed this issue from a commit
@pcwalton pcwalton librustc (RFC #34): Implement the new `Index` and `IndexMut` traits.
This will break code that used the old `Index` trait. Change this code
to use the new `Index` traits. For reference, here are their signatures:

    pub trait Index<Index,Result> {
        fn index<'a>(&'a self, index: &Index) -> &'a Result;
    }
    pub trait IndexMut<Index,Result> {
        fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
    }

Closes #6515.

[breaking-change]
7e4e991
@pcwalton pcwalton closed this in 7e4e991
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.