Rust DISCUSSION

Why can't a Rust struct hold a value and a reference to that same value?

Started by manh self-referential structRust lifetimesborrow checkermove semanticszero-copy parsing
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

Why can't a Rust struct hold a value and a reference to that same value?

manh Rust Forum
#1

I want a parser struct that owns its input and also keeps a slice into it: struct Parser { text: String, current: &str }. First the compiler demands a lifetime on current. After adding <'a>, my constructor, which creates the String and then sets current to &text[..], fails because text cannot be moved while it is borrowed, or because the function returns a value referencing data it owns.

The heap data of a String does not move when the struct moves, so why is this rejected, and how do people structure code like this?

Community replies 4

Re: Why can't a Rust struct hold a value and a reference to that same value?

#2

Every Rust value may be moved by a plain byte copy at any time: returned from a function, pushed into a Vec, assigned. There is no move constructor that could patch internal pointers. To build your struct you must first borrow the local text and then move text into the struct, and moving a value while it is borrowed is exactly what the borrow checker forbids.

You are right that the heap buffer stays put, but the type system does not distinguish "points into the heap data of" from "points at". With struct S { n: [u8; 16], r: &u8 } the reference really would dangle after a move. And even with a String, nothing would stop parser.text.push_str(...) from reallocating while current still pointed at the old buffer.

Re: Why can't a Rust struct hold a value and a reference to that same value?

#3

The simplest fix is to store positions rather than references: struct Parser { text: String, start: usize, end: usize }, and produce the slice on demand with fn current(&self) -> &str { &self.text[self.start..self.end] }.

The returned slice borrows self for as long as it is used, which the compiler can check. The cost is one bounds check per access, and the struct stays freely movable. Note that the offsets are byte offsets and must fall on UTF-8 character boundaries, otherwise the slice expression panics.

Re: Why can't a Rust struct hold a value and a reference to that same value?

#4

The second pattern is to split owner and view into two types. The caller owns the String and the parser only borrows it: struct Parser<'a> { text: &'a str, current: &'a str } with fn new(text: &'a str) -> Self. Usage is let input = std::fs::read_to_string(path)?; let mut p = Parser::new(&input);.

Now input is a separate variable that outlives the parser and cannot be moved or modified while the parser exists. Most zero-copy parsers are shaped this way. The limitation is that the parser cannot be returned from the function that owns input.

Re: Why can't a Rust struct hold a value and a reference to that same value?

#5

If owner and borrower really must travel together, for example in a long-lived struct or across threads, there are three routes. Shared ownership instead of references: keep an Rc<str> or Arc<str> plus offsets. Crates that generate self-referential structs behind a safe interface, such as ouroboros or self_cell. Or Pin, the mechanism async futures use; it guarantees that a value will not move again, but setting up the internal pointer still needs unsafe, so it is not for everyday application code.

Do not transmute the lifetime to 'static to get past the error. That compiles and then becomes undefined behaviour at the first reallocation.

TEP COMMUNITY