#Trying to implement an Abstract Syntax Tree using a vec as a buffer, why do I get an error here?

19 messages · Page 1 of 1 (latest)

coral cypress
#
pub struct AbstractSyntaxTree {
    buffer: Rc<RefCell<Vec<RefCell<Expression>>>>,
    root: ExpressionIndex,
}

impl AbstractSyntaxTree {
    fn try_get_mut_expression_by_location(
        &mut self,
        location: ExpressionIndex,
    ) -> Option<RefMut<'_, Expression>> {
        Some(self.buffer.borrow_mut().get_mut(location)?.borrow_mut())
    }
}

The above code fails to compile with cannot return value referencing temporary value

  1. Is this really a temporary value? Shouldn't this reference be valid as long as the AbstractSyntaxTree struct exists?

  2. Would you implement this tree a different way?

eternal rune
#

no, the borrow_mut call creates a BorrowMut that gets dropped when the function returns

mint abyss
#

One of the things you give up when you use RefCell is the ability to return plain references to things that are within the cell, from outside (not having borrow()ed it yet).

coral cypress
#

Ok, so I realize that I don't need the buffer to be an Rc with RefCell so I changed it to

pub struct AbstractSyntaxTree<'a> {
    buffer: Vec<RefCell<Expression>>,
    root: ExpressionIndex,
    _phantom: PhantomData<&'a mut Expression>,
}

impl<'a> AbstractSyntaxTree<'a> {
    fn try_get_mut_expression_by_location(
        &mut self,
        location: ExpressionIndex,
    ) -> Option<RefMut<'a, Expression>> {
        Some(self.buffer.get(location)?.borrow_mut())
    }
}
mint abyss
#

that's not the right annotations

#

this should be correct:

pub struct AbstractSyntaxTree {
    buffer: Vec<RefCell<Expression>>,
    root: ExpressionIndex,
}

impl AbstractSyntaxTree {
    fn try_get_mut_expression_by_location<'a>(
        &'a mut self,
        location: ExpressionIndex,
    ) -> Option<RefMut<'a, Expression>> {
        Some(self.buffer.get(location)?.borrow_mut())
    }
}
#

and you can actually leave out the 'as entirely and put RefMut<'_, ... to implicitly refer to the self borrow lifetime

coral cypress
#

Wow, I thought I understood lifetimes until I tried doing something slightly difficult

mint abyss
#

the reason that that's the right lifetime is because the RefMut is a sort of borrow of the RefCell, which is part of self

#

it is very rarely a good idea to put a lifetime on a struct

#

(RefMut itself is one of those cases, but you're not implementing RefMut)

coral cypress
#

Seems like my gap in knowledge is around RefCell specifically

#

thanks for the help

manic gulch
mint abyss
#

this is more beginner advice

#

beginners try to build data structures out of references

#

where they should be owning the data

#

and in this particular case here, the lifetime had no reason to be on the struct at all

#

once you know well when to use &str, then you can reasonably make a struct with &'a str in it