# 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:** 4\
**Page:** 3

<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:** [June 12, 2017, 9:17pm UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/41 "2017-06-12T21:17:54Z")

</div>

Note that there is a pending RFC on this topic:

[https://github.com/rust-lang/rfcs/pull/2025](https://github.com/rust-lang/rfcs/pull/2025)

---

<div class="post-metadata">

**Author:** ![briansmith](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/briansmith/32/1306_2.png) [@briansmith](https://internals.rust-lang.org/u/briansmith)\
**Post date:** [June 15, 2017, 8:47am UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/42 "2017-06-15T08:47:42Z")

</div>

> [@zackw](#):
>
> ```rust
> vec.push(vec.len());
> 
> ```
> 
> evaluated strictly left to right, really desugars to something like
> 
> ```rust
> {
> let mut v1 = &vec;
> let a = {
> let v2 = &vec;
> Vec::len(v2)
> };
> Vec::push(v1, a);
> }
> 
> ```

I don't think that is the most reasonable desugaring, though it appears to be what the Rust compiler is currently doing. I think this is what should be done:

```rust
{
    // evaluate outer vec.
    let a = {
        // evaluate inner vec.
        let v_ref = &vec;
        Vec::len(v_ref)
    };
    let v_mut_ref = &mut vec;
    Vec::push(v_mut_ref, a);
}

```

In particular, even the though compiler needs to evaluate the leftmost `vec` first, it doesn't need to _borrow_ it at that time; it only needs to borrow it mutably just before `Vec::push()` is called.

Consider this:

```rust
fn len_mut<T>(vec: &mut Vec<T>) -> usize {
    vec.len()
}

```

That shows that we can create a non-mut reference even though a mut reference to the object exists.

Now consider this:

```rust
fn len_then_push(vec: &mut Vec<usize>) {
    let len = vec.len();
    vec.push(len);
}

```

This shows that we can use a mut reference after we've used the reference in a non-mut context.

Now consider this:

```rust
fn push_len(vec: &mut Vec<usize>) {
    vec.push(vec.len());
}

```

This should be exactly like `len_then_push()`, but instead it fails to compile because `vec` is borrowed mutably too early.

Here's this code on [play.rust-lang.org](http://play.rust-lang.org): [Rust Playground](https://is.gd/CYnjtF)

---

<div class="post-metadata">

**Author:** ![briansmith](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/briansmith/32/1306_2.png) [@briansmith](https://internals.rust-lang.org/u/briansmith)\
**Post date:** [June 15, 2017, 9:14am UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/43 "2017-06-15T09:14:28Z")

</div>

In the RFC, there is an example illustrating a proposal to expand your RFC’s proposal. Here’s an expanded version that I think captures more of the subtly:

```rust
fn len_then_push(tmp0: &mut Vec<usize>) {
    let tmp1 = tmp0.len(); // Used as shared.
    Vec::push(tmp0, tmp1); // Used as mutable.
}

fn main() {
   // Works fine today.
   let mut vec = vec![0];
   len_then_push(&mut vec);

   // Works fine today as only one reference to `vec` is used.
   {
     let tmp0 = &mut vec; // `vec` is mutably borrowed.
     let tmp1 = tmp0.len(); // Used as shared.
     Vec::push(tmp0, tmp1); // Used as mutable.
   }

   // Now: Fails to compile. Future: OK.
   vec.push(vec.len());

   // Now: Fails to compile. Future: OK.
   {
     let tmp0 = &mut vec; // Now: Mutable borrow. Future: reserve `vec`.
     let tmp1 = vec.len(); // shared borrow of vec. Now: fails. Future: OK.
     Vec::push(tmp0, tmp1); // Future: mutable borrow of `vec` is activated.
   }
}

```

---

<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 25, 2019, 8:27am UTC](https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588/44 "2019-03-25T08:27:39Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.

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