# Borrowing a variable in a thread from an endless loop inside main thread

**URL:** <https://internals.rust-lang.org/t/borrowing-a-variable-in-a-thread-from-an-endless-loop-inside-main-thread/6771>\
**Category:** compiler\
**Created:** [February 16, 2018, 1:29pm UTC](https://internals.rust-lang.org/t/borrowing-a-variable-in-a-thread-from-an-endless-loop-inside-main-thread/6771 "2018-02-16T13:29:40Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![yaa110](https://avatars.discourse-cdn.com/v4/letter/y/9f8e36/32.png) [@yaa110](https://internals.rust-lang.org/u/yaa110)\
**Post date:** [February 16, 2018, 1:29pm UTC](https://internals.rust-lang.org/t/borrowing-a-variable-in-a-thread-from-an-endless-loop-inside-main-thread/6771/1 "2018-02-16T13:29:41Z")

</div>

I posted the same question in [users](https://users.rust-lang.org/t/passing-a-borrowed-variable-to-a-thread-from-an-endless-loop/15468) forum, however, I could not find an acceptable answer (other than a workaround) for the question.

Please consider the following code:

```rust
use std::thread;
use std::sync::mpsc;
use std::sync::mpsc::Receiver;

fn handle(_rx:Receiver<(i32, &str)>) {
    // ...
}

fn main() {
    let s = String::from("Some text");
    
    let (tx, rx) = mpsc::channel();
    thread::spawn(move|| handle(rx));

    loop {
        // Endless loop
        tx.send((5, s.as_str())).unwrap();
    }
}

```

the code is not compiled with the following error:

```rust
error[E0597]: `s` does not live long enough
  --> a.rs:17:21
   |
17 | tx.send((5, s.as_str())).unwrap();
   | ^ does not live long enough
18 | }
19 | }
   | - borrowed value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

```

However, since `s` has been defined in the main function, it would live for the entire life of program (i.e. static lifetime).

rustc 1.23.0 (766bd11c8 2018-01-01)

---

<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:** [February 16, 2018, 4:57pm UTC](https://internals.rust-lang.org/t/borrowing-a-variable-in-a-thread-from-an-endless-loop-inside-main-thread/6771/2 "2018-02-16T16:57:13Z")

</div>

Rust doesn’t have any special concept of lifetimes for `main()`, so from perspective of the borrow checker it is a short-lived value. Rust doesn’t look at what your program actually does. It only enforces a few general rules.

To make the borrow checker happy:

- clone and send owned values
- use string literal
- wrap it in `Arc`
- look for string interning libraries

---

<div class="post-metadata">

**Author:** ![Centril](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/centril/32/3334_2.png) [@Centril](https://internals.rust-lang.org/u/Centril)\
**Post date:** [February 16, 2018, 8:56pm UTC](https://internals.rust-lang.org/t/borrowing-a-variable-in-a-thread-from-an-endless-loop-inside-main-thread/6771/3 "2018-02-16T20:56:22Z")

</div>

I recommend just using [`Box::leak`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.leak) to get a `&'static str`.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [February 16, 2018, 9:04pm UTC](https://internals.rust-lang.org/t/borrowing-a-variable-in-a-thread-from-an-endless-loop-inside-main-thread/6771/4 "2018-02-16T21:04:32Z")

</div>

Technically, you could even call `main()` again from some other context.

---

<div class="post-metadata">

**Author:** ![yaa110](https://avatars.discourse-cdn.com/v4/letter/y/9f8e36/32.png) [@yaa110](https://internals.rust-lang.org/u/yaa110)\
**Post date:** [February 16, 2018, 10:30pm UTC](https://internals.rust-lang.org/t/borrowing-a-variable-in-a-thread-from-an-endless-loop-inside-main-thread/6771/5 "2018-02-16T22:30:26Z")

</div>

I used `lazy_static` to initiate a static reference and sent it via channel sender.

@cuviper as you mentioned, calling `main` function from some other context would cause lifetime issues, however, I think **the recalling of `main` function** should be considered as an error in this case. But, in my example where no recalling of `main` function has occurred, the compilation error is not true.

---

<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:** [February 17, 2018, 10:33pm UTC](https://internals.rust-lang.org/t/borrowing-a-variable-in-a-thread-from-an-endless-loop-inside-main-thread/6771/6 "2018-02-17T22:33:04Z")

</div>

I don’t think the issue here is about recursive calls to main. Rather, I think the issue is that the spawned thread can continue to exist after main has returned. In this specific case, main never returns, but I guess the borrow-checker doesn’t know that, and I suspect teaching it enough about the CFG to know that would open its own can of worms.)

The existing thread library doesn’t model thread lifetimes explicitly, even when they aren’t detached; but you could imagine an improved one that does, such that `tx.send` could safely and soundly be applied to any object whose lifetime was provably shorter than the lifetime of `tx` itself. Unfortunately I am not clever enough with lifetime annotations to know what that would look like.

(I think recursive calls to main should be allowed, for the record. Rust’s zero-argument main makes it less useful than it might be in other languages, but if you can think of something to do with it, who am i to say no?)

---

<div class="post-metadata">

**Author:** ![hanna-kruppe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hanna-kruppe/32/6540_2.png) [@hanna-kruppe](https://internals.rust-lang.org/u/hanna-kruppe)\
**Post date:** [February 17, 2018, 10:51pm UTC](https://internals.rust-lang.org/t/borrowing-a-variable-in-a-thread-from-an-endless-loop-inside-main-thread/6771/7 "2018-02-17T22:51:08Z")

</div>

> [@zackw](#):
>
> I don’t think the issue here is about recursive calls to main. Rather, I think the issue is that the spawned thread can continue to exist after main has returned.

Yes. Even with the code given, `main` can panic (if `handle` closes the receiver, or even just if there's a bug in this part of the standard library). This panic will unwind out of `main`, dropping the string, and the thread can continue to run afterwards (concurrently to, or preempting, the little bit of work that remains to be done on the main thread after the string has been dropped), accessing deallocated memory. So the code above is, in fact, potentially memory unsafe!

Similar reasoning will apply to virtually every non-trivial piece of code. Even if it has been painstakingly ensured that it cannot actually panic (something that I believe to be completely impossible in practice for any piece of code larger than a few simple lines), the compiler cannot and should not have to prove absence of panics.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:29am UTC](https://internals.rust-lang.org/t/borrowing-a-variable-in-a-thread-from-an-endless-loop-inside-main-thread/6771/8 "2019-03-25T08:29:40Z")

</div>

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