# Accepting nested method calls with an \`&mut self\` receiver

**URL:** <https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588>\
**Category:** language design\
**Created:** [January 10, 2017, 5:39pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588 "2017-01-10T17:39:07Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![sanxiyn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/sanxiyn/32/8824_2.png) [@sanxiyn](https://internals.rust-lang.org/u/sanxiyn)\
**Post date:** [January 11, 2017, 3:15am UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/21 "2017-01-11T03:15:52Z")

</div>

I think “pure deref” case is important: in particular because of interactions with borrowck it is impossible to do “perfect forwarding” in Rust now.

On the other hand, “pure deref” does seem orthogonal to “upgradeable borrow”. I support solving “upgradeable borrow” first. One step at a time.

Among concrete proposals, I like proposal 2 better. Even if I didn’t, as I understand proposal 2 is the more conservative one?

As for implementation, I support desugaring and hacking this into current borrowck instead of waiting on MIR borrowck, but then it is unlikely I will get to implement this, so there is not much reason you should listen to me here.

---

<div class="post-metadata">

**Author:** ![comex](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/comex/32/2587_2.png) [@comex](https://internals.rust-lang.org/u/comex)\
**Post date:** [January 11, 2017, 5:46am UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/22 "2017-01-11T05:46:17Z")

</div>

My strong personal impression is that Rust has so many “I have to refactor this perfectly good code because the borrow checker is too dumb to realize it’s safe” moments, it leaves a bad taste to add “I have to refactor this because the borrow checker is opinionated about the design”, if at all avoidable. So I prefer option 1.

Besides, I think something like ‘borrowing for later’ is definitely the future, and I don’t think the no-mutation rule generalizes well to that. The rule would have to be that you can access a variable between when you take a mutable reference to it and when you use the reference, but only immutably; and that would block a lot of code that isn’t nearly as crazy as in the present case. (Consider the case where the reference is stored in some other structure.)

---

<div class="post-metadata">

**Author:** ![arielb1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arielb1/32/3044_2.png) [@arielb1](https://internals.rust-lang.org/u/arielb1)\
**Post date:** [January 11, 2017, 12:16pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/23 "2017-01-11T12:16:02Z")

</div>

> [@comex](#):
>
> Besides, I think something like 'borrowing for later' is definitely the future, and I don't think the no-mutation rule generalizes well to that. The rule would have to be that you can access a variable between when you take a mutable reference to it and when you use the reference, but only immutably; and that would block a lot of code that isn't nearly as crazy as in the present case. (Consider the case where the reference is stored in some other structure.)

Of course. Tracking when you mutate through that reference becomes the hard part.

---

<div class="post-metadata">

**Author:** ![arielb1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arielb1/32/3044_2.png) [@arielb1](https://internals.rust-lang.org/u/arielb1)\
**Post date:** [January 11, 2017, 12:39pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/24 "2017-01-11T12:39:19Z")

</div>

> [@nikomatsakis](#):
>
> To be more explicit, you mean that upgradable borrows (or "borrowing for the future", as I was calling it, though it occurs to me that "reservations" might be a clearer term) will still report an error for `vec[vec.len() - 1]`? I agree, that seems true. (And, more generally, will be true for any deref/index impl.)

Sure enough.

And as we're talking about 2-phase lifetimes, let me propose something that should "fix" this (with a change to `Index`):

1. Add the possibility of "not-yet-active" lifetimes (ATM every lifetime has been active at some point). Find some hopefully-unhacky way of integrating this with lifetime inference.
2. Add a `Ref2Φ<'immut, 'mutbl, T> where T: 'immut, 'immut: 'mutbl` reference type. Note that

```rust
&'a T ~ Ref2Φ<'a, 'empty, T>
&'a mut T ~ Ref2Φ<'a, 'a, T>

```

Where the equivalence/coercion/whatever can't be made to an eqty because you can't dispatch on lifetimes, but they should be at least coercions. 3) Make all borrows biphase. A borrowck conflict happens when the immutable segment of one Ref2Φ conflicts with the mutable segment of another. Reborrowing works like usual. 4) PROFIT:

```rust
Vec::push(&mut v, Vec::len(&v)) // this works regardless of the desugaring
Vec::deref_mut(&mut v)[0] = Vec::len(&v); // still does not work

```

1. BONUS: make `Ref2Φ` and NYA lifetimes user-accessible (bikeshed about the syntax until you get tired), and define:

```rust
trait Deref2Φ : Deref {
    fn deref2Φ<'immut, #[may_dangle] 'mutbl>(self: Ref2Φ<'immut, 'mutbl, Self>)
        -> Ref2Φ<'immut, 'mutbl, Self::Target>;
}

trait Index2Φ<Idx: ?Sized> : Index<Idx> {
    fn index2Φ<'immut, #[may_dangle] 'mutbl>(self: Ref2Φ<'immut, 'mutbl, Self>,
                                             index: Idx)
        -> Ref2Φ<'immut, 'mutbl, Self::Output>;
}

```

1. BONUS: profit even more, because now you can have a single unified `Index`/`IndexMut` implementation (for backwards compat, forward both to `Index2Φ`) and "everything" works.

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [January 11, 2017, 6:10pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/25 "2017-01-11T18:10:24Z")

</div>

> [@arielb1](#):
>
> 1. Add the possibility of "not-yet-active" lifetimes (ATM every lifetime has been active at some point). Find some hopefully-unhacky way of integrating this with lifetime inference.

Interesting. This seems like an extension on 'borrowing for the future' to me, one which exposes the two (overlapping) lifetimes in the type (`Ref2`, as you called it) and thus allows us to build abstractions that mirror those lifetimes further up.

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [January 11, 2017, 6:13pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/26 "2017-01-11T18:13:53Z")

</div>

> [@comex](#):
>
> Besides, I think something like 'borrowing for later' is definitely the future, and I don't think the no-mutation rule generalizes well to that.

Actually, I think it's _more_ friendly for that, as I mentioned in the text. In particular, since it uses an already existing set of restrictions (sharing), it lets you think of "borrowing for the future" as starting out with a shared borrow and "upgrading" it to a mutable borrow when you first use it (or, alternatively, as having two overlapping lifetimes, one that starts later, which is how @arielb1 described it below (or, alternatively, having a notion of a "reservation" -- that is, when you do an `&mut foo` in lifetime `'x`, you register that `foo` is borrowed during `'x` -- if `'x` hasn't started yet, it is "reserved" which means we treat it like a shared borrow)). Anyway TL;DR having fewer sets of rules seems easier.

---

<div class="post-metadata">

**Author:** ![arielb1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arielb1/32/3044_2.png) [@arielb1](https://internals.rust-lang.org/u/arielb1)\
**Post date:** [January 11, 2017, 8:55pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/27 "2017-01-11T20:55:09Z")

</div>

> [@nikomatsakis](#):
>
> Interesting. This seems like an extension on 'borrowing for the future' to me, one which exposes the two (overlapping) lifetimes in the type (Ref2, as you called it) and thus allows us to build abstractions that mirror those lifetimes further up.

First, that's Ref2Φ with a Φ - that makes it bad syntax :-).

Second, my first intent was to formalize the thing _within_ the borrow checker first, and only expose it to the user afterwards.

---

<div class="post-metadata">

**Author:** ![gereeter](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gereeter/32/3175_2.png) [@gereeter](https://internals.rust-lang.org/u/gereeter)\
**Post date:** [January 24, 2017, 5:05pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/28 "2017-01-24T17:05:47Z")

</div>

I really like the `Ref2Φ` idea. It preserves the property that once borrowed, an object cannot be mutated, which I like. Moreover, it seems to capture exactly the sort of borrowing behavior I wanted from streaming iterators:

```rust
trait StreamingIterator {
    type Item<'a>;

    fn next<'immut, /* N.B.: no #[may_dangle] */ 'mubl>(
        self: Ref2Φ<'immut, 'mutbl, Self>
    ) -> Item<'immut>;
}

```

This would allow, e.g., doing a nice iteration through a file while still being able to access the file properties (path, size, etc.) in the middle of iteration.

However, instead of using “not-yet-active” lifetimes, it might be cleaner to just use arbitrary sets of program points (not necessarily contiguous) for the mutable section. With a lifetime, a reference would be able to be changed from immutable to mutable to immutable, but not anything more complex than that. This seems like an odd choice, and it lacks symmetry - labeling the immutable part of the borrow would allow a completely different set of patterns.

Essentially, your initial `Ref2Φ` proposal allows

```rust
let v_ref = &mut v;
Vec::push(v_ref, Vec::len(&v));

```

and

```rust
let v_ref = &mut v;
Vec::push(v_ref, 3);
Vec::push(v_ref, 5);

```

but disallows

```rust
let v_ref = &mut v;
Vec::push(v_ref, Vec::len(&v));
Vec::push(v_ref, 5);

```

which seems strange to me.

Another way to look at this is as a generalized notion of the mutability part of a reference. A reference currently has three parts - a lifetime, a mutability (`mut` vs. not), and a type. This would just change the mutability part from a binary choice to a binary choice at every program point. Therefore, a change like this could be initially exposed to the user by just being generic over mutability (which has already been RFCed).

---

<div class="post-metadata">

**Author:** ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)\
**Post date:** [January 25, 2017, 11:49pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/29 "2017-01-25T23:49:43Z")

</div>

These notions of “stable lvalues” and “borrowing for the future” seem very relevant to the recent coroutine proposals, since a coroutine’s state has to be borrowed on suspension until it gets resumed, and due to potential implicit self-borrowing that state has to be unmoveable until the coroutine finally returns.

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [March 1, 2017, 2:51pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/30 "2017-03-01T14:51:19Z")

</div>

Spin-off thread: [[blog post] Nested method calls via two-phase borrowing](https://internals.rust-lang.org/t/blog-post-nested-method-calls-via-two-phase-borrowing/4886)

---

<div class="post-metadata">

**Author:** ![logannc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/logannc/32/693_2.png) [@logannc](https://internals.rust-lang.org/u/logannc)\
**Post date:** [March 2, 2017, 10:22pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/31 "2017-03-02T22:22:57Z")

</div>

What are the problems with first desurgaring everything to UFCS, then at each level evaluating in an order: borrow then mutable borrow/move?

`vec.push(vec.len())` desugars to `Vec::push(&mut vec, vec.len())`. `vec.len()` is a borrow so it is evaluated first (read: desugared like proposal 1), then it continues.

Optionally, you can make it depth-first with respect to nested calls which accomplishes the same thing by having the desugared `Vec::len(vec)` evaluated first.

Note: I am being imprecise because I’m on my phone. A literal desurgaring into UFCS first would make the semantics for things like `x.mut_something().bar(y.only_borrow())` awkward since `bar(foo(&mut x), baz(&y))` would force evaluation of baz first, which is not what we want. I think, if my understanding of stable lvalues was correct, we only would any of these rules when there is a stable lvalue on the left? EDIT: the perils of writing on your phone. Stable path, not stable lvalue. But basically we only want to initiate these desurgaring when the left hand side is a variable? I don’t have time to come up with a good definition right this second.

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [March 3, 2017, 1:22pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/32 "2017-03-03T13:22:59Z")

</div>

> [@logannc](#):
>
> What are the problems with first desurgaring everything to UFCS, then at each level evaluating in an order: borrow then mutable borrow/move?

This sounds sort-of similar to the evaluation order that @arielb1 proposed. I left some [thoughts on their proposal here](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/14).

---

<div class="post-metadata">

**Author:** ![logannc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/logannc/32/693_2.png) [@logannc](https://internals.rust-lang.org/u/logannc)\
**Post date:** [March 3, 2017, 2:18pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/33 "2017-03-03T14:18:30Z")

</div>

I did draw inspiration from that, but mine has different drawbacks. Mine supports UFCS and I propose that it would not come into play for indices, etc. The exact mechanism by which we avoid initiating my rules are as of yet unspecified until it is determined the rest of the idea isnt horribly flawed.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [March 7, 2017, 7:09pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/34 "2017-03-07T19:09:28Z")

</div>

I don’t understand the desire to prevent receiver from being modified by the arguments.

To me it’s normal than arguments are evaluated before the function call, and so it’s normal that arguments are evaluated before a method call too.

For me `x.add(x.increment(1))` seems entirely reasonable, and I’d expect it to always be identical to

```rust
let tmp = x.increment(1); 
x.add(tmp);

```

---

<div class="post-metadata">

**Author:** ![zackw](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zackw/32/2071_2.png) [@zackw](https://internals.rust-lang.org/u/zackw)\
**Post date:** [March 8, 2017, 9:03pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/35 "2017-03-08T21:03:42Z")

</div>

I keep thinking ‘nested method calls with an `&mut self` receiver’ means something completely different:

```
trait Foo {
    fn foo(&mut self);
    fn bar(&mut self);
}
impl Foo for () {
    fn foo(&mut self) { println!("()::foo"); }
    fn bar(&mut self) { println!("()::bar"); self.foo(); }
    // ^^^^^^^^^^ this here 
}

```

Since (I’m pretty sure) the above is already OK, can anyone think of a more descriptive term for the feature actually under discussion?

---

<div class="post-metadata">

**Author:** ![Xaeroxe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/xaeroxe/32/2209_2.png) [@Xaeroxe](https://internals.rust-lang.org/u/Xaeroxe)\
**Post date:** [June 9, 2017, 12:48pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/36 "2017-06-09T12:48:18Z")

</div>

Edit: I’m coming to the realization this was proposal 1. So I’ll just say I’m in support of proposal 1.

Perhaps I’m misunderstanding here, but it seems to me the easiest way to fix this would be to modify the desugaring so that the end result looks like what we’re currently using as a workaround today.

All arguments need to be evaluated before the inner function call can begin, so why not always translate

vec.push(vec.len());

to

let a = vec.len() vec.push(a);

That’s more or less what the resulting assembly code would look like is it not? Why do we need to introduce new language features to accomplish this? We can keep our existing left to right evaluation. This would also work for more complicated setups too, such as

let a = vec.len() let b = vec.len() \* 2; vec.push((a, b));

---

<div class="post-metadata">

**Author:** ![zackw](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zackw/32/2071_2.png) [@zackw](https://internals.rust-lang.org/u/zackw)\
**Post date:** [June 9, 2017, 1:07pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/37 "2017-06-09T13:07:38Z")

</div>

Unfortunately, your proposal _does_ break the existing left to right evaluation, because that includes the implicit “receiver” argument.

```
vec.push(vec.len());

```

evaluated strictly left to right, really desugars to something like

```
{
    let mut v1 = &vec;
    let a = {
        let v2 = &vec;
        Vec::len(v2)
    };
    Vec::push(v1, a);
}

```

Your change would move the `let mut v1 = &vec` below the `let a = { ... }`, _and that’s the problem_. As I understand it, there is quite a bit of existing code that depends on the receiver expression being evaluated before any of the arguments.

---

<div class="post-metadata">

**Author:** ![Xaeroxe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/xaeroxe/32/2209_2.png) [@Xaeroxe](https://internals.rust-lang.org/u/Xaeroxe)\
**Post date:** [June 9, 2017, 1:51pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/38 "2017-06-09T13:51:16Z")

</div>

I see. Could you give me a code example where the borrow was required to be taken prior to the arguments being evaluated? I don’t quite see how this could impact end behavior, as taking a borrow isn’t a mutating operation.

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [June 9, 2017, 4:50pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/39 "2017-06-09T16:50:37Z")

</div>

There’s one in the very first post in this thread. 🙂Here it is:

```rust
let mut v: Vec<String> = vec![format!("Hello, ")];
v[0].push_str({ v.push(format!("foo")); "World!" });
// ^^^^^^^^^^^^^^^^^^^^^^ sneaky attempt to mutate `v`

```

The point is that the receiver (the `self` argument) can be any expression, so it _can_ be a mutating operation. Notice that the index access `[0]` is calling `Index::index`, which can run arbitrary code. It could have side-effects on global variables or do I/O or whatever. We can’t just re-order it to run _after_ the arguments have been evaluated, that would change the behavior.

---

<div class="post-metadata">

**Author:** ![toc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/toc/32/6692_2.png) [@toc](https://internals.rust-lang.org/u/toc)\
**Post date:** [June 10, 2017, 10:08pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/40 "2017-06-10T22:08:51Z")

</div>

It seems like it would enable enough of the ergonomic improvement to desugar into something like:

```rust
let arg0 = &mut vec;
let arg1 = arg0.len();
Vec::push(arg0, arg1);

```

That is, keeping track of “simple” variable usage and allowing use of an alias in that case. I’d be fine if some of these more complicated examples continued to not compile.

[Previous page](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588.md?page=1)

[Next page](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588.md?page=3)
