# Why does the borrow checker let me do this?

**URL:** https://users.rust-lang.org/t/why-does-the-borrow-checker-let-me-do-this/20135
**Category:** help
**Created:** [September 4, 2018, 4:36am UTC](https://users.rust-lang.org/t/why-does-the-borrow-checker-let-me-do-this/20135 "2018-09-04T04:36:52Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![yarrow](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/yarrow/32/6126_2.png) [@yarrow](https://users.rust-lang.org/u/yarrow)
#### Post date: [September 4, 2018, 4:36am UTC](https://users.rust-lang.org/t/why-does-the-borrow-checker-let-me-do-this/20135/1 "2018-09-04T04:36:52Z")

</div>

I recently ran into a situation where after tearing my hair out for some time saying "Why won't the borrow checker let me do this!?" I found a solution — but I'm now wondering "Why _does_ the borrow checker let me do this?"

Here's a simplified version: If `text` is a `&str` reference to the contents of a text file, we want to update a `HashSet` by inserting the lines of the file — but sometimes we want a `HashSet<&'a str>` of string slices borrowed from `text` and sometimes a `HashSet<String>` of heap-allocated copies of those slices. I defined a trait to allow implementation sharing. (In the larger problem we also want operations other than insertion.)

Two things puzzle me about the solution below. First, I'm not sure why it's OK to say

```rust
impl<'a> LineSet<'a> for VecSet { ... }

```

I'd been under the assumption that the `'a` in `LineSet<'a>` referred to the lifetime of the `LineSet`. Is it simply a lifetime parameter that can be used fairly arbitrarily in the trait and impl definitions?

Second, I wondered why it's OK to say:

```rust
impl<'a> LineSet<'a> for SliceSet<'a> {
    fn update_with(&mut self, line: &'a str) {
        self.insert(line);
    }
}

```

Here the lifetime of `line` could be longer than the lifetime of `self`, rather than identical to it. I'd expected to need this:

```rust
fn update_with<'b: 'a>(&mut self, line: &'b str)

```

This second version, explicitly specifying the larger lifetime, also works. Does the compiler desugar the first version into the second? What are the rules about such desugaring (if that's in fact what's happening)?

[Edit: I'd mistakenly used the playground version with `<'b: 'a>`, but meant to use the one without.)  
([Playground](https://play.rust-lang.org/?gist=5c5f9e07f5dc8750ce792b218952d4b9&version=stable&mode=debug&edition=2015))

```rust
use std::collections::HashSet;

trait LineSet<'a> {
    fn update_with(&mut self, line: &'a str);
    fn update_with_all(&mut self, text: &'a str) {
        for line in text.lines() {
            self.update_with(line);
        }
    }
}

type SliceSet<'a> = HashSet<&'a str>;
impl<'a> LineSet<'a> for SliceSet<'a> {
    fn update_with(&mut self, line: &'a str) {
        self.insert(line);
    }
}

type VecSet = HashSet<String>;
impl<'a> LineSet<'a> for VecSet {
    fn update_with(&mut self, line: &'a str) {
        self.insert(String::from(line));
    }
}

fn contents() -> String { String::from("abc\ndef\n") }

fn main() {
    let saved = contents();
    let mut slice_set = SliceSet::default();
    slice_set.update_with_all(saved.as_str()); // `saved` outlives `slice_set`
    // slice_set.update_with_all(contents().as_str()); // `contents().as_str()` does not
    println!("{:?}", slice_set);

    let mut vec_set = VecSet::default();
    vec_set.update_with_all(contents().as_str());
    println!("{:?}", vec_set);
}

```

---

<div class="post-metadata">

### Author: ![Wafflespeanut](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/wafflespeanut/32/1046_2.png) [@Wafflespeanut](https://users.rust-lang.org/u/Wafflespeanut)
#### Post date: [September 4, 2018, 6:40am UTC](https://users.rust-lang.org/t/why-does-the-borrow-checker-let-me-do-this/20135/2 "2018-09-04T06:40:57Z")

</div>

I'll try and address your questions.

> Is it simply a lifetime parameter that can be used fairly arbitrarily in the trait and impl definitions?

Here, `impl<'a>` defines a lifetime to be used in the block. In this, you're literally saying, "for some lifetime `'a` implement `LineSet` (belonging to that lifetime `'a`) for `VecSet`".

> Here the lifetime of `line` could be longer than the lifetime of `self`, rather than identical to it.

You're right that `line` could live longer than `self`, and that's totally fine. Imagine calling `update_with` method with a static string. The compiler tries to guess the lifetime (based on elision rules), and in your case, since `line` lives _atleast_ as long as `self`, we're good.

> This second version, explicitly specifying the larger lifetime, also works.

Same as above. `line` (of lifetime `'b`) lives at least as long as `self` (of lifetime `'a`).

> Does the compiler desugar the first version into the second?

I don't think so, because the lifetimes of `line` are different.

Now, coming to code:

> `slice_set.update_with_all(saved.as_str());`

Here, `saved` lives as long as the `main` function. And, `SliceSet` lives as long as the `main` function. So, it doesn't outlive.

> `slice_set.update_with_all(contents().as_str());`

In this case, `contents()` returns an owned `String`, and you're immediately getting the reference to it. This means the owned string will be dropped / destroyed after executing `update_with_all` (and the reference in `SliceSet` will then be dangling), which cannot be allowed, because `SliceSet` contents should live at least as long as itself.

This doesn't matter for `VecSet` because it only needs the string slice to live as long as `update_with_all`, which it does.

---

<div class="post-metadata">

### Author: ![jonh](https://avatars.discourse-cdn.com/v4/letter/j/dec6dc/32.png) [@jonh](https://users.rust-lang.org/u/jonh)
#### Post date: [September 4, 2018, 10:47am UTC](https://users.rust-lang.org/t/why-does-the-borrow-checker-let-me-do-this/20135/3 "2018-09-04T10:47:16Z")

</div>

The technical detail is [Variance](https://doc.rust-lang.org/nomicon/subtyping.html), but don't expect this to give much help explaining it in use.

> [@yarrow](#):
>
> the `'a` in `LineSet<'a>` referred to the lifetime of the `LineSet`

Avoid saying "lifetime of" it leads to confusion. This is saying `LineSet` is bound by the lifetime, there is a borrow that constrains how much the structure can move about.

---

<div class="post-metadata">

### Author: ![ExpHP](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/exphp/32/13145_2.png) [@ExpHP](https://users.rust-lang.org/u/ExpHP)
#### Post date: [September 4, 2018, 12:26pm UTC](https://users.rust-lang.org/t/why-does-the-borrow-checker-let-me-do-this/20135/4 "2018-09-04T12:26:21Z")

</div>

> [@jonh](#):
>
> Avoid saying “lifetime of” it leads to confusion. This is saying `LineSet` is bound by the lifetime, there is a borrow that constrains how much the structure can move about.

Indeed, I feel like this terminology leads to a lot of problems.

A lifetime is more like a set of read/write locks. It describes a set of objects which must not be touched in order for the data in some other object (the one with the lifetime) to remain valid.

- These locks are created whenever something is borrowed immutably or mutably in a function body.
- `T: 'a` means that, for as long as T exists, all of the locks in `'a` will be held.
- `'b: 'a` means that every read/write lock held by `'a` is also held by `'b`.

This much is easy to explain, but it is perhaps hard to perceive.

* * *

( **Edit from me 11 days in the future:** The second bullet is only half true, and the third bullet is _completely backwards!_ I'm currently writing a blog post that will beat this topic to death.)

---

<div class="post-metadata">

### Author: ![trentj](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/trentj/32/5690_2.png) [@trentj](https://users.rust-lang.org/u/trentj)
#### Post date: [September 4, 2018, 1:01pm UTC](https://users.rust-lang.org/t/why-does-the-borrow-checker-let-me-do-this/20135/5 "2018-09-04T13:01:27Z")

</div>

> [@Wafflespeanut](#):
>
> The compiler tries to guess the lifetime (based on elision rules), and in your case, `&mut self` automatically becomes `&'a mut self` and since `line` lives _atleast_ as long as `self` , we’re good.

Not in this case. If you replace `&mut self` with `&'a mut self`, the code won't compile. It's because `Self` is `HashSet<&'a str>` that `line` can be stored inside it. The elided lifetime is just the duration of the mutable borrow of `self`, which can be shorter than `'a`.

---

<div class="post-metadata">

### Author: ![Wafflespeanut](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/wafflespeanut/32/1046_2.png) [@Wafflespeanut](https://users.rust-lang.org/u/Wafflespeanut)
#### Post date: [September 4, 2018, 1:18pm UTC](https://users.rust-lang.org/t/why-does-the-borrow-checker-let-me-do-this/20135/6 "2018-09-04T13:18:57Z")

</div>

Oh right! Sorry, yes. That was wrong.

---

<div class="post-metadata">

### Author: ![yarrow](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/yarrow/32/6126_2.png) [@yarrow](https://users.rust-lang.org/u/yarrow)
#### Post date: [September 4, 2018, 4:03pm UTC](https://users.rust-lang.org/t/why-does-the-borrow-checker-let-me-do-this/20135/7 "2018-09-04T16:03:22Z")

</div>

> [@trentj](#):
>
> It’s because `Self` is `HashSet<&'a str>` that `line` can be stored inside it. The elided lifetime is just the duration of the mutable borrow of `self` , which can be shorter than `'a` .

Ah! That cleared up a lot of my confusion. In code like this:

```rust
let saved = contents();
let mut slice_set = SliceSet::default();
slice_set.update_with_all(saved.as_str());
println!("{:?}", slice_set);

```

the slices stored inside `slice_set` reference pieces of `saved`, and thus can be used as long as `saved` exists.

Thanks to everybody else too! @jonh's link to [Variance](https://doc.rust-lang.org/nomicon/subtyping.html) was particularly helpful. I'd skimmed it before, but this time I had the motivation to study it.

---

<div class="post-metadata">

### Author: ![steffahn](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steffahn/32/47569_2.png) [@steffahn](https://users.rust-lang.org/u/steffahn)
#### Post date: [January 12, 2023, 8:49am UTC](https://users.rust-lang.org/t/why-does-the-borrow-checker-let-me-do-this/20135/8 "2023-01-12T08:49:29Z")

</div>


