Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bump in struct #111

Open
MarcWeber opened this issue Apr 30, 2024 · 3 comments
Open

bump in struct #111

MarcWeber opened this issue Apr 30, 2024 · 3 comments

Comments

@MarcWeber
Copy link

I have this case:
I want to allocate binary strings with bumpalo and add them to a vec and hashmap to create a symbols table.
[u8] -> u32, u32 -> [u8].

Now the problem is that borrowing the bumpalo disallows adding to vec and hashmap ?

When putting symbols and positions into RefCell it feels like compiling, until fixing all errors then doesn't live long enough happens on #[self_referencing] line.

Not sure this is a bug. Is there a simple workaround I don't see ?

#[self_referencing]
pub struct Symbols {
  bumpalo: Bump,

  #[borrows(bumpalo)]
  #[covariant]
  pub symbols: Vec<&'this S>,

  #[borrows(bumpalo)]
  #[covariant]
  pub positions: HashMap<&'this S, Symbol>,
}

impl Symbols {

  // Constructor to create a new BSList
  pub fn new2() -> Self {
    Symbols::new(Bump::new(), |bump| Vec::with_capacity(100000), |bump| HashMap::new())
  }

  // Method to add a new BS to the list and update the HashMap
  pub fn symbol_new(&mut self, bs: &S) -> Symbol {
    let found = self.borrow_positions().borrow().get(bs).map(|x| x.clone());
    if let Some(position) = found {
      // println!("found\n");
      position
    } else {
      // If BS is new, add it to the list and update the position
      let position = self.borrow_symbols().len() as Symbol;
      // todo is it required to clone 2 times ?
      // let bs: BS = bs.into();
      let b = self.borrow_bumpalo().alloc_slice_clone(bs); // borrow immutable happens
      self.with_positions_mut(|x| x.insert(b, position));  // mutable borrow happens -> doesn't compile
      self.with_symbols_mut(|x| x.push(b));
      position
    }
  }
@kpreid
Copy link
Contributor

kpreid commented Apr 30, 2024

In order to borrow multiple fields at once you can use the generated .with_mut() method. This will compile:

    pub fn symbol_new(&mut self, bs: &S) -> Symbol {
        let found = self.borrow_positions().get(bs).cloned();
        if let Some(position) = found {
            position
        } else {
            // If BS is new, add it to the list and update the position
            let position = self.borrow_symbols().len() as Symbol;
            self.with_mut(|fields| {
                let b = fields.bumpalo.alloc_slice_clone(bs);
                fields.positions.insert(b, position);
                fields.symbols.push(b);
            });
            position
        }
    }

(The error isn't specific to ouroboros — you'd have the same problem with any other Rust code that tries to obtain mutable+mutable or mutable+immutable borrows through getter methods. In that situation, you must create a single method which returns the “split” borrows all at once.)

@MarcWeber
Copy link
Author

In fact the code I have had RefCell<Vec..> but will try this way. When using RefCell fields.symbols.borrow().len() fails because it cannot derive the type. Rust is like entangled Quantum Computing. If you change one thing it fails somewhere else.

@MarcWeber
Copy link
Author

symbol_new is called millions of times in my application. Is there a way to 'borrow_mut' all once only such as returning them as struct and add new_symbol like to that ? Or is the only way symbols.with_fun(fun) where with_fun uses with_mut then passing borrowed items to fun ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants