Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

split Index into Index, IndexMut and IndexAssign #6515

Closed
thestinger opened this issue May 15, 2013 · 21 comments
Closed

split Index into Index, IndexMut and IndexAssign #6515

thestinger opened this issue May 15, 2013 · 21 comments
Labels
E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.
Milestone

Comments

@thestinger
Copy link
Contributor

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
Copy link
Contributor

graydon commented May 23, 2013

Relative of #5992 -- dupe?

@thestinger
Copy link
Contributor Author

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

@chris-morgan
Copy link
Member

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

@huonw
Copy link
Member

huonw commented Sep 27, 2013

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

@bluss
Copy link
Member

bluss commented Sep 28, 2013

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
Copy link
Contributor

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
Copy link
Contributor

brson commented Jan 24, 2014

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

@pnkfelix
Copy link
Member

Accepted for 1.0, P-high.

@nikomatsakis
Copy link
Contributor

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
Copy link
Contributor Author

@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
Copy link
Contributor

wycats commented Jan 30, 2014

@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
Copy link
Contributor

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
Copy link
Contributor

I am happy to mentor this bug fyi

@nikomatsakis
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

See comments here:

#7141 (comment)

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

@huonw
Copy link
Member

huonw commented Mar 15, 2014

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

@sfackler
Copy link
Member

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
Copy link
Contributor

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

@seanmonstar
Copy link
Contributor

Does this need a real RFC?

@pcwalton
Copy link
Contributor

pcwalton commented Jun 9, 2014

This is RFC #111.

bors added a commit that referenced this issue Jul 7, 2014
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
flip1995 pushed a commit to flip1995/rust that referenced this issue Jan 4, 2021
[beta] Backport of rust-lang#6375 - field_reassign_with_default fix

With the pinned nightly we can test backports to our beta branch now 🎉

cc rust-lang#6515

changelog: beta 1.50: Backport of private fields fix in [`field_reassign_with_default`] lints
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.
Projects
None yet
Development

Successfully merging a pull request may close this issue.