Question Details

No question body available.

Tags

rust borrow-checker

Answers (3)

Accepted Answer Available
Accepted Answer
November 29, 2025 Score: 3 Rep: 199 Quality: High Completeness: 50%

I see your points and it is definitely much simpler to just contain a Compiler struct within compile.

pub fn compile(source: &str) -> Result {
    let mut chunk = Chunk::new();
    let mut compiler  = Compiler::new(&mut chunk, source);

compiler.consume()?;

Ok(chunk) }

I was in the train of thought; all compiler functionality should be contained within the compiler but as cdhowie said, it's not idiomatic and more of an OOP concept.

December 4, 2025 Score: 1 Rep: 303,698 Quality: Medium Completeness: 80%

Is there anyway to tell the borrow checker this is safe, or should I just clone the chunk and return that?

No, because there's a lifetime issue:

  • The Compiler struct must outlive the call to compile.
  • Any references within the Compiler struct must outlive the Compiler itself.

As a result, you have a conflict: the lifetime of a local variable created in Compiler::compile will obviously NOT outlive the call to compile, and thus it cannot be stored in self.


As with almost everything in computer science, this can be solved by adding a layer of indirection. In this case, assuming that your Compiler struct contains valuable state -- possibly configuration, etc... -- then you need instead to introduce a temporary helper:

struct ChunkCompiler {
   chunk: &'chunk mut Chunk,
   compiler: &'compiler mut Compiler,
}

impl ChunkCompiler { fn new( chunk: &'chunk mut Chunk, compiler: &'compiler mut Compiler, ) -> Self { Self { chunk, compiler } } }

impl ChunkCompiler { fn compile(&mut self, source: &str) -> Result { todo!() } }

Then, you can define your Compiler method as:

impl Compiler {
    fn compile(&mut self, source: &str) -> Result {
        let mut chunk = Chunk::new();

ChunkCompiler::new(&mut chunk, self).compile(source)?;

Ok(chunk) }

Due to lifetime requirements, it's not unusual in Rust to split the state within a struct into 2 or 3 different "sub-structs" so as to be able to borrow them independently from one another.

November 29, 2025 Score: 0 Rep: 199 Quality: Low Completeness: 50%

I solved this by not using a reference in the struct and using the Option::take function to move it out.

self.scanner = Some(Scanner::new(source));
self.chunk = Some(Chunk::new());
...
self.scanner = None;
let chunk = self.chunk.take().expect("How'd the chunk disappear, something really bad happend ig?");
Ok(chunk)

This was pretty self-explanatory and I should've held off on asking this question but it would still be good to see how someone else would do this?