How to turn &mut Parent into long-lived &mut child and later recover parent in Rust?
00:46 04 Jun 2026

I’m trying to model a typestate API where a mutable borrow of a parent object is temporarily narrowed into a mutable borrow of one child field, held across multiple method calls, then consumed to recover the parent state.

Simplified example:

struct Table {  
    columns: Vec,  
}  
  
struct Column {  
    data: String,  
    offsets: Vec,  
}  
  
struct RowBuilder<'a> {  
    table: &'a mut Table,  
    current_col: usize,  
}  
  
struct FieldBuilder<'a> {  
    table: &'a mut Table,  
    data: &'a mut String, // borrowed from table.columns[current_col].data  
    current_col: usize,  
} 

Desired API:

let mut row = table.begin_row();  
  
let mut field = row.begin_field();  
field.push_str("hello");  
field.push_str(" world");  
row = field.finish();  
  
let mut field = row.begin_field();  
field.push_str("next");  
row = field.finish();  
  
row.commit();

Conceptually this is linear:
&mut Table
-> RowBuilder
-> FieldBuilder borrowing one column's String
-> RowBuilder
-> commit

Only one state exists at a time. begin_field consumes RowBuilder; finish consumes FieldBuilder and returns RowBuilder.

But I don’t see how to represent FieldBuilder safely, because it wants both:

table: &'a mut Table
data: &'a mut String // sub-borrow from inside table 

Questions:

  1. Is there a safe idiomatic way to express this parent borrow → child borrow → parent borrow transformation?
  2. Can this be done with borrow splitting / split_at_mut, or does the long-lived child borrow require a self-referential pattern?
  3. Are crates like ouroboros or self_cell appropriate here?
  4. Is the usual solution to hide a raw pointer internally and expose a safe linear typestate API?

Minimal sketch of intended methods:

impl<'a> RowBuilder<'a> {
    fn begin_field(self) -> FieldBuilder<'a> {
        todo!()
    }
}

impl<'a> FieldBuilder<'a> {
    fn push_str(&mut self, s: &str) {
        self.data.push_str(s);
    }
  
    fn finish(self) -> RowBuilder<'a> {
        // write offset, advance current_col, recover row builder
        todo!()
    }
}
rust borrow-checker